diff options
author | Richard Guenther <rguenther@suse.de> | 2010-05-26 10:30:31 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2010-05-26 10:30:31 +0000 |
commit | 630d3fad23b067a707161db41e58f13406a0174a (patch) | |
tree | e629cdd028a222d98c2cb8569146c330a61a9b68 /gcc | |
parent | b9b6c0843114c581b7f203075d87357c23b8f88a (diff) | |
download | gcc-630d3fad23b067a707161db41e58f13406a0174a.zip gcc-630d3fad23b067a707161db41e58f13406a0174a.tar.gz gcc-630d3fad23b067a707161db41e58f13406a0174a.tar.bz2 |
re PR rtl-optimization/44164 (Aliasing bug triggered by Boost.Bind/Boost.Function)
2010-05-26 Richard Guenther <rguenther@suse.de>
PR rtl-optimization/44164
* tree-ssa-alias.c (aliasing_component_refs_p): Fix the
no-common access-path disambiguation.
(indirect_ref_may_alias_decl_p): Adjust.
(indirect_refs_may_alias_p): Likewise.
(refs_may_alias_p_1): Likewise.
* gcc.c-torture/execute/pr44164.c: New testcase.
* g++.dg/tree-ssa/pr13146.C: Adjust.
From-SVN: r159861
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-ssa/pr13146.C | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr44164.c | 24 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 50 |
5 files changed, 84 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 656ae38..7996315 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2010-05-26 Richard Guenther <rguenther@suse.de> + + PR rtl-optimization/44164 + * tree-ssa-alias.c (aliasing_component_refs_p): Fix the + no-common access-path disambiguation. + (indirect_ref_may_alias_decl_p): Adjust. + (indirect_refs_may_alias_p): Likewise. + (refs_may_alias_p_1): Likewise. + 2010-05-26 Steven Bosscher <steven@gcc.gnu.org> * c-typeck.c: Do not include expr.h. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index abfdca5..a319f63 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-05-26 Richard Guenther <rguenther@suse.de> + + PR rtl-optimization/44164 + * gcc.c-torture/execute/pr44164.c: New testcase. + * g++.dg/tree-ssa/pr13146.C: Adjust. + 2010-05-26 Paul Thomas <pault@gcc.gnu.org> PR fortran/40011 diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr13146.C b/gcc/testsuite/g++.dg/tree-ssa/pr13146.C index 62447c1..22baf03 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr13146.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr13146.C @@ -30,7 +30,10 @@ class multi: public third, public second { public: short s; - char f3; + /* The following field used to be of type char but that causes + class multi to effectively get alias-set zero which we end + up not optimizing because of the fix for PR44164. */ + int f3; }; extern void link_error (); diff --git a/gcc/testsuite/gcc.c-torture/execute/pr44164.c b/gcc/testsuite/gcc.c-torture/execute/pr44164.c new file mode 100644 index 0000000..171f9c3 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr44164.c @@ -0,0 +1,24 @@ +struct X { + struct Y { + struct YY { + struct Z { + int i; + } c; + } bb; + } b; +} a; +int __attribute__((noinline, noclone)) +foo (struct Z *p) +{ + int i = p->i; + a.b = (struct Y){}; + return p->i + i; +} +extern void abort (void); +int main() +{ + a.b.bb.c.i = 1; + if (foo (&a.b.bb.c) != 1) + abort (); + return 0; +} diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 2db3058..10292f2 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -563,13 +563,21 @@ same_type_for_tbaa (tree type1, tree type2) /* Determine if the two component references REF1 and REF2 which are based on access types TYPE1 and TYPE2 and of which at least one is based - on an indirect reference may alias. */ + on an indirect reference may alias. REF2 is the only one that can + be a decl in which case REF2_IS_DECL is true. + REF1_ALIAS_SET, BASE1_ALIAS_SET, REF2_ALIAS_SET and BASE2_ALIAS_SET + are the respective alias sets. */ static bool aliasing_component_refs_p (tree ref1, tree type1, + alias_set_type ref1_alias_set, + alias_set_type base1_alias_set, HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1, tree ref2, tree type2, - HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2) + alias_set_type ref2_alias_set, + alias_set_type base2_alias_set, + HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2, + bool ref2_is_decl) { /* If one reference is a component references through pointers try to find a common base and apply offset based disambiguation. This handles @@ -613,8 +621,20 @@ aliasing_component_refs_p (tree ref1, tree type1, offset1 -= offadj; return ranges_overlap_p (offset1, max_size1, offset2, max_size2); } + /* If we have two type access paths B1.path1 and B2.path2 they may - only alias if either B1 is in B2.path2 or B2 is in B1.path1. */ + only alias if either B1 is in B2.path2 or B2 is in B1.path1. + But we can still have a path that goes B1.path1...B2.path2 with + a part that we do not see. So we can only disambiguate now + if there is no B2 in the tail of path1 and no B1 on the + tail of path2. */ + if (base1_alias_set == ref2_alias_set + || alias_set_subset_of (base1_alias_set, ref2_alias_set)) + return true; + /* If this is ptr vs. decl then we know there is no ptr ... decl path. */ + if (!ref2_is_decl) + return (base2_alias_set == ref1_alias_set + || alias_set_subset_of (base2_alias_set, ref1_alias_set)); return false; } @@ -649,9 +669,11 @@ decl_refs_may_alias_p (tree base1, static bool indirect_ref_may_alias_decl_p (tree ref1, tree ptr1, HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1, + alias_set_type ref1_alias_set, alias_set_type base1_alias_set, tree ref2, tree base2, HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2, + alias_set_type ref2_alias_set, alias_set_type base2_alias_set) { /* If only one reference is based on a variable, they cannot alias if @@ -695,9 +717,11 @@ indirect_ref_may_alias_decl_p (tree ref1, tree ptr1, && handled_component_p (ref1) && handled_component_p (ref2)) return aliasing_component_refs_p (ref1, TREE_TYPE (TREE_TYPE (ptr1)), + ref1_alias_set, base1_alias_set, offset1, max_size1, ref2, TREE_TYPE (base2), - offset2, max_size2); + ref2_alias_set, base2_alias_set, + offset2, max_size2, true); return true; } @@ -712,9 +736,11 @@ indirect_ref_may_alias_decl_p (tree ref1, tree ptr1, static bool indirect_refs_may_alias_p (tree ref1, tree ptr1, HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1, + alias_set_type ref1_alias_set, alias_set_type base1_alias_set, tree ref2, tree ptr2, HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2, + alias_set_type ref2_alias_set, alias_set_type base2_alias_set) { /* If both bases are based on pointers they cannot alias if they may not @@ -756,9 +782,11 @@ indirect_refs_may_alias_p (tree ref1, tree ptr1, && handled_component_p (ref1) && handled_component_p (ref2)) return aliasing_component_refs_p (ref1, TREE_TYPE (TREE_TYPE (ptr1)), + ref1_alias_set, base1_alias_set, offset1, max_size1, ref2, TREE_TYPE (TREE_TYPE (ptr2)), - offset2, max_size2); + ref2_alias_set, base2_alias_set, + offset2, max_size2, false); return true; } @@ -911,14 +939,18 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p) set = tbaa_p ? -1 : 0; if (var1_p && ind2_p) return indirect_ref_may_alias_decl_p (ref2->ref, TREE_OPERAND (base2, 0), - offset2, max_size2, set, + offset2, max_size2, + ao_ref_alias_set (ref2), set, ref1->ref, base1, - offset1, max_size1, set); + offset1, max_size1, + ao_ref_alias_set (ref1), set); else if (ind1_p && ind2_p) return indirect_refs_may_alias_p (ref1->ref, TREE_OPERAND (base1, 0), - offset1, max_size1, set, + offset1, max_size1, + ao_ref_alias_set (ref1), set, ref2->ref, TREE_OPERAND (base2, 0), - offset2, max_size2, set); + offset2, max_size2, + ao_ref_alias_set (ref2), set); gcc_unreachable (); } |