commit 71454637909401501ec0fa268f83db0bc8ffbc03 Author: Bin Cheng Date: Fri May 28 16:49:54 2021 +0800 Fix overflow check in simplifying exit cond comparing two IVs. We should also check that iv1.step - iv2.step doesn't overflow, in addition to overflowness of the two IVs. gcc: PR tree-optimization/100740 * tree-ssa-loop-niter.c (number_of_iterations_cond): Check overflowness for subtract operation of the two IVs. gcc/testsuite: * gcc.c-torture/execute/pr100740.c diff --git a/gcc/testsuite/gcc.c-torture/execute/pr100740.c b/gcc/testsuite/gcc.c-torture/execute/pr100740.c new file mode 100644 index 00000000000..8fcdaffef3b --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr100740.c @@ -0,0 +1,11 @@ +/* PR tree-optimization/100740 */ + +unsigned a, b; +int main() { + unsigned c = 0; + for (a = 0; a < 2; a++) + for (b = 0; b < 2; b++) + if (++c < a) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 325bd978609..45c8d99c43d 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -1782,7 +1782,9 @@ number_of_iterations_cond (class loop *loop, provided that either below condition is satisfied: a) the test is NE_EXPR; - b) iv0.step - iv1.step is integer and iv0/iv1 don't overflow. + b) no overlfow happens during simplification; + - iv0 and iv1 don't overflow. + - iv0.step - iv1.step is integer and doesn't overflow. This rarely occurs in practice, but it is simple enough to manage. */ if (!integer_zerop (iv0->step) && !integer_zerop (iv1->step)) @@ -1790,14 +1792,27 @@ number_of_iterations_cond (class loop *loop, tree step_type = POINTER_TYPE_P (type) ? sizetype : type; tree step = fold_binary_to_constant (MINUS_EXPR, step_type, iv0->step, iv1->step); + if (code != NE_EXPR) + { + if (TREE_CODE (step) != INTEGER_CST) + return false; + + if (!iv0->no_overflow || !iv1->no_overflow) + return false; + + bool wrap_p = TYPE_OVERFLOW_WRAPS (step_type); + if (wrap_p) + { + tree t = fold_binary_to_constant (GE_EXPR, step_type, + iv0->step, iv1->step); + wrap_p = integer_zerop (t); + } + if (wrap_p) + return false; + } /* No need to check sign of the new step since below code takes care of this well. */ - if (code != NE_EXPR - && (TREE_CODE (step) != INTEGER_CST - || !iv0->no_overflow || !iv1->no_overflow)) - return false; - iv0->step = step; if (!POINTER_TYPE_P (type)) iv0->no_overflow = false;