diff options
author | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-11-22 21:33:47 +0000 |
---|---|---|
committer | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-11-22 21:33:47 +0000 |
commit | 9a73db25af4324ec736aba56a4f23a057c0bec21 (patch) | |
tree | d8660e4627f3ddc5b8cbe84ddc41e85ff94cac90 /gcc/tree-ssa-loop-niter.c | |
parent | 2800f0cbc2e531ce45b9932e3c9cb580ba6c4a2b (diff) | |
download | gcc-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.c | 84 |
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, |