Full comments in the PR, but basically substitute and fold was expecting to see a constant returned for any range which globally evaluates to a constant.
This allowed it to replace all uses of an ssa name as they were encountered.

The ranger model can return UNDEFINED for the range of names in blocks which are unreachable..  the patch simply overrides the UNDEFINED value in folders query if the global value is a constant so that subst_and_fold will get what it is expecting.

Bootstrapped on  x86_64-pc-linux-gnu, no regressions, pushed.

Andrew
commit 0d0bbb379d7e5f029d0fb05465fac996493e7850
Author: Andrew MacLeod <amacl...@redhat.com>
Date:   Wed Oct 21 19:55:28 2020 -0400

    Check for undefined before not returning a constant value
    
    Don't return UNDEFINED for a range in an unreachable block if the global
    value evaluates to a constant.  Return that constant instead.
    
            PR tree-optimization/97515
            * value-query.cc (range_query::value_of_expr): If the result is
            UNDEFINED, check to see if the global value is a constant.
            (range_query::value_on_edge): Ditto.

diff --git a/gcc/testsuite/gcc.dg/pr97515.c b/gcc/testsuite/gcc.dg/pr97515.c
new file mode 100644
index 00000000000..2b6185ec90b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97515.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+e7 (int gg)
+{
+  int xe = 0;
+
+  while (xe < 1)
+    {
+      int ui;
+
+      ui = ~xe;
+      if (ui == 0)
+        ui = xe >> gg;
+
+      xe %= !ui;
+    }
+
+  return xe;
+}
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index 5370a23fe18..23ba48d73a7 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -82,8 +82,16 @@ range_query::value_of_expr (tree name, gimple *stmt)
 
   if (!irange::supports_type_p (TREE_TYPE (name)))
     return NULL_TREE;
-  if (range_of_expr (r, name, stmt) && r.singleton_p (&t))
-    return t;
+
+  if (range_of_expr (r, name, stmt))
+    {
+      // A constant used in an unreachable block oftens returns as UNDEFINED.
+      // If the result is undefined, check the global value for a constant.
+      if (r.undefined_p ())
+	range_of_expr (r, name);
+      if (r.singleton_p (&t))
+	return t;
+    }
   return NULL_TREE;
 }
 
@@ -95,8 +103,15 @@ range_query::value_on_edge (edge e, tree name)
 
   if (!irange::supports_type_p (TREE_TYPE (name)))
     return NULL_TREE;
-  if (range_on_edge (r, e, name) && r.singleton_p (&t))
-    return t;
+  if (range_on_edge (r, e, name))
+    {
+      // A constant used in an unreachable block oftens returns as UNDEFINED.
+      // If the result is undefined, check the global value for a constant.
+      if (r.undefined_p ())
+	range_of_expr (r, name);
+      if (r.singleton_p (&t))
+	return t;
+    }
   return NULL_TREE;
 
 }

Reply via email to