https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69224
--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- Ok, so we have for (int j = 0; j < s->d - 1; j++) { if ((c[i] >= s->x[j]) && (c[i] <= s->x[j + 1])) { b[2*j][i] = s->x[j]; break; } } and we can conclude j is in [0, 4] because of the c[i] >= s->x[j] check. But we can _not_ conclude it is in [0, 3] because of the short-circuited c[i] <= s->x[j+1] check. So we're left with if (c[4] >= s->x[4]) { if (c[5] <= s->x[j + 1]) { ... } } in the last iteration. The only issue is that we warn "is above array bounds" rather than "may be" (well, if the access is executed then it _is_ above array bounds, we never warn "maybe", all array-bound warnigns are "maybe" in some way, unless in main() and always executable). So I think we can't do anything here but not optimize (completely peel). The issue is that usually VRP doesn't warn if it gets a range for the access that is [0, 5] because its ranges are conservative and that would result in way too many diagnostics. Now the complete peeling makes the ranges very precise (single element) and we get those false positive warnings. Fact is that at runtime unless s->d is "proper" (I guess it's 5) the access may be out of bounds.