https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65258
--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- There are of course two issues here - one VRP not optimizing away the dead code and unrolling creating the dead code in the first place (thus number of iteration analysis being not very precise). Number of iteration analysis has a hard time exercising SCEV here as that cannot handle division (generally such IVs are not affine, in this case the evolution of j/8 is not affine in the j loop). Now for the VRP issue it is forwprop that replaces the sequence of i-- with i = j/8 - 1, i = j/8 - 2, ... thereby making VRPs life hard with <bb 3>: i_9 = j_3 / 8; i_26 = i_9 + 4294967295; if (i_9 != 0) goto <bb 4>; else goto <bb 14>; <bb 4>: a[i_26] = 0; i_30 = i_9 + 4294967294; if (i_26 != 0) goto <bb 5>; else goto <bb 14>; <bb 5>: a[i_30] = 0; i_34 = i_9 + 4294967293; if (i_30 != 0) goto <bb 6>; else goto <bb 14>; where the assertion on i_26 != 0 doesn't help it improving the range for i_34 (which is based on i_9 again). Disabling forwprop2 fixes the warning and makes VRP1 do its job. It is match.pd:491 that does the transform. Of course I can write the problematic code in plain C as well so VRP should better deal with it somehow. We can "easily" do i_38 = i_53 + 4294967292; if (i_34 != 0) goto <bb 7>; else goto <bb 14>; <bb 7>: i_56 = ASSERT_EXPR <i_53, i_53 != 3>; a[i_38] = 0; i_42 = i_56 + 4294967291; if (i_38 != 0) goto <bb 8>; else goto <bb 14>; <bb 8>: i_57 = ASSERT_EXPR <i_56, i_56 != 4>; a[i_42] = 0; but then we'd still need an assert for i_42 as well which is quite backward. In fact the way VRP works makes this quite hard to do. For a "real" sophisticated VRP we'd walk the full dominator tree dominating each predicate to compute value-ranges for SSA names dominated by those predicates (but that's quadratic). That said - with the above we are down to a single warning (but the code is not removed). We are not able to simplify the last branch to false and the branch after gets UNDEFINED into the comparison so we can fold either way (we could put builtin_unreachable before that branch...). So - not sure if improving to t.c: In function 'main': t.c:8:3: warning: array subscript is above array bounds [-Warray-bounds] a[i] = 0; ^ is worth it.