Fix ICE in insert_access

Message ID 20211105223454.GF4548@kam.mff.cuni.cz
State Committed
Commit 5f37780372212a7245f0528e46dbeb741316bba1
Headers
Series Fix ICE in insert_access |

Commit Message

Jan Hubicka Nov. 5, 2021, 10:34 p.m. UTC
  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.
  

Patch

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"} } */