Description
This makes WidenIV::widenIVUse (IndVarSimplify.cpp) fail to widen narrow IV uses in some cases. The latter affects IndVarSimplify which may not eliminate narrow IV's when there actually exists such a possibility, thereby producing ineffective code.
When WidenIV::widenIVUse gets a NarrowUse such as {(-2 + %inc.lcssa),+,1}<nsw><%for.body3>, it first tries to get a wide recurrence for it via the getWideRecurrence call.
getWideRecurrence returns recurrence like this: {(sext i32 (-2 + %inc.lcssa) to i64),+,1}<nsw><%for.body3>.
Then a wide use operation is generated by cloneIVUser. The generated wide use is evaluated to {(-2 + (sext i32 %inc.lcssa to i64))<nsw>,+,1}<nsw><%for.body3>, which is different from the getWideRecurrence result. cloneIVUser sees the difference and returns nullptr.
This patch also fixes the broken LLVM tests by adding missing <nsw> entries introduced by the correction.
Minimal reproducer:
int foo(int a, int b, int c); int baz(); void bar() { int arr[20]; int i = 0; for (i = 0; i < 4; ++i) arr[i] = baz(); for (; i < 20; ++i) arr[i] = foo(arr[i - 4], arr[i - 3], arr[i - 2]); }
Clang command line:
clang++ -mllvm -debug -S -emit-llvm -O3 --target=aarch64-linux-elf test.cpp -o test.ir
Expected result:
The -mllvm -debug log shows that all the IV's for the second for loop have been eliminated.
Can you please add a comment here on why this is correct: