From bd03c0848a46497cb991f1425c232ab1d70894cd Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Thu, 27 Mar 2008 09:17:43 +0000 Subject: [PATCH] fold-const.c (target.h): Include. 2008-03-27 Richard Guenther * fold-const.c (target.h): Include. (fold_comparison): Fold comparison of addresses of decls that bind locally or of constants. Consolidate address folding code. * tree-vrp.c (operand_less_p): Deal with non-INTEGER_CST results from fold_binary_to_constant. (compare_values_warnv): Likewise. * gcc.dg/fold-addr-1.c: New testcase. From-SVN: r133632 --- gcc/ChangeLog | 9 ++++ gcc/fold-const.c | 78 ++++++++++++++++++------------ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/fold-addr-1.c | 10 ++++ gcc/tree-vrp.c | 5 +- 5 files changed, 72 insertions(+), 34 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/fold-addr-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8eca39fde41..efe11979599 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2008-03-27 Richard Guenther + + * fold-const.c (target.h): Include. + (fold_comparison): Fold comparison of addresses of decls + that bind locally or of constants. Consolidate address folding code. + * tree-vrp.c (operand_less_p): Deal with non-INTEGER_CST + results from fold_binary_to_constant. + (compare_values_warnv): Likewise. + 2008-03-27 Andrew Pinski PR middle-end/35429 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 896a9838e14..a7dcfc3ff90 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see #include "rtl.h" #include "expr.h" #include "tm_p.h" +#include "target.h" #include "toplev.h" #include "intl.h" #include "ggc.h" @@ -8483,11 +8484,12 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1) HOST_WIDE_INT bitsize, bitpos0 = 0, bitpos1 = 0; enum machine_mode mode; int volatilep, unsignedp; - bool indirect_base0 = false; + bool indirect_base0 = false, indirect_base1 = false; /* Get base and offset for the access. Strip ADDR_EXPR for get_inner_reference, but put it back by stripping INDIRECT_REF - off the base object if possible. */ + off the base object if possible. indirect_baseN will be true + if baseN is not an address but refers to the object itself. */ base0 = arg0; if (TREE_CODE (arg0) == ADDR_EXPR) { @@ -8511,24 +8513,19 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1) base1 = get_inner_reference (TREE_OPERAND (arg1, 0), &bitsize, &bitpos1, &offset1, &mode, &unsignedp, &volatilep, false); - /* We have to make sure to have an indirect/non-indirect base1 - just the same as we did for base0. */ - if (TREE_CODE (base1) == INDIRECT_REF - && !indirect_base0) + if (TREE_CODE (base1) == INDIRECT_REF) base1 = TREE_OPERAND (base1, 0); - else if (!indirect_base0) - base1 = NULL_TREE; + else + indirect_base1 = true; } else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR) { base1 = TREE_OPERAND (arg1, 0); offset1 = TREE_OPERAND (arg1, 1); } - else if (indirect_base0) - base1 = NULL_TREE; /* If we have equivalent bases we might be able to simplify. */ - if (base0 && base1 + if (indirect_base0 == indirect_base1 && operand_equal_p (base0, base1, 0)) { /* We can fold this expression to a constant if the non-constant @@ -8583,6 +8580,44 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1) return fold_build2 (code, type, offset0, offset1); } } + /* For non-equal bases we can simplify if they are addresses + of local binding decls or constants. */ + else if (indirect_base0 && indirect_base1 + /* We know that !operand_equal_p (base0, base1, 0) + because the if condition was false. */ + && TREE_CODE (arg0) == ADDR_EXPR + && TREE_CODE (arg1) == ADDR_EXPR + && ((DECL_P (base0) + && (targetm.binds_local_p (base0) + || CONSTANT_CLASS_P (base1))) + || CONSTANT_CLASS_P (base0)) + && ((DECL_P (base1) + && (targetm.binds_local_p (base1) + || CONSTANT_CLASS_P (base0))) + || CONSTANT_CLASS_P (base1))) + { + if (code == EQ_EXPR) + return omit_two_operands (type, boolean_false_node, arg0, arg1); + else if (code == NE_EXPR) + return omit_two_operands (type, boolean_true_node, arg0, arg1); + } + /* For equal offsets we can simplify to a comparison of the + base addresses. */ + else if (bitpos0 == bitpos1 + && (indirect_base0 + ? base0 != TREE_OPERAND (arg0, 0) : base0 != arg0) + && (indirect_base1 + ? base1 != TREE_OPERAND (arg1, 0) : base1 != arg1) + && ((offset0 == offset1) + || (offset0 && offset1 + && operand_equal_p (offset0, offset1, 0)))) + { + if (indirect_base0) + base0 = fold_addr_expr (base0); + if (indirect_base1) + base1 = fold_addr_expr (base1); + return fold_build2 (code, type, base0, base1); + } } /* Transform comparisons of the form X +- C1 CMP Y +- C2 to @@ -8929,27 +8964,6 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1) } } - /* Fold a comparison of the address of COMPONENT_REFs with the same - type and component to a comparison of the address of the base - object. In short, &x->a OP &y->a to x OP y and - &x->a OP &y.a to x OP &y */ - if (TREE_CODE (arg0) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (arg0, 0)) == COMPONENT_REF - && TREE_CODE (arg1) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (arg1, 0)) == COMPONENT_REF) - { - tree cref0 = TREE_OPERAND (arg0, 0); - tree cref1 = TREE_OPERAND (arg1, 0); - if (TREE_OPERAND (cref0, 1) == TREE_OPERAND (cref1, 1)) - { - tree op0 = TREE_OPERAND (cref0, 0); - tree op1 = TREE_OPERAND (cref1, 0); - return fold_build2 (code, type, - fold_addr_expr (op0), - fold_addr_expr (op1)); - } - } - /* We can fold X/C1 op C2 where C1 and C2 are integer constants into a single range test. */ if ((TREE_CODE (arg0) == TRUNC_DIV_EXPR diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e7f0cbe0608..1ad89e161d2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2008-03-27 Richard Guenther + + * gcc.dg/fold-addr-1.c: New testcase. + 2008-03-27 Andrew Pinski PR middle-end/35429 diff --git a/gcc/testsuite/gcc.dg/fold-addr-1.c b/gcc/testsuite/gcc.dg/fold-addr-1.c new file mode 100644 index 00000000000..7323ffdabf7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-addr-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-original" } */ + +int bar(char p1, char p2) +{ + return &p1 == &p2; +} + +/* { dg-final { scan-tree-dump "return 0;" "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 5944e6a95b2..64f60003733 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -724,7 +724,8 @@ operand_less_p (tree val, tree val2) fold_undefer_and_ignore_overflow_warnings (); - if (!tcmp) + if (!tcmp + || TREE_CODE (tcmp) != INTEGER_CST) return -2; if (!integer_zerop (tcmp)) @@ -932,7 +933,7 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p) || TREE_CODE (val2) != INTEGER_CST) { t = fold_binary_to_constant (NE_EXPR, boolean_type_node, val1, val2); - if (t && tree_expr_nonzero_p (t)) + if (t && integer_onep (t)) return 2; } -- 2.30.2