From 020d90eeafef20bc913608dbf794ba33ee578774 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Sat, 29 Jan 2005 19:25:17 +0000 Subject: [PATCH] re PR tree-optimization/15791 (fold misses that two ADDR_EXPR of an arrary obvious not equal) 2005-01-29 Richard Guenther 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. From-SVN: r94414 --- gcc/ChangeLog | 7 ++ gcc/fold-const.c | 78 +++++++++++++++++++++++ gcc/testsuite/ChangeLog | 14 ++++ gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C | 25 ++++++++ gcc/testsuite/g++.dg/tree-ssa/pr15791-2.C | 13 ++++ gcc/testsuite/g++.dg/tree-ssa/pr15791-3.C | 13 ++++ gcc/testsuite/g++.dg/tree-ssa/pr15791-4.C | 13 ++++ gcc/testsuite/g++.dg/tree-ssa/pr15791-5.C | 13 ++++ gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c | 25 ++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c | 13 ++++ gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c | 13 ++++ gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c | 13 ++++ gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c | 13 ++++ 13 files changed, 253 insertions(+) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr15791-2.C create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr15791-3.C create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr15791-4.C create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr15791-5.C create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 601ef3d95ee..bfb9128738e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-01-29 Richard Guenther + + 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 * gcse.c (insert_expr_in_table): Revamp handling of available diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 67a0217057a..5d6e713ff53 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 7f6149c7d97..88725cba350 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2005-01-29 Richard Guenther + + 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 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 00000000000..68f14adad00 --- /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 00000000000..fb8cbbe4c82 --- /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 00000000000..be7ac1e0e1b --- /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 00000000000..54cf0dd91d9 --- /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 00000000000..0db13b09a49 --- /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 00000000000..68f14adad00 --- /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 00000000000..df68bfeba7f --- /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 00000000000..be7ac1e0e1b --- /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 00000000000..54cf0dd91d9 --- /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 00000000000..0db13b09a49 --- /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" } } */ + -- 2.30.2