Closed
Description
Consider this simple function:
void anti(int *A, int x, unsigned N, unsigned M) {
for (unsigned m = 0; m < M; ++m)
for (unsigned i = 0U; i < N - 1; ++i) {
A[i] = A[i + 1] + x;
}
}
LoopInterchange currently kicks in on this loop and turns it into:
void anti(int *A, int x, unsigned N, unsigned M) {
for (unsigned i = 0U; i < N - 1; ++i)
for (unsigned m = 0; m < M; ++m) {
A[i] = A[i + 1] + x;
}
}
Which is apparently wrong.
To further illustrate the problem, one can run the function with this main
function:
int main(int argc, char **argv) {
int A[5] = {1, 2, 3, 4, 5};
anti(A, argc + 2, 5, 3);
for (unsigned i = 0U; i < 5; ++i) {
printf(" %d", A[i]);
}
printf("\n");
return 0;
}
The -O0
program (w/ argc = 1) prints out " 13 14 11 8 5" while the incorrectly interchanged program prints " 5 6 7 8 5", hence the miscompile.
The culprit of this problem comes from DependenceAnalysis, which provides a direction vector (between A[i]
& A[i + 1]
) of "[S <]" in this case, but I think it really should yield "[S >]" because we have an anti-dependency here. LoopInterchange should be able to stop doing any optimization when it sees "[S >]" as it violates the legality.