re PR rtl-optimization/44164 (Aliasing bug triggered by Boost.Bind/Boost.Function)
authorRichard Guenther <rguenther@suse.de>
Wed, 26 May 2010 10:30:31 +0000 (10:30 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 26 May 2010 10:30:31 +0000 (10:30 +0000)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/pr13146.C
gcc/testsuite/gcc.c-torture/execute/pr44164.c [new file with mode: 0644]
gcc/tree-ssa-alias.c

index 656ae38a1433087ba41decc2d92bab31de041f16..7996315d1bd0ce840add9f59dd4582ee016f1b24 100644 (file)
@@ -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.
index abfdca5d413af129d558c5db03c820fa6137c1b2..a319f63060f1136751cd02a7c5f994da2990c645 100644 (file)
@@ -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
index 62447c1a2727799a8b6363a9419b567dd6c6ac91..22baf03d33b3edb7cbb65d13a37e7a8a47ac14c7 100644 (file)
@@ -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 (file)
index 0000000..171f9c3
--- /dev/null
@@ -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;
+}
index 2db305873249abf46e6db0c811ee97cc8c6c43b6..10292f27a964f8262953adcfc908ea4ac3d5f76b 100644 (file)
@@ -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 ();
 }