https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84321
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Less reduced testcase so that it is valid: int c; void foo (int *a, int b) { int e; if (b == 1) return -1; for (e = 0; e < (b & ~7); e += 8) ; for (++e; e < b;) c = a[e]; } This is because the range info and nonzero bits improvements improve just gradually and improvements on nonzero bits don't have immediate effect on the min/max. We initially have: # RANGE [-2147483648, 2147483647] NONZERO 4294967288 # e_11 = PHI <e_6(4)> # RANGE [-2147483648, 2147483647] NONZERO 4294967289 e_13 = e_11 + 1; i.e. basically all range, but 0xfffffff8 and 0xfffffff9 masks. Then vrp1 improves that to: # RANGE [0, 2147483647] NONZERO 2147483640 # e_11 = PHI <e_6(4)> # RANGE ~[-2147483647, 0] NONZERO 4294967289 e_13 = e_11 + 1; which is conservatively correct, but not perfect, because of the 0x7fffffff8 nonzero mask on the PHI guarantees that the actual range must be [0, 2147483640]. And because e_11 is never INT_MAX, e_11 + 1 will never be INT_MIN. Later on ccp3 improves it further: # RANGE [0, 2147483647] NONZERO 2147483640 # e_18 = PHI <e_12(4), 0(3)> # RANGE ~[-2147483647, 0] NONZERO 2147483641 e_13 = e_18 + 1; but just the nonzero mask. So, while it would be nice to optimize this better, the asserts in intersect_range_with_nonzero_bits are just wrong, just punt (return VR_UNDEFINED) in those cases.