https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120035
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |hubicka at gcc dot gnu.org --- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> --- Ah, so this is because the loop in question looks to us like do { ++i; if (i == 1ul << 60) break; ++i; } while (i < 1ul << 60); and we are confused about this case since we also do not know the initial value (which is set from the loop including the call). Analyzing # of iterations of loop 2 exit condition [i_18 + 2, + , 2] != 1152921504606846976 bounds on difference of bases: -1 ... 1152921504606846974 result: under assumptions (i_18 & 1) == 0 # of iterations (1152921504606846974 - i_18) /[ex] 2, bounded by 9223372036854775807 Analyzing # of iterations of loop 2 exit condition [i_18 + 1, + , 2] != 1152921504606846976 bounds on difference of bases: 0 ... 1152921504606846975 result: under assumptions (1152921504606846975 - i_18 & 1) == 0 # of iterations (1152921504606846975 - i_18) /[ex] 2, bounded by 9223372036854775807 cannot prove finiteness of loop 2 so we fail to "combine" the two exits assumptions when computing the upper bound of iterations for the loop. Also a side-effect of handling < as != - this also shows that when threadfull2 creates the second loop in the first place we fail to do so "conciously" and forget to copy over the flag that says that second loop is finite as well. The issue is that thread2 unrolls part of the loop body but that also seems like an enabler to split it out ... Isolated testcase for the niter issue: void f(unsigned i) { do { ++i; if (i == 1u << 28) break; ++i; } while (i != 1u <<28); }