The code in PR 100512 triggers an interaction between ranger and the propagation engine related to undefined values.

I put the detailed analysis in the PR, but it boils down to the early VRP pass has concluded that something is a constant and can be replaced, and removes the definition expecting the constant to be propagated everywhere.


If the code is in an undefined region that the CFG is going to remove, we can find impossible situations,a nd ranger then changes that value ot UNDEFINED..  because, well, it is.  But then the propagation engine panics because it doesnt have a constant any more, so odesnt replace it, and now we have a used but not defined value.

Once we get to a globally constant range where further refinements can only end up in an UNDEFINED state, stop further evaluating the range.  This is typically in places which are about to be removed by CFG cleanup anyway, and it will make the propagation engine happy with no surprises.

Bootstraps on x86_64-pc-linux-gnu with no regressions, and fixes the PR.

Pushed.

Andrew



commit 3f476de7fd274f619a0b04c2e2f7077ee8ab17a5
Author: Andrew MacLeod <amacl...@redhat.com>
Date:   Mon May 17 15:53:39 2021 -0400

    Once a range becomes constant, make it invariant.
    
    Once a range is forced to a constant globally, simply make it invariant.
    Unify this with the code which makes non-zero pointer ranges invariant.
    
            gcc/
            PR tree-optimization/100512
            * gimple-range-cache.cc (ranger_cache::set_global_range): Mark const
            and non-zero pointer ranges as invariant.
            * gimple-range.cc (gimple_ranger::range_of_stmt): Remove pointer
            processing from here.
    
            gcc/testsuite/
            PR tree-optimization/100512
            * gcc.dg/pr100512.c: New.

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 60e5d66c52d..2c922e32913 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -703,8 +703,19 @@ ranger_cache::set_global_range (tree name, const irange &r)
 
       propagate_updated_value (name, bb);
     }
-  // Mark the value as up-to-date.
-  m_temporal->set_timestamp (name);
+  // Constants no longer need to tracked.  Any further refinement has to be
+  // undefined. Propagation works better with constants. PR 100512.
+  // Pointers which resolve to non-zero also do not need
+  // tracking in the cache as they will never change.  See PR 98866.
+  // Otherwise mark the value as up-to-date.
+  if (r.singleton_p ()
+      || (POINTER_TYPE_P (TREE_TYPE (name)) && r.nonzero_p ()))
+    {
+      set_range_invariant (name);
+      m_temporal->set_always_current (name);
+    }
+  else
+    m_temporal->set_timestamp (name);
 }
 
 // Register a dependency on DEP to name.  If the timestamp for DEP is ever
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 5b288d8e6a7..710bc7f9632 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -1082,11 +1082,6 @@ gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
   r.intersect (tmp);
   m_cache.set_global_range (name, r);
 
-  // Pointers which resolve to non-zero at the defintion point do not need
-  // tracking in the cache as they will never change.  See PR 98866.
-  if (POINTER_TYPE_P (TREE_TYPE (name)) && r.nonzero_p ())
-    m_cache.set_range_invariant (name);
-
   return true;
 }
 
diff --git a/gcc/testsuite/gcc.dg/pr100512.c b/gcc/testsuite/gcc.dg/pr100512.c
new file mode 100644
index 00000000000..70b90e04be9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr100512.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -w" } */
+
+#include <stdint.h>
+int a;
+void b() {
+  int16_t *c;
+  uint16_t d = 2;
+  if (0 == d) {
+    uint64_t e;
+    uint64_t *f = &e;
+    for (;;) {
+      if (e += 0 >= 0)
+        for (;;)
+          ;
+    g:
+      for (; a;) {
+        int16_t i = &d;
+        *c = i && *f;
+      }
+    }
+  }
+  goto g;
+}
+

Reply via email to