aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c78
-rw-r--r--gcc/testsuite/ChangeLog14
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C25
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr15791-2.C13
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr15791-3.C13
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr15791-4.C13
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr15791-5.C13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c13
13 files changed, 253 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 601ef3d..bfb9128 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 67a0217..5d6e713 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7f6149c..88725cb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..68f14ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
@@ -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
index 0000000..fb8cbbe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr15791-2.C
@@ -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
index 0000000..be7ac1e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr15791-3.C
@@ -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
index 0000000..54cf0dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr15791-4.C
@@ -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
index 0000000..0db13b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr15791-5.C
@@ -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
index 0000000..68f14ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c
@@ -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
index 0000000..df68bfe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c
@@ -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
index 0000000..be7ac1e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c
@@ -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
index 0000000..54cf0dd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c
@@ -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
index 0000000..0db13b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c
@@ -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" } } */
+