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/fold-const.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/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 68 |
1 files changed, 63 insertions, 5 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0c1a3d587c5..611ac145093 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) |