summaryrefslogtreecommitdiff
path: root/gcc/fold-const.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/fold-const.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/fold-const.c')
-rw-r--r--gcc/fold-const.c68
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)