fold-const.c (target.h): Include.
authorRichard Guenther <rguenther@suse.de>
Thu, 27 Mar 2008 09:17:43 +0000 (09:17 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 27 Mar 2008 09:17:43 +0000 (09:17 +0000)
2008-03-27  Richard Guenther  <rguenther@suse.de>

* 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
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/fold-addr-1.c [new file with mode: 0644]
gcc/tree-vrp.c

index 8eca39fde41dafa74cde1b76dbedd1f16a616c85..efe1197959939f77be3d3d5822579a9821fd1c4f 100644 (file)
@@ -1,3 +1,12 @@
+2008-03-27  Richard Guenther  <rguenther@suse.de>
+
+       * 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  <pinskia@gmail.com>
 
        PR middle-end/35429
index 896a9838e142af5f8863af3fc153f655f3f08942..a7dcfc3ff90885cb342fc2297fbbdf9a4e81f793 100644 (file)
@@ -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
index e7f0cbe0608e25e25505df2d1e2ff295b80ed800..1ad89e161d2464cf328b456f94d0961a336f8427 100644 (file)
@@ -1,3 +1,7 @@
+2008-03-27  Richard Guenther  <rguenther@suse.de>
+
+       * gcc.dg/fold-addr-1.c: New testcase.
+
 2008-03-27  Andrew Pinski  <pinskia@gmail.com>
 
        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 (file)
index 0000000..7323ffd
--- /dev/null
@@ -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" } } */
index 5944e6a95b246101e7acb0d53acba91b9ffb69e7..64f6000373380b59ec3134e77c5ae946532f6017 100644 (file)
@@ -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;
        }