diff options
author | Jeff Law <law@gcc.gnu.org> | 2005-05-31 08:33:29 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2005-05-31 08:33:29 -0600 |
commit | 4ea73bfac370705eaf74e204264bf994c51bdfd9 (patch) | |
tree | a7d96a788cce99a3c5e29aae3516eefd479c4bc4 | |
parent | aa7f91020495d7fb90d297e66b82674c60697968 (diff) | |
download | gcc-4ea73bfac370705eaf74e204264bf994c51bdfd9.zip gcc-4ea73bfac370705eaf74e204264bf994c51bdfd9.tar.gz gcc-4ea73bfac370705eaf74e204264bf994c51bdfd9.tar.bz2 |
fold-const.c (extract_array_ref): Handle more cases, do some useful canonicalization of the base.
* 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
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/fold-const.c | 47 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/foldaddr-1.c | 16 |
4 files changed, 62 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6bec3f3..947517b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 9880327..c780659 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e5fbfc9..f537330 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..2c04027 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/foldaddr-1.c @@ -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" } } */ + |