From: rguenth Date: Tue, 26 Apr 2005 16:35:31 +0000 (+0000) Subject: 2004-04-26 Richard Guenther X-Git-Url: http://git.sourceforge.jp/view?a=commitdiff_plain;h=1f1b108e8b5d5faa79229e11d862b4b1516f6e2c;p=pf3gnuchains%2Fgcc-fork.git 2004-04-26 Richard Guenther PR tree-optimization/17598 * fold-const.c (fold_binary): Fold comparisons of addresses of COMPONENT_REFs which reference the same field to comparisons of the addresses of the base objects. * gcc.dg/tree-ssa/pr17598.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@98775 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 07c96a5372f..2d57e1f2e81 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2004-04-26 Richard Guenther + + PR tree-optimization/17598 + * fold-const.c (fold_binary): Fold comparisons of addresses + of COMPONENT_REFs which reference the same field to + comparisons of the addresses of the base objects. + 2005-04-26 Julian Brown * config/arm/arm.c (arm_return_in_msb): New function. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 416d89e1cdf..9de988c2300 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -9708,6 +9708,39 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return t1; } + /* 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); + if (TREE_CODE (op0) == INDIRECT_REF) + op0 = TREE_OPERAND (op0, 0); + else + { + tree ptype = build_pointer_type (TREE_TYPE (op0)); + op0 = build1 (ADDR_EXPR, ptype, op0); + } + if (TREE_CODE (op1) == INDIRECT_REF) + op1 = TREE_OPERAND (op1, 0); + else + { + tree ptype = build_pointer_type (TREE_TYPE (op1)); + op1 = build1 (ADDR_EXPR, ptype, op1); + } + return fold_build2 (code, type, op0, op1); + } + } + /* If this is a comparison of complex values and either or both sides are a COMPLEX_EXPR or COMPLEX_CST, it is best to split up the comparisons and join them with a TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5efc74bb8a6..17d95422d83 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-04-26 Richard Guenther + + PR tree-optimization/17598 + * gcc.dg/tree-ssa/pr17598.c: New testcase. + 2005-04-25 Mike Stump * objc.dg/fix-and-continue-1.m: Add. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr17598.c b/gcc/testsuite/gcc.dg/tree-ssa/pr17598.c new file mode 100644 index 00000000000..9313623f888 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr17598.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-generic" } */ + +struct f +{ + int i; + int j; +}; + +struct g +{ + int i; + struct f j; + struct f *k; +}; + +int foo(struct f *x, struct f *y) +{ + return &x->j == &y->j; /* x == y */ +} + +struct f y; +int bar(struct f *x) +{ + return &x->j == &y.j; /* x == &y */ +} + +struct g yy; +int foobar(struct g *x) +{ + return &x->j.i == &yy.j.i; /* x == &yy */ +} +int foobar2(struct g *x) +{ + return &x->k->i == &yy.k->i; /* x->k == yy.k */ +} + +/* { dg-final { scan-tree-dump-times "x == y" 1 "generic" } } */ +/* { dg-final { scan-tree-dump-times "x == &y" 2 "generic" } } */ +/* { dg-final { scan-tree-dump "x->k" "generic" } } */ +/* { dg-final { scan-tree-dump "yy.k" "generic" } } */ +/* { dg-final { cleanup-tree-dump "generic" } } */