Combine new calculated ranges with existing range.
authorAndrew MacLeod <amacleod@redhat.com>
Fri, 6 Nov 2020 19:14:46 +0000 (14:14 -0500)
committerAndrew MacLeod <amacleod@redhat.com>
Fri, 6 Nov 2020 19:20:54 +0000 (14:20 -0500)
When a range is recalculated, retain what was previously known as IL changes
can produce different results from un-executed code.   This also paves
the way for external injection of ranges.

gcc/
PR tree-optimization/97737
PR tree-optimization/97741
* gimple-range.cc: (gimple_ranger::range_of_stmt): Intersect newly
calculated ranges with the existing known global range.
gcc/testsuite/
* gcc.dg/pr97737.c: New.
* gcc.dg/pr97741.c: New.

gcc/gimple-range.cc
gcc/testsuite/gcc.dg/pr97737.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr97741.c [new file with mode: 0644]

index 0c8ec40448fb0b577b2e04ee78b4f40c4027d757..92a6335bec565ac6871102be7d2502280ee86c80 100644 (file)
@@ -1026,8 +1026,14 @@ gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
   if (m_cache.get_non_stale_global_range (r, name))
     return true;
 
-  // Otherwise calculate a new value and save it.
-  calc_stmt (r, s, name);
+  // Otherwise calculate a new value.
+  int_range_max tmp;
+  calc_stmt (tmp, s, name);
+
+  // Combine the new value with the old value.  This is required because
+  // the way value propagation works, when the IL changes on the fly we
+  // can sometimes get different results.  See PR 97741.
+  r.intersect (tmp);
   m_cache.set_global_range (name, r);
   return true;
 }
diff --git a/gcc/testsuite/gcc.dg/pr97737.c b/gcc/testsuite/gcc.dg/pr97737.c
new file mode 100644 (file)
index 0000000..eef1c35
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int a = 1, b, c;
+
+void d() {
+  int e = 1;
+L1:
+  b = e;
+L2:
+  e = e / a;
+  if (!(e || c || e - 1))
+    goto L1;
+  if (!b)
+    goto L2;
+}
diff --git a/gcc/testsuite/gcc.dg/pr97741.c b/gcc/testsuite/gcc.dg/pr97741.c
new file mode 100644 (file)
index 0000000..47115d3
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -Wextra -fno-strict-aliasing -fwrapv -Os -fno-toplevel-reorder -fno-tree-ccp -fno-tree-fre" } */
+
+short a = 0;
+long b = 0;
+char c = 0;
+void d() {
+  int e = 0;
+f:
+  for (a = 6; a;)
+    c = e;
+  e = 0;
+  for (; e == 20; ++e)
+    for (; b;)
+      goto f;
+}
+int main() { return 0; }