This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [patch] for PR 18529
Hello,
here is the new version of the patch, with subst renamed and the
a == b && something transformation moved out of fold.
Zdenek
PR tree-optimization/18529
* fold-const.c (simplify_replace_tree,
fold_to_nonsharp_ineq_using_bound): New functions.
(simple_operand_p): Use STRIP_NOPS. Consider SSA names simple.
(fold): Call fold_to_nonsharp_ineq_using_bound.
* tree-ssa-loop-niter.c (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.
* tree.h (simplify_replace_tree): Declare.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.475
diff -c -3 -p -r1.475 fold-const.c
*** fold-const.c 18 Nov 2004 12:09:36 -0000 1.475
--- fold-const.c 19 Nov 2004 11:19:47 -0000
*************** eval_subst (tree arg, tree old0, tree ne
*** 2833,2838 ****
--- 2833,2870 ----
return arg;
}
}
+
+ /* Substitute NEW for OLD in EXPR and fold the result. */
+
+ tree
+ simplify_replace_tree (tree expr, tree old, tree new)
+ {
+ unsigned i, n;
+ tree ret = NULL_TREE, e, se;
+
+ 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);
+ }
/* Return a tree for the case when the result of an expression is RESULT
converted to TYPE and OMITTED was previously an operand of the expression
*************** static int
*** 3424,3436 ****
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);
return (CONSTANT_CLASS_P (exp)
|| (DECL_P (exp)
&& ! TREE_ADDRESSABLE (exp)
&& ! TREE_THIS_VOLATILE (exp)
--- 3456,3465 ----
simple_operand_p (tree exp)
{
/* Strip any conversions that don't change the machine mode. */
! STRIP_NOPS (exp);
return (CONSTANT_CLASS_P (exp)
+ || TREE_CODE (exp) == SSA_NAME
|| (DECL_P (exp)
&& ! TREE_ADDRESSABLE (exp)
&& ! TREE_THIS_VOLATILE (exp)
*************** try_move_mult_to_index (tree type, enum
*** 6180,6185 ****
--- 6209,6260 ----
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, 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;
+
+ if (!operand_equal_p (a1,
+ build2 (PLUS_EXPR, typea, a,
+ build_int_cst_type (typea, 1)), 0))
+ 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.
*************** fold (tree expr)
*** 8023,8028 ****
--- 8098,8119 ----
&& 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)
Index: tree-ssa-loop-niter.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-niter.c,v
retrieving revision 2.16
diff -c -3 -p -r2.16 tree-ssa-loop-niter.c
*** tree-ssa-loop-niter.c 15 Nov 2004 00:18:33 -0000 2.16
--- tree-ssa-loop-niter.c 19 Nov 2004 11:19:47 -0000
*************** number_of_iterations_cond (tree type, tr
*** 372,383 ****
if (zero_p (step0))
{
! base0 = 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 (PLUS_EXPR, type, base1, step));
}
--- 372,383 ----
if (zero_p (step0))
{
! base0 = fold (build2 (PLUS_EXPR, type, base0, delta));
base0 = fold (build2 (MINUS_EXPR, type, base0, step));
}
else
{
! base1 = fold (build2 (MINUS_EXPR, type, base1, delta));
base1 = fold (build2 (PLUS_EXPR, type, base1, step));
}
*************** tree_simplify_using_condition (tree cond
*** 603,608 ****
--- 603,653 ----
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,
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.657
diff -c -3 -p -r1.657 tree.h
*** tree.h 17 Nov 2004 22:06:00 -0000 1.657
--- tree.h 19 Nov 2004 11:19:47 -0000
*************** extern bool tree_swap_operands_p (tree,
*** 3540,3545 ****
--- 3540,3546 ----
extern enum tree_code swap_tree_comparison (enum tree_code);
extern bool ptr_difference_const (tree, tree, HOST_WIDE_INT *);
+ extern tree simplify_replace_tree (tree, tree, tree);
/* In builtins.c */
extern tree fold_builtin (tree, bool);