alias-access-path-4.c: New testcase.
authorJan Hubicka <hubicka@ucw.cz>
Sun, 16 Jun 2019 17:59:02 +0000 (19:59 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 16 Jun 2019 17:59:02 +0000 (17:59 +0000)
* gcc.dg/tree-ssa/alias-access-path-4.c: New testcase.
* gcc.dg/tree-ssa/alias-access-path-5.c: New testcase.

* tree-ssa-alias.c (aliasing_component_refs_p): Watch for arrays
at the end of structures.

From-SVN: r272357

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

index 89bb8c5..05c18aa 100644 (file)
@@ -1,3 +1,8 @@
+2019-06-16  Jan Hubicka  <hubicka@ucw.cz>
+
+       * tree-ssa-alias.c (aliasing_component_refs_p): Watch for arrays
+       at the end of structures.
+
 2019-06-16  Iain Sandoe  <iain@sandoe.co.uk>
 
        * config/darwin.c (machopic_indirect_call_target): Use renamed
index db21750..5186112 100644 (file)
@@ -1,3 +1,8 @@
+2019-06-16  Jan Hubicka  <hubicka@ucw.cz>
+
+       * gcc.dg/tree-ssa/alias-access-path-4.c: New testcase.
+       * gcc.dg/tree-ssa/alias-access-path-5.c: New testcase.
+
 2019-06-15  Iain Buclaw  <ibuclaw@gdcproject.org>
 
        PR d/90650
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c
new file mode 100644 (file)
index 0000000..641ef89
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct a {int v1;
+          int v2;};
+struct b {struct a a[0];};
+union c {struct b b;};
+
+int
+test (struct b *bptr1, union c *cptr, int i, int j)
+{
+  bptr1->a[i].v1=123;
+  cptr->b.a[j].v2=1;
+  return bptr1->a[i].v1;
+}
+int
+test2 (struct b *bptr1, union c *cptr, int i, int j)
+{
+  bptr1->a[i].v1=124;
+  cptr->b.a[j].v1=1;
+  return bptr1->a[i].v1;
+}
+/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-not "return 124" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c
new file mode 100644 (file)
index 0000000..412f99e
--- /dev/null
@@ -0,0 +1,25 @@
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct a {int v1;
+          int v2;};
+struct b {int array[0]; struct a a[];};
+union c {struct b b;};
+
+int
+test (struct b *bptr1, union c *cptr, int i, int j)
+{
+  bptr1->a[i].v1=123;
+  cptr->b.a[j].v2=1;
+  return bptr1->a[i].v1;
+}
+int
+test2 (struct b *bptr1, union c *cptr, int i, int j)
+{
+  bptr1->a[i].v1=124;
+  cptr->b.a[j].v1=1;
+  return bptr1->a[i].v1;
+}
+/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-not "return 124" "optimized"} } */
index 9cd39a2..52f9270 100644 (file)
@@ -877,22 +877,62 @@ aliasing_component_refs_p (tree ref1,
   tree *refp;
   int same_p1 = 0, same_p2 = 0;
   bool maybe_match = false;
+  tree end_struct_ref1 = NULL, end_struct_ref2 = NULL;
 
   /* Choose bases and base types to search for.  */
   base1 = ref1;
   while (handled_component_p (base1))
-    base1 = TREE_OPERAND (base1, 0);
+    {
+      /* Generally access paths are monotous in the size of object. The
+        exception are trailing arrays of structures. I.e.
+          struct a {int array[0];};
+        or
+          struct a {int array1[0]; int array[];};
+        Such struct has size 0 but accesses to a.array may have non-zero size.
+        In this case the size of TREE_TYPE (base1) is smaller than
+        size of TREE_TYPE (TREE_OPERNAD (base1, 0)).
+
+        Because we compare sizes of arrays just by sizes of their elements,
+        we only need to care about zero sized array fields here.  */
+      if (TREE_CODE (base1) == COMPONENT_REF
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (base1, 1))) == ARRAY_TYPE
+         && (!TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base1, 1)))
+             || integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base1, 1)))))
+         && array_at_struct_end_p (base1))
+       {
+         gcc_checking_assert (!end_struct_ref1);
+          end_struct_ref1 = base1;
+       }
+      base1 = TREE_OPERAND (base1, 0);
+    }
   type1 = TREE_TYPE (base1);
   base2 = ref2;
   while (handled_component_p (base2))
