https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121592
--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- Confirmed also on x86-64 with -O2 [-fwrapv]. But I'll note that for (unsigned char u = 2; u < (unsigned char)m[r] - 196; u += -254) with m[0] == -12326 should never be entered? (unsigned char)-12326 - 196 is -158, and the comparison should be carried out in integer type(?) Reduced testcase which behaves differently for -O[01] vs. -O2, no vectorization happening. unsigned short a; char b; short m[24]; unsigned char p[24][24][24]; unsigned q[4][24]; static void __attribute__((noipa)) c() { for (long r = 0; r < 3; r = 7) for (unsigned s = 0; s < 4; s = ~02) for (unsigned char u = 2; u < (unsigned char)m[r] - 196; u += -254) for (int w = 0; w < 24; w += 2) { a += p[1][u][1] ?: m[s]; b = q[u + 1][s]; } } int main() { for (int r = 0; r < 24; ++r) m[r] = -12326; for (int r = 0; r < 4; ++r) for (int s = 0; s < 4; ++s) for (int t = 0; t < 4; ++t) p[r][s][t] = 1; c(); if (a != 45060 || b != 0) __builtin_abort (); } Interestingly the C frontend emits if ((int) u < (int) (unsigned char) *(m + (sizetype) ((long unsigned int) r * 2)) + -196) goto <D.2978>; else goto <D.2972>; which looks OK (and expected). We do t.c:10:35: optimized: loop turned into non-loop; it never loops to the 'u' loop. That said, I did confirm that at -O0 we do enter the u and w loop bodies - which is unexpected to me. I'm confused. 2 is not less than -158!?