OSDN Git Service

2005-01-29 Richard Guenther <richard.guenther@uni-tuebingen.de>
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 29 Jan 2005 19:25:17 +0000 (19:25 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 29 Jan 2005 19:25:17 +0000 (19:25 +0000)
PR tree-optimization/15791
* fold-const.c (extract_array_ref): New function.
(fold): Fold comparisons between &a[i] and &a[j] or
semantically equivalent trees.

* gcc.dg/tree-ssa/pr15791-1.c: New testcase.
* gcc.dg/tree-ssa/pr15791-2.c: Likewise.
* gcc.dg/tree-ssa/pr15791-3.c: Likewise.
* gcc.dg/tree-ssa/pr15791-4.c: Likewise.
* gcc.dg/tree-ssa/pr15791-5.c: Likewise.
* g++.dg/tree-ssa/pr15791-1.C: Likewise.
* g++.dg/tree-ssa/pr15791-2.C: Likewise.
* g++.dg/tree-ssa/pr15791-3.C: Likewise.
* g++.dg/tree-ssa/pr15791-4.C: Likewise.
* g++.dg/tree-ssa/pr15791-5.C: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94414 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/pr15791-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/pr15791-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/pr15791-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/pr15791-5.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c [new file with mode: 0644]

index 601ef3d..bfb9128 100644 (file)
@@ -1,3 +1,10 @@
+2005-01-29  Richard Guenther <richard.guenther@uni-tuebingen.de>
+
+       PR tree-optimization/15791
+       * fold-const.c (extract_array_ref): New function.
+       (fold): Fold comparisons between &a[i] and &a[j] or
+       semantically equivalent trees.
+
 2005-01-29  Jeff Law  <law@redhat.com>
 
        * gcse.c (insert_expr_in_table): Revamp handling of available
index 67a0217..5d6e713 100644 (file)
@@ -5374,6 +5374,57 @@ constant_boolean_node (int value, tree type)
     return build_int_cst (type, value);
 }
 