-    base2 = TREE_OPERAND (base2, 0);
+    {
+      if (TREE_CODE (base2) == COMPONENT_REF
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (base2, 1))) == ARRAY_TYPE
+         && (!TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base2, 1)))
+             || integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base2, 1)))))
+         && array_at_struct_end_p (base2))
+       {
+         gcc_checking_assert (!end_struct_ref2);
+         end_struct_ref2 = base2;
+       }
+      base2 = TREE_OPERAND (base2, 0);
+    }
   type2 = TREE_TYPE (base2);
 
   /* Now search for the type1 in the access path of ref2.  This
      would be a common base for doing offset based disambiguation on.
      This however only makes sense if type2 is big enough to hold type1.  */
   int cmp_outer = compare_type_sizes (type2, type1);
-  if (cmp_outer >= 0)
+
+  /* If type2 is big enough to contain type1 walk its access path.
+     We also need to care of arrays at the end of structs that may extend
+     beyond the end of structure.  */
+  if (cmp_outer >= 0
+      || (end_struct_ref2
+         && compare_type_sizes (TREE_TYPE (end_struct_ref2), type1) >= 0))
     {
       refp = &ref2;
       while (true)
@@ -900,7 +940,11 @@ aliasing_component_refs_p (tree ref1,
          /* We walk from inner type to the outer types. If type we see is
             already too large to be part of type1, terminate the search.  */
          int cmp = compare_type_sizes (type1, TREE_TYPE (*refp));
-         if (cmp < 0)
+
+         if (cmp < 0
+             && (!end_struct_ref1
+                 || compare_type_sizes (TREE_TYPE (end_struct_ref1),
+                                        TREE_TYPE (*refp)) < 0))
            break;
          /* If types may be of same size, see if we can decide about their
             equality.  */
@@ -957,13 +1001,18 @@ aliasing_component_refs_p (tree ref1,
     }
 
   /* If we didn't find a common base, try the other way around.  */
-  if (cmp_outer <= 0)
+  if (cmp_outer <= 0 
+      || (end_struct_ref1
+         && compare_type_sizes (TREE_TYPE (end_struct_ref1), type1) <= 0))
     {
       refp = &ref1;
       while (true)
        {
          int cmp = compare_type_sizes (type2, TREE_TYPE (*refp));
-         if (cmp < 0)
+         if (cmp < 0
+             && (!end_struct_ref2
+                 || compare_type_sizes (TREE_TYPE (end_struct_ref2),
+                                        TREE_TYPE (*refp)) < 0))
            break;
          /* If types may be of same size, see if we can decide about their
             equality.  */
@@ -1024,6 +1073,9 @@ aliasing_component_refs_p (tree ref1,
      if there is no B2 in the tail of path1 and no B1 on the
      tail of path2.  */
   if (compare_type_sizes (TREE_TYPE (ref2), type1) >= 0
+      && (!end_struct_ref1
+         || compare_type_sizes (TREE_TYPE (ref2),
+                                TREE_TYPE (end_struct_ref1)) >= 0)
       && type_has_components_p (TREE_TYPE (ref2))
       && (base1_alias_set == ref2_alias_set
           || alias_set_subset_of (base1_alias_set, ref2_alias_set)))
@@ -1034,6 +1086,9 @@ aliasing_component_refs_p (tree ref1,
   /* If this is ptr vs. decl then we know there is no ptr ... decl path.  */
   if (!ref2_is_decl
       && compare_type_sizes (TREE_TYPE (ref1), type2) >= 0
+      && (!end_struct_ref2
+         || compare_type_sizes (TREE_TYPE (ref1),
+                                TREE_TYPE (end_struct_ref2)) >= 0)
       && type_has_components_p (TREE_TYPE (ref1))
       && (base2_alias_set == ref1_alias_set
          || alias_set_subset_of (base2_alias_set, ref1_alias_set)))
@@ -1477,8 +1532,9 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
       && 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);
+             && TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) == INTEGER_CST))
+      && !ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2))
+    return false;
 
   if (ref1 && ref2
       && nonoverlapping_component_refs_p (ref1, ref2))
@@ -1558,8 +1614,9 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
     {
       poly_offset_int moff1 = mem_ref_offset (base1) << LOG2_BITS_PER_UNIT;
       poly_offset_int moff2 = mem_ref_offset (base2) << LOG2_BITS_PER_UNIT;
-      return ranges_maybe_overlap_p (offset1 + moff1, max_size1,
-                                    offset2 + moff2, max_size2);
+      if (!ranges_maybe_overlap_p (offset1 + moff1, max_size1,
+                                  offset2 + moff2, max_size2))
+       return false;
     }
   if (!ptr_derefs_may_alias_p (ptr1, ptr2))
     return false;
@@ -1598,8 +1655,9 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
       /* But avoid treating arrays as "objects", instead assume they
          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);
+      && TREE_CODE (TREE_TYPE (ptrtype1)) != ARRAY_TYPE
+      && !ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2))
+    return false;
 
   if (ref1 && ref2
       && nonoverlapping_component_refs_p (ref1, ref2))