diff options
author | Zdenek Dvorak <dvorakz@suse.cz> | 2004-11-22 22:33:47 +0100 |
---|---|---|
committer | Zdenek Dvorak <rakdver@gcc.gnu.org> | 2004-11-22 21:33:47 +0000 |
commit | 1d481ba83c705072441d4a3c52902c4e3573069f (patch) | |
tree | d8660e4627f3ddc5b8cbe84ddc41e85ff94cac90 /gcc | |
parent | 392cd098c5d7aa57b0a5ae934f8ee0ce9945130c (diff) | |
download | gcc-1d481ba83c705072441d4a3c52902c4e3573069f.zip gcc-1d481ba83c705072441d4a3c52902c4e3573069f.tar.gz gcc-1d481ba83c705072441d4a3c52902c4e3573069f.tar.bz2 |
re PR tree-optimization/18529 (When the lower bound of a loop is non-constant we cannot find the number of iterations)
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.
From-SVN: r91031
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/fold-const.c | 68 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 84 |
3 files changed, 157 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d94b75d..2c974a0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2004-11-22 Zdenek Dvorak <dvorakz@suse.cz> + + 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. + 2004-11-22 Daniel Berlin <dberlin@dberlin.org> * tree-ssa.c (verify_ssa): SSA_OP_ALL_USES should be diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0c1a3d5..611ac14 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -3424,13 +3424,10 @@ static int simple_operand_p (tree exp) { /* Strip any conversions that don't change the machine mode. */ - while ((TREE_CODE (exp) == NOP_EXPR - || TREE_CODE (exp) == CONVERT_EXPR) - && (TYPE_MODE (TREE_TYPE (exp)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) - exp = TREE_OPERAND (exp, 0); + STRIP_NOPS (exp); return (CONSTANT_CLASS_P (exp) + || TREE_CODE (exp) == SSA_NAME || (DECL_P (exp) && ! TREE_ADDRESSABLE (exp) && ! TREE_THIS_VOLATILE (exp) @@ -6180,6 +6177,51 @@ try_move_mult_to_index (tree type, enum tree_code code, tree addr, tree mult) return build1 (ADDR_EXPR, type, ret); } + +/* Fold A < X && A + 1 > Y to A < X && A >= Y. Normally A + 1 > Y + means A >= Y && A != MAX, but in this case we know that + A < X <= MAX. INEQ is A + 1 > Y, BOUND is A < X. */ + +static tree +fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound) +{ + tree a, typea, type = TREE_TYPE (ineq), a1, diff, y; + + if (TREE_CODE (bound) == LT_EXPR) + a = TREE_OPERAND (bound, 0); + else if (TREE_CODE (bound) == GT_EXPR) + a = TREE_OPERAND (bound, 1); + else + return NULL_TREE; + + typea = TREE_TYPE (a); + if (!INTEGRAL_TYPE_P (typea) + && !POINTER_TYPE_P (typea)) + return NULL_TREE; + + if (TREE_CODE (ineq) == LT_EXPR) + { + a1 = TREE_OPERAND (ineq, 1); + y = TREE_OPERAND (ineq, 0); + } + else if (TREE_CODE (ineq) == GT_EXPR) + { + a1 = TREE_OPERAND (ineq, 0); + y = TREE_OPERAND (ineq, 1); + } + else + return NULL_TREE; + + if (TREE_TYPE (a1) != typea) + return NULL_TREE; + + diff = fold (build2 (MINUS_EXPR, typea, a1, a)); + if (!integer_onep (diff)) + return NULL_TREE; + + return fold (build2 (GE_EXPR, type, a, y)); +} + /* Perform constant folding and related simplification of EXPR. The related simplifications include x*1 => x, x*0 => 0, etc., and application of the associative law. @@ -8023,6 +8065,22 @@ fold (tree expr) && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)) return omit_one_operand (type, integer_zero_node, arg0); + /* A < X && A + 1 > Y ==> A < X && A >= Y. Normally A + 1 > Y + means A >= Y && A != MAX, but in this case we know that + A < X <= MAX. */ + + if (!TREE_SIDE_EFFECTS (arg0) + && !TREE_SIDE_EFFECTS (arg1)) + { + tem = fold_to_nonsharp_ineq_using_bound (arg0, arg1); + if (tem) + return fold (build2 (code, type, tem, arg1)); + + tem = fold_to_nonsharp_ineq_using_bound (arg1, arg0); + if (tem) + return fold (build2 (code, type, arg0, tem)); + } + truth_andor: /* We only do these simplifications if we are optimizing. */ if (!optimize) diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 3d4d4c0..c831134 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, |