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