https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114041
--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Reduced testcase: unsigned a[24], b[24]; __attribute__((noipa)) unsigned foo (unsigned _BitInt(4) x) { for (int i = 0; i < 24; ++i) a[i] = i; unsigned e = __builtin_stdc_bit_ceil (x); for (int i = 0; i < 24; ++i) b[i] = i; return e; } int main () { if (foo (0) != 1) __builtin_abort (); } I have to confirm Andrew's comment, before the graphite dump there was if (x_14(D) > 1) goto <bb 5>; [59.00%] else goto <bb 11>; [41.00%] <bb 11> [local count: 17609365]: goto <bb 6>; [100.00%] <bb 5> [local count: 25340307]: _2 = x_14(D) + 15; _3 = (unsigned int) _2; _4 = __builtin_clz (_3); _5 = 31 - _4; _6 = 2 << _5; iftmp.1_15 = (unsigned int) _6; <bb 6> [local count: 42949672]: # iftmp.1_10 = PHI <iftmp.1_15(5), 1(11)> This isn't part of any kind of loop, it is in between 2 different loops. Graphite hoists some of the statements to bb 2 where it is unconditional: _32 = x_14(D) + 15; _33 = (unsigned int) _32; the rest of it remains after the first loop, but is now unconditional: <bb 18> [count: 0]: _47 = 1; _31 = __builtin_clz (_33); _34 = 31 - _31; _35 = 2 << _34; iftmp.1_36 = (unsigned int) _35; _48 = iftmp.1_36; iftmp.1_37 = _48; In the testcase x is 0, so __builtin_stdc_bit_ceil returns 1, but when we take the > 1 path, it is 2 << (31 - 24) instead. The above feels like what ifcvt would do, if that _47 in there stands for one of the phi arguments and _48 for the other. Except __builtin_clz invokes UB when run on 0 (which is one of the reasons why it was guarded) and there is no conditional merging at the end.