Make aliasing_component_refs_p to work harder when same_type_for_tbaa returns -1
authorJan Hubicka <hubicka@ucw.cz>
Fri, 7 Jun 2019 08:14:04 +0000 (10:14 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Fri, 7 Jun 2019 08:14:04 +0000 (08:14 +0000)
* tree-ssa-alias.c (aliasing_component_refs_p): Do not give up
immediately after same_types_for_tbaa_p returns -1 and continue
looking for possible exact match; if matching types are arrays
watch for partial overlaps.
(indirect_ref_may_alias_decl_p): Watch for partial array overlaps.
(indirect_refs_may_alias_p): Do type based disambiguation first;
update comment.

* gcc.dg/lto/alias-access-path-2.0.c: New testcase.

From-SVN: r272036

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c [new file with mode: 0644]
gcc/tree-ssa-alias.c

index add02bbb9909eb40e1d06e071a500df8fa52d296..dbe6909a76580875e417eca92c9dda7a17ee63b8 100644 (file)
@@ -1,3 +1,13 @@
+2019-06-07  Jan Hubicka  <hubicka@ucw.cz>
+
+       * tree-ssa-alias.c (aliasing_component_refs_p): Do not give up
+       immediately after same_types_for_tbaa_p returns -1 and continue
+       looking for possible exact match; if matching types are arrays
+       watch for partial overlaps.
+       (indirect_ref_may_alias_decl_p): Watch for partial array overlaps.
+       (indirect_refs_may_alias_p): Do type based disambiguation first;
+       update comment.
+
 2019-06-07  Richard Sandiford  <richard.sandiford@arm.com>
 
        * fwprop.c (propagate_rtx): Fix call to paradoxical_subreg_p.
index d5f5cd469f0c1e76e14b79eee122a9ce0a6473f4..9410686a9f700bdd65c03baed40c707e8348a1ad 100644 (file)
@@ -1,3 +1,7 @@
+2019-06-07  Jan Hubicka  <hubicka@ucw.cz>
+
+       * gcc.dg/lto/alias-access-path-2.0.c: New testcase.
+
 2019-06-07  Martin Liska  <mliska@suse.cz>
 
        PR tree-optimization/78902
diff --git a/gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c b/gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c
new file mode 100644 (file)
index 0000000..7a53a1a
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { { -O3 -flto -fno-early-inlining } } } */
+
+/* In this test the access patch orracle (aliasing_component_refs_p)
+   can disambiguage array[0] from array[1] by base+offset but it needs to be
+   able to find the common type and not give up by not being able to compare
+   types earlier.  */
+
+typedef int (*fnptr) ();
+
+__attribute__ ((used))
+struct a
+{
+  void *array[2];
+} a, *aptr = &a;
+
+__attribute__ ((used))
+struct b
+{
+ struct a a;
+} *bptr;
+
+static void
+inline_me_late (int argc)
+{
+  if (argc == -1)
+    bptr->a.array[1] = bptr;
+}
+
+int
+main (int argc)
+{
+  aptr->array[0] = 0;
+  inline_me_late (argc);
+  if (!__builtin_constant_p (aptr->array[0] == 0))
+    __builtin_abort ();
+  return 0;
+}
index 429288b6ca523a7ed09267e651e3a35d8d53479f..ebe05544bad09e0e61df3c075f13b62b8deada8a 100644 (file)
@@ -860,6 +860,7 @@ aliasing_component_refs_p (tree ref1,
   tree type1, type2;
   tree *refp;
   int same_p1 = 0, same_p2 = 0;
+  bool maybe_match = false;
 
   /* Choose bases and base types to search for.  */
   base1 = ref1;
@@ -890,8 +891,14 @@ aliasing_component_refs_p (tree ref1,
          if (cmp == 0)
            {
              same_p2 = same_type_for_tbaa (TREE_TYPE (*refp), type1);
-             if (same_p2 != 0)
+             if (same_p2 == 1)
                break;
+             /* In case we can't decide whether types are same try to
+                continue looking for the exact match.
+                Remember however that we possibly saw a match
+                to bypass the access path continuations tests we do later.  */
+             if (same_p2 == -1)
+               maybe_match = true;
            }
          if (!handled_component_p (*refp))
            break;
@@ -901,6 +908,21 @@ aliasing_component_refs_p (tree ref1,
        {
          poly_int64 offadj, sztmp, msztmp;
          bool reverse;
+
+         /* We assume that arrays can overlap by multiple of their elements
+            size as tested in gcc.dg/torture/alias-2.c.
+            This partial overlap happen only when both arrays are bases of
+            the access and not contained within another component ref.
+            To be safe we also assume partial overlap for VLAs.  */
+         if (TREE_CODE (TREE_TYPE (base1)) == ARRAY_TYPE
+             && (!TYPE_SIZE (TREE_TYPE (base1))
+                 || TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) != INTEGER_CST
+                 || (*refp == base2 && !ref2_is_decl)))
+           {
+             ++alias_stats.aliasing_component_refs_p_may_alias;
+             return true;
+           }
+
          get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse);
          offset2 -= offadj;
          get_ref_base_and_extent (base1, &offadj, &sztmp, &msztmp, &reverse);
@@ -932,8 +954,10 @@ aliasing_component_refs_p (tree ref1,
          if (cmp == 0)
            {
              same_p1 = same_type_for_tbaa (TREE_TYPE (*refp), type2);
-             if (same_p1 != 0)
+             if (same_p1 == 1)
                break;
+             if (same_p1 == -1)
+               maybe_match = true;
            }
          if (!handled_component_p (*refp))
            break;
@@ -944,6 +968,15 @@ aliasing_component_refs_p (tree ref1,
          poly_int64 offadj, sztmp, msztmp;
          bool reverse;
 
+         if (TREE_CODE (TREE_TYPE (base2)) == ARRAY_TYPE
+             && (!TYPE_SIZE (TREE_TYPE (base2))
+                 || TREE_CODE (TYPE_SIZE (TREE_TYPE (base2))) != INTEGER_CST
+                 || (*refp == base1 && !ref2_is_decl)))
+           {
+             ++alias_stats.aliasing_component_refs_p_may_alias;
+             return true;
+           }
+
          get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse);
          offset1 -= offadj;
          get_ref_base_and_extent (base2, &offadj, &sztmp, &msztmp, &reverse);
@@ -965,7 +998,7 @@ aliasing_component_refs_p (tree ref1,
      paths do not overlap and thus accesses alias only if one path can be
      continuation of another.  If we was not able to decide about equivalence,
      we need to give up.  */
-  if (same_p1 == -1 || same_p2 == -1)
+  if (maybe_match)
     return true;
 
   /* If we have two type access paths B1.path1 and B2.path2 they may
@@ -1350,10 +1383,17 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
      For MEM_REFs we require that the component-ref offset we computed
      is relative to the start of the type which we ensure by
      comparing rvalue and access type and disregarding the constant
-     pointer offset.  */
+     pointer offset.
+
+     But avoid treating variable length arrays as "objects", instead assume they
+     can overlap by an exact multiple of their element size.
+     See gcc.dg/torture/alias-2.c.  */
   if ((TREE_CODE (base1) != TARGET_MEM_REF
        || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
-      && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (dbase2)) == 1)
+      && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (dbase2)) == 1
+      && (TREE_CODE (TREE_TYPE (base1)) != ARRAY_TYPE
+         || (TYPE_SIZE (TREE_TYPE (base1))
+             && TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) == INTEGER_CST)))
     return ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2);
 
   if (ref1 && ref2
@@ -1446,6 +1486,16 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
       || base2_alias_set == 0)
     return true;
 
