https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128517
Bug ID: 128517
Summary: [14/15/16/17 Regression] wrong code at -O3
-march=x86-64-v3: niter drops the assumptions of all
exits of a vectorized early-break loop since r14-6822
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: jeffchen006 at gmail dot com
Target Milestone: ---
Target: x86_64-pc-linux-gnu
int printf(const char *, ...);
unsigned calls;
static unsigned rec(unsigned d, unsigned x)
{
calls++;
if (d == 0)
return 0;
rec(d - 1, (x ? 2 : calls) % (2 * d + 1));
return calls % 10 / (calls / (x | 1) | 1);
}
int main(void)
{
printf("%u\n", rec(7, 1));
return 0;
}
$ gcc -O0 -march=x86-64-v3 t.c && ./a.out
0
$ gcc -O3 -march=x86-64-v3 t.c && ./a.out
1
Expected 0: calls is 8 when the outer call returns, so the result is 8 % 10 /
(8 / 1 | 1) = 8 / 9 = 0.
Cause: the recursion becomes a loop with several exits, which is vectorized as
an early-break loop. The vectorizer checks only the main exit's niter
assumption, and then sets LOOP_C_FINITE. When LOOP_C_FINITE is set,
number_of_iterations_exit_assumptions (tree-ssa-loop-niter.cc) drops the
assumptions of every exit. But a loop can be finite because a different exit is
taken. So IVOPTs in the scalar epilogue uses wrong iteration counts for the
other exits.
First bad commit: r14-6822-g01f4251b877 (vectorization of loops with multiple
exits).
Correct on 12.5 and 13.4. Wrong on 14.3, 15.2 and 16.2. Trunk prints 0 here
because of an inlining change, but with rec(8, 1) trunk is also wrong (expected
1, prints 0).
Avoided by: -fno-tree-loop-vectorize, -fno-ivopts.
Tested: the test above and the trunk rec(8, 1) form; of 7522 testsuite files,
the asm changes only in the new tests and in
vect-early-break_145-pr126778_1.c/_2.c (scalar epilogue, 11 more lines); 57
early-break run tests pass. No bootstrap or make check yet.
UBSan and ASan are clean at -O0.
gcc version 17.0.0 20261029 (experimental), r17-5747-g85867b0c935,
x86_64-pc-linux-gnu