fold-const.c (extract_array_ref): Handle more cases, do some useful canonicalization...
authorJeff Law <law@gcc.gnu.org>
Tue, 31 May 2005 14:33:29 +0000 (08:33 -0600)
committerJeff Law <law@gcc.gnu.org>
Tue, 31 May 2005 14:33:29 +0000 (08:33 -0600)
        * fold-const.c (extract_array_ref): Handle more cases,
        do some useful canonicalization of the base.
        (fold_binary): Explicitly deal with arrays of zero-sized
        structures during folding of &a[i] == &a[j].

        * gcc.dg/tree-ssa/foldaddr-1.c: New test.

From-SVN: r100391

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

index 6bec3f35b69da1c3d8bd350b07bfab368e540280..947517b3da467fc03ddbe164d434305fdbb78288 100644 (file)
@@ -1,3 +1,10 @@
+2005-05-31  Richard Guenther  <rguenth@gcc.gnu.org>
+
+       * fold-const.c (extract_array_ref): Handle more cases,
+       do some useful canonicalization of the base.
+       (fold_binary): Explicitly deal with arrays of zero-sized
+       structures during folding of &a[i] == &a[j].
+
 2005-05-31  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * doc/install.texi (sparc-sun-solaris2*): Update note
index 98803271f56185d894d456e087949757bd07f12c..c780659b5567c23af8152bbaf835e16dc3709ee0 100644 (file)
@@ -5488,26 +5488,31 @@ constant_boolean_node (int value, tree type)
 
 /* Return true if expr looks like an ARRAY_REF and set base and
    offset to the appropriate trees.  If there is no offset,
-   offset is set to NULL_TREE.  */
+   offset is set to NULL_TREE.  Base will be canonicalized to
+   something you can get the element type from using
+   TREE_TYPE (TREE_TYPE (base)).  */
 
 static bool
 extract_array_ref (tree expr, tree *base, tree *offset)
 {
-  /* We have to be careful with stripping nops as with the
-     base type the meaning of the offset can change.  */
-  tree inner_expr = expr;
-  STRIP_NOPS (inner_expr);
   /* One canonical form is a PLUS_EXPR with the first
      argument being an ADDR_EXPR with a possible NOP_EXPR
      attached.  */
   if (TREE_CODE (expr) == PLUS_EXPR)
     {
       tree op0 = TREE_OPERAND (expr, 0);
+      tree inner_base, dummy1;
+      /* Strip NOP_EXPRs here because the C frontends and/or
+        folders present us (int *)&x.a + 4B possibly.  */
       STRIP_NOPS (op0);
-      if (TREE_CODE (op0) == ADDR_EXPR)
+      if (extract_array_ref (op0, &inner_base, &dummy1))
        {
-         *base = TREE_OPERAND (expr, 0);
-         *offset = TREE_OPERAND (expr, 1);
+         *base = inner_base;
+         if (dummy1 == NULL_TREE)
+           *offset = TREE_OPERAND (expr, 1);
+         else
+           *offset = fold_build2 (PLUS_EXPR, TREE_TYPE (expr),
+                                  dummy1, TREE_OPERAND (expr, 1));
          return true;
        }
     }
@@ -5516,21 +5521,33 @@ extract_array_ref (tree expr, tree *base, tree *offset)
      offset.  For other arguments to the ADDR_EXPR we assume
      zero offset and as such do not care about the ADDR_EXPR
      type and strip possible nops from it.  */
-  else if (TREE_CODE (inner_expr) == ADDR_EXPR)
+  else if (TREE_CODE (expr) == ADDR_EXPR)
     {
-      tree op0 = TREE_OPERAND (inner_expr, 0);
+      tree op0 = TREE_OPERAND (expr, 0);
       if (TREE_CODE (op0) == ARRAY_REF)
        {
-         *base = build_fold_addr_expr (TREE_OPERAND (op0, 0));
+         *base = TREE_OPERAND (op0, 0);
          *offset = TREE_OPERAND (op0, 1);
        }
       else
        {
-         *base = inner_expr;
+         /* Handle array-to-pointer decay as &a.  */
+         if (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE)
+           *base = TREE_OPERAND (expr, 0);
+         else
+           *base = expr;
          *offset = NULL_TREE;
        }
       return true;
     }
+  /* The next canonical form is a VAR_DECL with POINTER_TYPE.  */
+  else if (SSA_VAR_P (expr)
+          && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
+    {
+      *base = expr;
+      *offset = NULL_TREE;
+      return true;
+    }
 
   return false;
 }
@@ -9017,6 +9034,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              && extract_array_ref (arg1, &base1, &offset1)
              && operand_equal_p (base0, base1, 0))
            {
+             if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (base0)))
+                 && integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_TYPE (base0)))))
+               offset0 = NULL_TREE;
+             if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (base1)))
+                 && integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_TYPE (base1)))))
+               offset1 = NULL_TREE;
              if (offset0 == NULL_TREE
                  && offset1 == NULL_TREE)
                {
index e5fbfc9be354b067e5bddca5f516949ced4ca2b3..f537330db2771c29c88622f9449e64e55f0c2616 100644 (file)
@@ -1,3 +1,7 @@
+2005-05-31  Jeff Law  <law@redhat.com>
+
+       * gcc.dg/tree-ssa/foldaddr-1.c: New test.
+
 2005-05-30  Paolo Carlini  <pcarlini@suse.de>
 
        PR middle-end/21743
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldaddr-1.c b/gcc/testsuite/gcc.dg/tree-ssa/foldaddr-1.c
new file mode 100644 (file)
index 0000000..2c04027
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-original" } */
+
+
+char *a;
+int foo(char *b)
+{
+        return a+5+(long)b == (long)b+a;
+}
+
+/* Folding should have determined that the two addresses were
+   not identical and thus collapsed the function into a trivial
+   "return 0".  */
+/* { dg-final { scan-tree-dump-times "return 0" 1 "original"} } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+