aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-niter.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r--gcc/tree-ssa-loop-niter.c195
1 files changed, 63 insertions, 132 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 39d6807..0309f4a 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1926,7 +1926,7 @@ expand_simple_operations (tree expr, tree stop)
expression (or EXPR unchanged, if no simplification was possible). */
static tree
-tree_simplify_using_condition_1 (tree cond, tree expr)
+tree_simplify_using_condition_1 (tree cond, tree expr, tree stop)
{
bool changed;
tree e, te, e0, e1, e2, notcond;
@@ -1941,17 +1941,17 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
{
changed = false;
- e0 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 0));
+ e0 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 0), stop);
if (TREE_OPERAND (expr, 0) != e0)
changed = true;
- e1 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 1));
+ e1 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 1), stop);
if (TREE_OPERAND (expr, 1) != e1)
changed = true;
if (code == COND_EXPR)
{
- e2 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 2));
+ e2 = tree_simplify_using_condition_1 (cond, TREE_OPERAND (expr, 2), stop);
if (TREE_OPERAND (expr, 2) != e2)
changed = true;
}
@@ -2014,7 +2014,7 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
return boolean_true_node;
}
- te = expand_simple_operations (expr);
+ te = expand_simple_operations (expr, stop);
/* Check whether COND ==> EXPR. */
notcond = invert_truthvalue (cond);
@@ -2038,19 +2038,19 @@ tree_simplify_using_condition_1 (tree cond, tree expr)
the loop do not cause us to fail. */
static tree
-tree_simplify_using_condition (tree cond, tree expr)
+tree_simplify_using_condition (tree cond, tree expr, tree stop)
{
- cond = expand_simple_operations (cond);
+ cond = expand_simple_operations (cond, stop);
- return tree_simplify_using_condition_1 (cond, expr);
+ return tree_simplify_using_condition_1 (cond, expr, stop);
}
/* Tries to simplify EXPR using the conditions on entry to LOOP.
Returns the simplified expression (or EXPR unchanged, if no
- simplification was possible).*/
+ simplification was possible). */
-static tree
-simplify_using_initial_conditions (struct loop *loop, tree expr)
+tree
+simplify_using_initial_conditions (struct loop *loop, tree expr, tree stop)
{
edge e;
basic_block bb;
@@ -2082,7 +2082,7 @@ simplify_using_initial_conditions (struct loop *loop, tree expr)
gimple_cond_rhs (stmt));
if (e->flags & EDGE_FALSE_VALUE)
cond = invert_truthvalue (cond);
- expr = tree_simplify_using_condition (cond, expr);
+ expr = tree_simplify_using_condition (cond, expr, stop);
/* Break if EXPR is simplified to const values. */
if (expr && (integer_zerop (expr) || integer_nonzerop (expr)))
break;
@@ -4114,137 +4114,68 @@ loop_exits_before_overflow (tree base, tree step,
help of analyzed loop control IV. This is done only for IVs with
constant step because otherwise we don't have the information. */
if (TREE_CODE (step) == INTEGER_CST)
- for (civ = loop->control_ivs; civ; civ = civ->next)
- {
- enum tree_code code;
- tree stepped, extreme, civ_type = TREE_TYPE (civ->step);
-
- /* Have to consider type difference because operand_equal_p ignores
- that for constants. */
- if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (civ_type)
- || element_precision (type) != element_precision (civ_type))
- continue;
-
- /* Only consider control IV with same step. */
- if (!operand_equal_p (step, civ->step, 0))
- continue;
-
- /* Done proving if this is a no-overflow control IV. */
- if (operand_equal_p (base, civ->base, 0))
- return true;
-
- /* If this is a before stepping control IV, in other words, we have
-
- {civ_base, step} = {base + step, step}
-
- Because civ {base + step, step} doesn't overflow during loop
- iterations, {base, step} will not overflow if we can prove the
- operation "base + step" does not overflow. Specifically, we try
- to prove below conditions are satisfied:
-
- base <= UPPER_BOUND (type) - step ;;step > 0
- base >= LOWER_BOUND (type) - step ;;step < 0
-
- by proving the reverse conditions are false using loop's initial
- condition. */
- if (POINTER_TYPE_P (TREE_TYPE (base)))
- code = POINTER_PLUS_EXPR;
- else
- code = PLUS_EXPR;
+ {
+ tree stop = (TREE_CODE (base) == SSA_NAME) ? base : NULL;
- stepped = fold_build2 (code, TREE_TYPE (base), base, step);
- if (operand_equal_p (stepped, civ->base, 0))
- {
- if (tree_int_cst_sign_bit (step))
- {
- code = LT_EXPR;
- extreme = lower_bound_in_type (type, type);
- }
- else
- {
- code = GT_EXPR;
- extreme = upper_bound_in_type (type, type);
- }
- extreme = fold_build2 (MINUS_EXPR, type, extreme, step);
- e = fold_build2 (code, boolean_type_node, base, extreme);
- e = simplify_using_initial_conditions (loop, e);
- if (integer_zerop (e))
- return true;
+ for (civ = loop->control_ivs; civ; civ = civ->next)
+ {
+ enum tree_code code;
+ tree stepped, extreme, civ_type = TREE_TYPE (civ->step);
+ /* Have to consider type difference because operand_equal_p ignores
+ that for constants. */
+ if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (civ_type)
+ || element_precision (type) != element_precision (civ_type))
continue;
- }
-
- /* Similar to above, only in this case we have:
-
- {civ_base, step} = {(signed T)((unsigned T)base + step), step}
- && TREE_TYPE (civ_base) = signed T.
-
- We prove that below condition is satisfied:
-
- (signed T)((unsigned T)base + step)
- == (signed T)(unsigned T)base + step
- == base + step
- because of exact the same reason as above. This also proves
- there is no overflow in the operation "base + step", thus the
- induction variable {base, step} during loop iterations.
+ /* Only consider control IV with same step. */
+ if (!operand_equal_p (step, civ->step, 0))
+ continue;
- This is necessary to handle cases as below:
+ /* Done proving if this is a no-overflow control IV. */
+ if (operand_equal_p (base, civ->base, 0))
+ return true;
- int foo (int *a, signed char s, signed char l)
- {
- signed char i;
- for (i = s; i < l; i++)
- a[i] = 0;
- return 0;
- }
+ /* If this is a before stepping control IV, in other words, we have
- The variable I is firstly converted to type unsigned char,
- incremented, then converted back to type signed char. */
- if (!CONVERT_EXPR_P (civ->base) || TREE_TYPE (civ->base) != type)
- continue;
- e = TREE_OPERAND (civ->base, 0);
- if (TREE_CODE (e) != PLUS_EXPR
- || TREE_CODE (TREE_OPERAND (e, 1)) != INTEGER_CST
- || !operand_equal_p (step,
- fold_convert (type,
- TREE_OPERAND (e, 1)), 0))
- continue;
- e = TREE_OPERAND (e, 0);
- if (!CONVERT_EXPR_P (e) || !operand_equal_p (e, unsigned_base, 0))
- continue;
- e = TREE_OPERAND (e, 0);
- /* It may still be possible to prove no overflow even if condition
- "operand_equal_p (e, base, 0)" isn't satisfied here, like below
- example:
+ {civ_base, step} = {base + step, step}
- e : ssa_var ; unsigned long type
- base : (int) ssa_var
- unsigned_base : (unsigned int) ssa_var
+ Because civ {base + step, step} doesn't overflow during loop
+ iterations, {base, step} will not overflow if we can prove the
+ operation "base + step" does not overflow. Specifically, we try
+ to prove below conditions are satisfied:
- Unfortunately this is a rare case observed during GCC profiled
- bootstrap. See PR66638 for more information.
+ base <= UPPER_BOUND (type) - step ;;step > 0
+ base >= LOWER_BOUND (type) - step ;;step < 0
- For now, we just skip the possibility. */
- if (!operand_equal_p (e, base, 0))
- continue;
+ by proving the reverse conditions are false using loop's initial
+ condition. */
+ if (POINTER_TYPE_P (TREE_TYPE (base)))
+ code = POINTER_PLUS_EXPR;
+ else
+ code = PLUS_EXPR;
- if (tree_int_cst_sign_bit (step))
- {
- code = LT_EXPR;
- extreme = lower_bound_in_type (type, type);
- }
- else
- {
- code = GT_EXPR;
- extreme = upper_bound_in_type (type, type);
- }
- extreme = fold_build2 (MINUS_EXPR, type, extreme, step);
- e = fold_build2 (code, boolean_type_node, base, extreme);
- e = simplify_using_initial_conditions (loop, e);
- if (integer_zerop (e))
- return true;
- }
+ stepped = fold_build2 (code, TREE_TYPE (base), base, step);
+ if (operand_equal_p (stepped, civ->base, 0))
+ {
+ if (tree_int_cst_sign_bit (step))
+ {
+ code = LT_EXPR;
+ extreme = lower_bound_in_type (type, type);
+ }
+ else
+ {
+ code = GT_EXPR;
+ extreme = upper_bound_in_type (type, type);
+ }
+ extreme = fold_build2 (MINUS_EXPR, type, extreme, step);
+ e = fold_build2 (code, boolean_type_node, base, extreme);
+ e = simplify_using_initial_conditions (loop, e, stop);
+ if (integer_zerop (e))
+ return true;
+ }
+ }
+ }
return false;
}