tree-optimization: fix access path oracle on mismatched array refs [PR93586]
authorJan Hubicka <jh@suse.cz>
Fri, 21 Feb 2020 14:36:00 +0000 (15:36 +0100)
committerJan Hubicka <jh@suse.cz>
Fri, 21 Feb 2020 14:36:00 +0000 (15:36 +0100)
nonoverlapping_array_refs_p is not supposed to give meaningful results when
bases of ref1 and ref2 are not same or completely disjoint and here it is
called on c[0][j_2][0] and c[0][1] so bases in sence of this functions are
"c[0][j_2]" and "c[0]" which do partially overlap.  nonoverlapping_array_refs
however walks pair of array references and in this case it misses to note the
fact that if it walked across first mismatched pair it is no longer safe to
compare rest.

The reason why it continues matching is because it hopes it will
eventually get pair of COMPONENT_REFs from types of same size and use
TBAA to conclude that their addresses must be either same or completely
disjoint.

This patch makes the loop to terminate early but popping all the
remaining pairs so walking can continue.  We could re-synchronize on
arrays of same size with TBAA but this is bit fishy (because we try to
support some sort of partial array overlaps) and hard to implement
(because of zero sized arrays and VLAs) so I think it is not worth the
effort.

In addition I notied that the function is not !flag_strict_aliasing safe
and added early exits on places we set seen_unmatched_ref_p since later
we do not check that in:

       /* If we skipped array refs on type of different sizes, we can
   no longer be sure that there are not partial overlaps.  */
       if (seen_unmatched_ref_p
    && !operand_equal_p (TYPE_SIZE (type1), TYPE_SIZE (type2), 0))
  {
    ++alias_stats
      .nonoverlapping_refs_since_match_p_may_alias;
}

   PR tree-optimization/93586
* tree-ssa-alias.c (nonoverlapping_array_refs_p): Finish array walk
after mismatched array refs; do not sure type size information to
recover from unmatched referneces with !flag_strict_aliasing_p.

* gcc.dg/torture/pr93586.c: New testcase.

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr93586.c [new file with mode: 0644]
gcc/tree-ssa-alias.c

index b6e52531be03439497d4cbd9d9f03711df586d66..85630f3613f3398bb5e75e39b9cb1b973ba20128 100644 (file)
@@ -1,3 +1,11 @@
+2020-02-21  Jan Hubicka  <hubicka@ucw.cz>
+           Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/93586
+       * tree-ssa-alias.c (nonoverlapping_array_refs_p): Finish array walk
+       after mismatched array refs; do not sure type size information to
+       recover from unmatched referneces with !flag_strict_aliasing_p.
+
 2020-02-21  Andrew Stubbs  <ams@codesourcery.com>
 
        * config/gcn/gcn-valu.md (gather_load<mode>): Rename to ...
index ad4f43529daacbc898d1667794ccaf5e6e6d7874..606d00920d1e0d95cc7fbfd4d771fb41a130b175 100644 (file)
@@ -1,3 +1,9 @@
+2020-02-21  Jan Hubicka  <hubicka@ucw.cz>
+           Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/93586
+       * gcc.dg/torture/pr93586.c: New testcase.
+
 2020-02-21  Martin Jambor  <mjambor@suse.cz>
 
        PR tree-optimization/93845
diff --git a/gcc/testsuite/gcc.dg/torture/pr93586.c b/gcc/testsuite/gcc.dg/torture/pr93586.c
new file mode 100644 (file)
index 0000000..e861bdc
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fgimple" } */
+
+int __GIMPLE(ssa) foo(int j)
+{
+  int c[1][10][1];
+  int _1;
+
+__BB(2):
+  c[0][1][0] = 1;
+  c[0][1] = _Literal (int[1]) {};
+  _1 = c[0][j_2(D)][0];
+  return _1;
+}
+
+int main()
+{
+  if (foo (1) != 0)
+    __builtin_abort ();
+  return 0;
+}
index fd7810506685c27d5c0f6e7c7ef0cfe895f8a179..7554e209efa19e07904d8f07ef19afa210e202d7 100644 (file)
@@ -1486,9 +1486,27 @@ nonoverlapping_refs_since_match_p (tree match1, tree ref1,
                    .nonoverlapping_refs_since_match_p_no_alias;
                  return 1;
                }
-             partial_overlap = false;
              if (cmp == -1)
-               seen_unmatched_ref_p = true;
+               {
+                 seen_unmatched_ref_p = true;
+                 /* We can not maintain the invariant that bases are either
+                    same or completely disjoint.  However we can still recover
+                    from type based alias analysis if we reach referneces to
+                    same sizes.  We do not attempt to match array sizes, so
+                    just finish array walking and look for component refs.  */
+                 if (!flag_strict_aliasing)
+                   {
+                     ++alias_stats.nonoverlapping_refs_since_match_p_may_alias;
+                     return -1;
+                   }
+                 for (i++; i < narray_refs1; i++)
+                   {
+                     component_refs1.pop ();
+                     component_refs2.pop ();
+                   }
+                 break;
+               }
+             partial_overlap = false;
            }
        }
 
@@ -1503,7 +1521,14 @@ nonoverlapping_refs_since_match_p (tree match1, tree ref1,
            }
          ref1 = component_refs1.pop ();
          if (TREE_CODE (ref1) != COMPONENT_REF)
-           seen_unmatched_ref_p = true;
+           {
+             seen_unmatched_ref_p = true;
+             if (!flag_strict_aliasing)
+               {
+                 ++alias_stats.nonoverlapping_refs_since_match_p_may_alias;
+                 return -1;
+               }
+           }
        }
       while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref1, 0))));
 
@@ -1517,7 +1542,14 @@ nonoverlapping_refs_since_match_p (tree match1, tree ref1,
            }
          ref2 = component_refs2.pop ();
          if (TREE_CODE (ref2) != COMPONENT_REF)
-           seen_unmatched_ref_p = true;
+           {
+             if (!flag_strict_aliasing)
+               {
+                 ++alias_stats.nonoverlapping_refs_since_match_p_may_alias;
+                 return -1;
+               }
+             seen_unmatched_ref_p = true;
+           }
        }
       while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref2, 0))));
 
@@ -1537,6 +1569,8 @@ nonoverlapping_refs_since_match_p (tree match1, tree ref1,
 
       partial_overlap = false;
 
+      gcc_checking_assert (!seen_unmatched_ref_p || flag_strict_aliasing);
+
       /* If we skipped array refs on type of different sizes, we can
         no longer be sure that there are not partial overlaps.  */
       if (seen_unmatched_ref_p