aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2010-05-26 10:30:31 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2010-05-26 10:30:31 +0000
commit630d3fad23b067a707161db41e58f13406a0174a (patch)
treee629cdd028a222d98c2cb8569146c330a61a9b68 /gcc
parentb9b6c0843114c581b7f203075d87357c23b8f88a (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr13146.C5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr44164.c24
-rw-r--r--gcc/tree-ssa-alias.c50
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 ();
}