fold-const.c (target.h): Include.
authorRichard Guenther <rguenther@suse.de>
Wed, 26 Mar 2008 12:37:29 +0000 (12:37 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 26 Mar 2008 12:37:29 +0000 (12:37 +0000)
2008-03-26  Richard Guenther  <rguenther@suse.de>

* fold-const.c (target.h): Include.
(fold_comparison): Fold comparison of addresses of two decls
that bind locally.  Consolidate address folding code.

* gcc.dg/fold-addr-1.c: New testcase.

From-SVN: r133599

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/fold-addr-1.c [new file with mode: 0644]

index d31e6adbe14699fdf0495dcc0146d723960f3f68..e1f0e34f2eb0f64cd9219793e6d30e962a118cea 100644 (file)
@@ -1,3 +1,9 @@
+2008-03-26  Richard Guenther  <rguenther@suse.de>
+
+       * fold-const.c (target.h): Include.
+       (fold_comparison): Fold comparison of addresses of two decls
+       that bind locally.  Consolidate address folding code.
+
 2008-03-26  Nick Clifton  <nickc@redhat.com>
 
        PR target/31232
 2008-03-19  Richard Guenther  <rguenther@suse.de>
 
        PR middle-end/35609
-       * tree-ssa.c (always_executed): New global flag.
-       (warn_uninitialized_var): If !always_executed warn with "maybe"
+       * tree-ssa.c (walk_data): New structure.
+       (warn_uninitialized_var): If not always_executed warn with "maybe"
        instead of "is".
        (execute_early_warn_uninitialized): Compute post-dominators.
        Initialize always_executed before processing each basic block.
index 3bfe52e0081f1eeee75e08cfe192b7222dacf8ab..4964ef7b525d25222c00769540e5f85adc742214 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"
@@ -8481,11 +8482,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)
        {
@@ -8509,24 +8511,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
@@ -8581,6 +8578,37 @@ 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 plain decls.  */
+      else if (!indirect_base0 && !indirect_base1
+              && TREE_CODE (arg0) == ADDR_EXPR
+              && TREE_CODE (arg1) == ADDR_EXPR
+              && DECL_P (base0) && DECL_P (base1)
+              && !operand_equal_p (base0, base1, 0)
+              && targetm.binds_local_p (base0)
+              && targetm.binds_local_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
@@ -8927,27 +8955,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 6c8c1902efdf28a6d2d340f956d38dba6b5c6b72..64ffcb07fcac7487298d0ec61b58bd6c621706fa 100644 (file)
@@ -1,3 +1,7 @@
+2008-03-26  Richard Guenther  <rguenther@suse.de>
+
+       * gcc.dg/fold-addr-1.c: New testcase.
+
 2008-03-26  Richard Guenther  <rguenther@suse.de>
 
        * gcc.dg/tree-ssa/20030731-2.c: Scan dce1 dump.
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" } } */