summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-niter.c
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2004-11-22 21:33:47 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2004-11-22 21:33:47 +0000
commit9a73db25af4324ec736aba56a4f23a057c0bec21 (patch)
treed8660e4627f3ddc5b8cbe84ddc41e85ff94cac90 /gcc/tree-ssa-loop-niter.c
parent2800f0cbc2e531ce45b9932e3c9cb580ba6c4a2b (diff)
downloadgcc-9a73db25af4324ec736aba56a4f23a057c0bec21.tar.gz
PR tree-optimization/18529
* fold-const.c (fold_to_nonsharp_ineq_using_bound): New function. (simple_operand_p): Use STRIP_NOPS. Consider SSA names simple. (fold): Call fold_to_nonsharp_ineq_using_bound. * tree-ssa-loop-niter.c (simplify_replace_tree): New function. (number_of_iterations_cond): Fold the expressions before futher processing. (tree_simplify_using_condition): Handle case when cond or expr is an EQ_EXPR specially. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@91031 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r--gcc/tree-ssa-loop-niter.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 3d4d4c0dec4..c83113430bc 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -372,12 +372,12 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
if (zero_p (step0))
{
- base0 = build2 (PLUS_EXPR, type, base0, delta);
+ base0 = fold (build2 (PLUS_EXPR, type, base0, delta));
base0 = fold (build2 (MINUS_EXPR, type, base0, step));
}
else
{
- base1 = build2 (MINUS_EXPR, type, base1, delta);
+ base1 = fold (build2 (MINUS_EXPR, type, base1, delta));
base1 = fold (build2 (PLUS_EXPR, type, base1, step));
}
@@ -555,6 +555,41 @@ simplify_using_outer_evolutions (struct loop *loop, tree expr)
return expr;
}
+/* Substitute NEW for OLD in EXPR and fold the result. */
+
+static tree
+simplify_replace_tree (tree expr, tree old, tree new)
+{
+ unsigned i, n;
+ tree ret = NULL_TREE, e, se;
+
+ if (!expr)
+ return NULL_TREE;
+
+ if (expr == old
+ || operand_equal_p (expr, old, 0))
+ return unshare_expr (new);
+
+ if (!EXPR_P (expr))
+ return expr;
+
+ n = TREE_CODE_LENGTH (TREE_CODE (expr));
+ for (i = 0; i < n; i++)
+ {
+ e = TREE_OPERAND (expr, i);
+ se = simplify_replace_tree (e, old, new);
+ if (e == se)
+ continue;
+
+ if (!ret)
+ ret = copy_node (expr);
+
+ TREE_OPERAND (ret, i) = se;
+ }
+
+ return (ret ? fold (ret) : expr);
+}
+
/* Tries to simplify EXPR using the condition COND. Returns the simplified
expression (or EXPR unchanged, if no simplification was possible).*/
@@ -603,6 +638,51 @@ tree_simplify_using_condition (tree cond, tree expr)
return expr;
}
+ /* In case COND is equality, we may be able to simplify EXPR by copy/constant
+ propagation, and vice versa. Fold does not handle this, since it is
+ considered too expensive. */
+ if (TREE_CODE (cond) == EQ_EXPR)
+ {
+ e0 = TREE_OPERAND (cond, 0);
+ e1 = TREE_OPERAND (cond, 1);
+
+ /* We know that e0 == e1. Check whether we cannot simplify expr
+ using this fact. */
+ e = simplify_replace_tree (expr, e0, e1);
+ if (zero_p (e) || nonzero_p (e))
+ return e;
+
+ e = simplify_replace_tree (expr, e1, e0);
+ if (zero_p (e) || nonzero_p (e))
+ return e;
+ }
+ if (TREE_CODE (expr) == EQ_EXPR)
+ {
+ e0 = TREE_OPERAND (expr, 0);
+ e1 = TREE_OPERAND (expr, 1);
+
+ /* If e0 == e1 (EXPR) implies !COND, then EXPR cannot be true. */
+ e = simplify_replace_tree (cond, e0, e1);
+ if (zero_p (e))
+ return e;
+ e = simplify_replace_tree (cond, e1, e0);
+ if (zero_p (e))
+ return e;
+ }
+ if (TREE_CODE (expr) == NE_EXPR)
+ {
+ e0 = TREE_OPERAND (expr, 0);
+ e1 = TREE_OPERAND (expr, 1);
+
+ /* If e0 == e1 (!EXPR) implies !COND, then EXPR must be true. */
+ e = simplify_replace_tree (cond, e0, e1);
+ if (zero_p (e))
+ return boolean_true_node;
+ e = simplify_replace_tree (cond, e1, e0);
+ if (zero_p (e))
+ return boolean_true_node;
+ }
+
/* Check whether COND ==> EXPR. */
notcond = invert_truthvalue (cond);
e = fold (build2 (TRUTH_OR_EXPR, boolean_type_node,