Split out from PR58143, /* { dg-do run } */ /* { dg-additional-options "-fstrict-overflow" } */ int a, b, c, d, e; int main () { for (b = 4; b > -30; b--) { e = a > (int)((unsigned int) __INT_MAX__ - (unsigned int) b); for (; c;) for (;;) { if (d) break; } } return 0; } is compiled to an infinite loop at -O3 by IVOPTs and VRP teaming up, rewriting (unsigned int) __INT_MAX__ - (unsigned int) b as signed arithmetic and then removing the loop exit test.
I will have a look.
rewrite_use_compare rewrites b.1_5 = (unsigned int) b.0_20; _6 = 2147483647 - b.1_5; _7 = (int) _6; _9 = _7 < pretmp_23; into _13 = 2147483647 - b.0_20; _9 = _13 < pretmp_23; here: /* The induction variable elimination failed; just express the original giv. */ comp = get_computation (data->current_loop, use, cand); using the candidate b.0_20 where already the affine form of the computation is wrong: { type = int offset = 2147483647 elements = { [0] = b.0_20 * -1 } } which is because the use induction variable for _7 is wrongly determined by simple_iv as { 2147483643, +, 1 } (but it has ->no_overflow == false but nothing in IVOPTs ever checks that which looks like a bug).
The following patch fixes this and the testcase. Index: gcc/tree-ssa-loop-ivopts.c =================================================================== --- gcc/tree-ssa-loop-ivopts.c (revision 203590) +++ gcc/tree-ssa-loop-ivopts.c (working copy) @@ -1084,6 +1084,13 @@ find_givs_in_stmt_scev (struct ivopts_da if (!simple_iv (loop, loop_containing_stmt (stmt), lhs, iv, true)) return false; + + /* If the induction variable invokes undefined behavior when it wraps + make sure it does not overflow. */ + if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs)) + && !iv->no_overflow) + return false; + iv->base = expand_simple_operations (iv->base); if (contains_abnormal_ssa_name_p (iv->base)
Err. Triggered by local changes in my tree.