https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128519

            Bug ID: 128519
           Summary: wrong code at -O1: SCEV widens a decreasing unsigned
                    short IV as no_overflow; loop exits one iteration
                    early since r17-5477
           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 s;
int n = 10;

int main(void)
{
  unsigned short v = 1;
  int i;
  for (i = 0; i < n; i++) {
    s = v;
    if (s > 25)
      break;
    v--;
  }
  printf("%d\n", i);
  return 0;
}

$ gcc -O0 t.c && ./a.out
2
$ gcc -O1 t.c && ./a.out
1

Expected 2: v goes 1, 0, 65535 (unsigned wrap), and 65535 > 25 stops the loop
at i == 2.

Cause: SCEV widens the unsigned short IV {1, +, -1} to {1, +,
65535}(no_overflow) in unsigned int. derive_simple_iv_with_niters
(tree-scalar-evolution.cc) computes the no-wrap bound with
get_niter_type_bound, which reads the step 65535 as -1, but the new chrec keeps
the zero-extended step 65535. ivcanon and cunroll then use 1 iteration instead
of 2.

First bad commit: r17-5477-gc34d17fe720.
Correct on 16.2. Wrong on trunk.

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