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

Reply via email to