+  /* Do type-based disambiguation.  */
+  if (base1_alias_set != base2_alias_set
+      && !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
+    return false;
+
+  /* If either reference is view-converted, give up now.  */
+  if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1
+      || same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) != 1)
+    return true;
+
   /* If both references are through the same type, they do not alias
      if the accesses do not overlap.  This does extra disambiguation
      for mixed/pointer accesses but requires strict aliasing.  */
@@ -1453,25 +1503,14 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
        || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
       && (TREE_CODE (base2) != TARGET_MEM_REF
          || (!TMR_INDEX (base2) && !TMR_INDEX2 (base2)))
-      && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) == 1
-      && same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) == 1
       && same_type_for_tbaa (TREE_TYPE (ptrtype1),
                             TREE_TYPE (ptrtype2)) == 1
       /* But avoid treating arrays as "objects", instead assume they
-         can overlap by an exact multiple of their element size.  */
+         can overlap by an exact multiple of their element size.
+         See gcc.dg/torture/alias-2.c.  */
       && TREE_CODE (TREE_TYPE (ptrtype1)) != ARRAY_TYPE)
     return ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2);
 
-  /* Do type-based disambiguation.  */
-  if (base1_alias_set != base2_alias_set
-      && !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
-    return false;
-
-  /* If either reference is view-converted, give up now.  */
-  if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1
-      || same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) != 1)
-    return true;
-
   if (ref1 && ref2
       && nonoverlapping_component_refs_p (ref1, ref2))
     return false;