https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108419
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |aldyh at gcc dot gnu.org, | |jakub at gcc dot gnu.org --- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Slightly cleaned up testcase: static int b = 6, c; long d; short h, i, j; signed char k; void foo (void); short baz (int, int, int, int, int, int, int); short qux (unsigned short, int, char, long); short bar (short l, short m) { return l + m; } static signed char corge (void) { unsigned n; for (n = -10U; n >= 14; n = bar (n, 8)) { i = qux (b, 0, c, b); j = baz (i, b, d < j, 5, 7, 9, 5); k = 200 + n; h = k % 5; if (!h) foo (); } return n; } int main () { b || corge (); b = 1; } The loop iterates twice, with n -10U and -2U, in third iteration 6U fails the 6U >= 14 condition. In GCC 12 as well as in r13-439 and r13-440 the loop IV is # ivtmp.30_42 = PHI <ivtmp.30_34(8), 190(7)> and loop condition is ivtmp.30_34 = ivtmp.30_42 + 8; if (ivtmp.30_34 != 206) while trunk has 2 IVs: # RANGE [irange] unsigned int [38, 32767][4294934528, +INF] NONZERO 0xfffffffe # n_32 = PHI <n_30(8), 4294967286(7)> # RANGE [irange] unsigned int [1, +INF] # ivtmp_2 = PHI <ivtmp_43(8), 2(7)> and # RANGE [irange] unsigned short [30, +INF] NONZERO 0xfffe l.0_27 = (unsigned short) n_32; # RANGE [irange] unsigned short [0, 7][38, +INF] NONZERO 0xfffe _28 = l.0_27 + 8; # RANGE [irange] short int [-INF, 7][38, +INF] NONZERO 0xfffe _29 = (short int) _28; # RANGE [irange] unsigned int [0, 7][38, 32767][4294934528, +INF] NONZERO 0xfffffffe n_30 = (unsigned int) _29; ivtmp_43 = ivtmp_2 - 1; if (ivtmp_43 != 0) The r13-440 regression is in vrp2, previously we were able to determine that because ivtmp.30_42 is [190, 190][198, 198] then (signed char) of that is [-66, -66][-58, -58] and that % 5 is [-3, -3][-1, -1]. Folding statement: _24 = (signed char) ivtmp.30_42; - Loops range found for ivtmp.30_42: unsigned char [190, 198] and calculated range :unsigned char [190, 190][198, 205] -Global Exported: _24 = signed char [-66, -58] ... irange was : signed char [-66, -66][-58, -58] +Global Exported: _24 = signed char [-66, -58] Not folded Folding statement: k = _24; Not folded Folding statement: _25 = _24 % 5; -Global Exported: _25 = signed char [-3, -1] ... irange was : signed char [-3, -3][-1, -1] +Global Exported: _25 = signed char [-4, 0] is the first difference in the vrp2 dump between r13-439 and r13-440. The other major change is starting with r13-3486-g4c5b1160776382772 when ivopts uses the 2 IVs rather than one and the convoluted increment by 8. It is actually only a normal increment by 8 if n_32 is in [0, 32759][-32777U, -1U] but that is actually the case here. I think the ranger doesn't iterate, right? So is there any way that it would figure out the exact range for the IV?