Hi,
this patch makes insert_access to ignore accesses that are paradoxical
(i.e. their max_size is smaller than size) which can happen for example
when VRP proves that the access happens past the end of array bounds.
It also checks for zero sized accesses and verifies that max_size is
never negative.

Bootstrapped/regtested x86_64-linux, comitted.


gcc/ChangeLog:

        PR ipa/103073
        * ipa-modref-tree.h (modref_tree::insert): Do nothing for
        paradoxical and zero sized accesses.

gcc/testsuite/ChangeLog:

        PR ipa/103073
        * g++.dg/torture/pr103073.C: New test.
        * gcc.dg/tree-ssa/modref-11.c: New test.

diff --git a/gcc/ipa-modref-tree.h b/gcc/ipa-modref-tree.h
index bc428d193d2..54ae9e1df4e 100644
--- a/gcc/ipa-modref-tree.h
+++ b/gcc/ipa-modref-tree.h
@@ -818,6 +818,36 @@ struct GTY((user)) modref_tree
 
     bool changed = false;
 
+    /* We may end up with max_size being less than size for accesses past the
+       end of array.  Those are undefined and safe to ignore.  */
+    if (a.range_info_useful_p ()
+       && known_size_p (a.size) && known_size_p (a.max_size)
+       && known_lt (a.max_size, a.size))
+      {
+       if (dump_file)
+         fprintf (dump_file,
+                  "   - Paradoxical range. Ignoring\n");
+       return false;
+      }
+    if (known_size_p (a.size)
+       && known_eq (a.size, 0))
+      {
+       if (dump_file)
+         fprintf (dump_file,
+                  "   - Zero size. Ignoring\n");
+       return false;
+      }
+    if (known_size_p (a.max_size)
+       && known_eq (a.max_size, 0))
+      {
+       if (dump_file)
+         fprintf (dump_file,
+                  "   - Zero max_size. Ignoring\n");
+       return false;
+      }
+    gcc_checking_assert (!known_size_p (a.max_size)
+                        || !known_le (a.max_size, 0));
+
     /* No useful information tracked; collapse everything.  */
     if (!base && !ref && !a.useful_p ())
       {
diff --git a/gcc/testsuite/g++.dg/torture/pr103073.C 
b/gcc/testsuite/g++.dg/torture/pr103073.C
new file mode 100644
index 00000000000..02b1eee064a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr103073.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+int a;
+void b(bool c[], char d[], bool g[][55][21]) {
+  for (signed e = 0; e < 11; e += 3)
+    for (unsigned f = c[0] + 1; f < d[0]; f += 3)
+      a = g[0][e][f + 2];
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-11.c 
b/gcc/testsuite/gcc.dg/tree-ssa/modref-11.c
new file mode 100644
index 00000000000..de9ad16879f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-11.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-modref1"  } */
+struct linkedlist {
+  struct linkedlist *next;
+};
+struct linkedlist *
+find_last (struct linkedlist *l)
+{
+  while (l->next)
+   l = l->next;
+  return l;
+}
+/* { dg-final { scan-tree-dump "noclobber noescape nodirectescape" "modref1"} 
} */

Reply via email to