+
+/* 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.  */
+
+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);
+      STRIP_NOPS (op0);
+      if (TREE_CODE (op0) == ADDR_EXPR)
+       {
+         *base = TREE_OPERAND (expr, 0);
+         *offset = TREE_OPERAND (expr, 1);
+         return true;
+       }
+    }
+  /* Other canonical form is an ADDR_EXPR of an ARRAY_REF,
+     which we transform into an ADDR_EXPR with appropriate
+     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)
+    {
+      tree op0 = TREE_OPERAND (inner_expr, 0);
+      if (TREE_CODE (op0) == ARRAY_REF)
+       {
+         *base = build_fold_addr_expr (TREE_OPERAND (op0, 0));
+         *offset = TREE_OPERAND (op0, 1);
+       }
+      else
+       {
+         *base = inner_expr;
+         *offset = NULL_TREE;
+       }
+      return true;
+    }
+
+  return false;
+}
+
+
 /* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
    Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'.  Here
    CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
@@ -8246,6 +8297,33 @@ fold (tree expr)
                                      ? code == EQ_EXPR : code != EQ_EXPR,
                                      type);
 
+      /* If this is a comparison of two exprs that look like an
+        ARRAY_REF of the same object, then we can fold this to a
+        comparison of the two offsets.  */
+      if (COMPARISON_CLASS_P (t))
+       {
+         tree base0, offset0, base1, offset1;
+
+         if (extract_array_ref (arg0, &base0, &offset0)
+             && extract_array_ref (arg1, &base1, &offset1)
+             && operand_equal_p (base0, base1, 0))
+           {
+             if (offset0 == NULL_TREE
+                 && offset1 == NULL_TREE)
+               {
+                 offset0 = integer_zero_node;
+                 offset1 = integer_zero_node;
+               }
+             else if (offset0 == NULL_TREE)
+               offset0 = build_int_cst (TREE_TYPE (offset1), 0);
+             else if (offset1 == NULL_TREE)
+               offset1 = build_int_cst (TREE_TYPE (offset0), 0);
+
+             if (TREE_TYPE (offset0) == TREE_TYPE (offset1))
+               return fold (build2 (code, type, offset0, offset1));
+           }
+       }
+
       if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
        {
          tree targ0 = strip_float_extensions (arg0);
index 7f6149c..88725cb 100644 (file)
@@ -1,3 +1,17 @@
+2005-01-29  Richard Guenther <richard.guenther@uni-tuebingen.de>
+
+       PR tree-optimization/15791
+       * gcc.dg/tree-ssa/pr15791-1.c: New testcase.
+       * gcc.dg/tree-ssa/pr15791-2.c: Likewise.
+       * gcc.dg/tree-ssa/pr15791-3.c: Likewise.
+       * gcc.dg/tree-ssa/pr15791-4.c: Likewise.
+       * gcc.dg/tree-ssa/pr15791-5.c: Likewise.
+       * g++.dg/tree-ssa/pr15791-1.C: Likewise.
+       * g++.dg/tree-ssa/pr15791-2.C: Likewise.
+       * g++.dg/tree-ssa/pr15791-3.C: Likewise.
+       * g++.dg/tree-ssa/pr15791-4.C: Likewise.
+       * g++.dg/tree-ssa/pr15791-5.C: Likewise.
+
 2005-01-29  Paul Brook  <paul@codesourcery.com>
 
        PR fortran/18565
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C b/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
new file mode 100644 (file)
index 0000000..68f14ad
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do link } */
+
+void link_error ();
+
+int main ()
+{
+  struct { int b[2]; } x;
+  int b[2];
+  if (&b[1] != &b[1])
+    link_error ();
+  if (&b[0] != b)
+    link_error ();
+  if (b == &b[2])
+    link_error ();
+  if (b != b)
+    link_error ();
+  if (&x.b[1] == &x.b[0])
+    link_error ();
+  if (x.b != &x.b[0])
+    link_error ();
+  if (&x.b[1] == x.b)
+    link_error ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr15791-2.C b/gcc/testsuite/g++.dg/tree-ssa/pr15791-2.C
new file mode 100644 (file)
index 0000000..fb8cbbe
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do link } */
+/* { dg-options "" } */
+
+void link_error ();
+struct a {};
+int main ()
+{
+  struct a b[2];
+  if (&b[0] == &b[1])
+    link_error ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr15791-3.C b/gcc/testsuite/g++.dg/tree-ssa/pr15791-3.C
new file mode 100644 (file)
index 0000000..be7ac1e
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+int f(int i, unsigned j)
+{
+      int b[2];
+      if (&b[i] == &b[j])
+             return 1;
+      return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "i == j" 0 "gimple" } } */
+
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr15791-4.C b/gcc/testsuite/g++.dg/tree-ssa/pr15791-4.C
new file mode 100644 (file)
index 0000000..54cf0dd
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+int f(int i, int j)
+{
+    int b[2][2];
+    if (&b[1][i] == &b[0][j])
+      return 1;
+    return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "i == j" 0 "gimple" } } */
+
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr15791-5.C b/gcc/testsuite/g++.dg/tree-ssa/pr15791-5.C
new file mode 100644 (file)
index 0000000..0db13b0
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+int foo(int i, int j)
+{
+       char g[16];
+       if (&g[i] == &g[j])
+               return 1;
+       return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "i == j" 1 "gimple" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c
new file mode 100644 (file)
index 0000000..68f14ad
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do link } */
+
+void link_error ();
+
+int main ()
+{
+  struct { int b[2]; } x;
+  int b[2];
+  if (&b[1] != &b[1])
+    link_error ();
+  if (&b[0] != b)
+    link_error ();
+  if (b == &b[2])
+    link_error ();
+  if (b != b)
+    link_error ();
+  if (&x.b[1] == &x.b[0])
+    link_error ();
+  if (x.b != &x.b[0])
+    link_error ();
+  if (&x.b[1] == x.b)
+    link_error ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c
new file mode 100644 (file)
index 0000000..df68bfe
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do link } */
+/* { dg-options "" } */
+
+void link_error ();
+struct a {};
+int main ()
+{
+  struct a b[2];
+  if (&b[0] != &b[1])
+    link_error ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c
new file mode 100644 (file)
index 0000000..be7ac1e
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+int f(int i, unsigned j)
+{
+      int b[2];
+      if (&b[i] == &b[j])
+             return 1;
+      return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "i == j" 0 "gimple" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c
new file mode 100644 (file)
index 0000000..54cf0dd
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+int f(int i, int j)
+{
+    int b[2][2];
+    if (&b[1][i] == &b[0][j])
+      return 1;
+    return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "i == j" 0 "gimple" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c
new file mode 100644 (file)
index 0000000..0db13b0
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+int foo(int i, int j)
+{
+       char g[16];
+       if (&g[i] == &g[j])
+               return 1;
+       return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "i == j" 1 "gimple" } } */
+