On Tue, Aug 2, 2022 at 9:19 AM Richard Biener
<richard.guent...@gmail.com> wrote:
>
> On Mon, Aug 1, 2022 at 8:17 AM Aldy Hernandez via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> >
> > Even though ranger is type agnostic, SCEV seems to only work with
> > integers.  This patch removes some FIXME notes making it explicit that
> > bounds_of_var_in_loop only works with iranges.
>
> SCEV also handles floats, where do you see this failing?  Yes, support is
> somewhat limited, but still.

Oh, it does?  We could convert  range_of_ssa_name_with_loop_info to
the type agnostic vrange if so... (see attached untested patch).

I'm looking at the testcase for 24021 with the attached patch, and
bounds_of_var_in_loop() is returning false because SCEV couldn't
figure out the direction of the loop:

  dir = scev_direction (chrec);
  if (/* Do not adjust ranges if we do not know whether the iv increases
     or decreases,  ... */
      dir == EV_DIR_UNKNOWN
      /* ... or if it may wrap.  */
      || scev_probably_wraps_p (NULL_TREE, init, step, stmt,
                get_chrec_loop (chrec), true))
    return false;

The chrec in question is rather simple... a loop increasing by 0.01:

(gdb) p debug(chrec)
{1.00000000000000002081668171172168513294309377670288085938e-2, +,
1.00000001490116119384765625e-1}_1

I also see that bounds_of_var_in_loop() calls niter's
max_loop_iterations(), which if I understand things correctly, bails
at several points if the step is not integral.

I'd be happy to adapt our code, if SCEV can give me useful information.

Aldy
From 86752bb57b0534b496b51559ec8e28e56fb3ea4e Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <al...@redhat.com>
Date: Tue, 2 Aug 2022 13:27:16 +0200
Subject: [PATCH] Make range_of_ssa_name_with_loop_info type agnostic.

gcc/ChangeLog:

	* gimple-range-fold.cc (fold_using_range::range_of_phi): Remove
	irange check.
	(tree_lower_bound): New.
	(tree_upper_bound): New.
	(fold_using_range::range_of_ssa_name_with_loop_info): Convert to
	vrange.
	* gimple-range-fold.h (range_of_ssa_name_with_loop_info): Change
	argument to vrange.
---
 gcc/gimple-range-fold.cc | 46 ++++++++++++++++++++++++++++++----------
 gcc/gimple-range-fold.h  |  2 +-
 2 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 7665c954f2b..923094abd62 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -854,13 +854,12 @@ fold_using_range::range_of_phi (vrange &r, gphi *phi, fur_source &src)
 
   // If SCEV is available, query if this PHI has any knonwn values.
   if (scev_initialized_p ()
-      && !POINTER_TYPE_P (TREE_TYPE (phi_def))
-      && irange::supports_p (TREE_TYPE (phi_def)))
+      && !POINTER_TYPE_P (TREE_TYPE (phi_def)))
     {
       class loop *l = loop_containing_stmt (phi);
       if (l && loop_outer (l))
 	{
-	  int_range_max loop_range;
+	  Value_Range loop_range (type);
 	  range_of_ssa_name_with_loop_info (loop_range, phi_def, l, phi, src);
 	  if (!loop_range.varying_p ())
 	    {
@@ -1330,10 +1329,32 @@ fold_using_range::range_of_cond_expr  (vrange &r, gassign *s, fur_source &src)
   return true;
 }
 
+// Return the lower bound of R as a tree.
+
+static inline tree
+tree_lower_bound (const vrange &r, tree type)
+{
+  if (is_a <irange> (r))
+    return wide_int_to_tree (type, as_a <irange> (r).lower_bound ());
+  // ?? Handle floats when they contain endpoints.
+  return NULL;
+}
+
+// Return the upper bound of R as a tree.
+
+static inline tree
+tree_upper_bound (const vrange &r, tree type)
+{
+  if (is_a <irange> (r))
+    return wide_int_to_tree (type, as_a <irange> (r).upper_bound ());
+  // ?? Handle floats when they contain endpoints.
+  return NULL;
+}
+
 // If SCEV has any information about phi node NAME, return it as a range in R.
 
 void
-fold_using_range::range_of_ssa_name_with_loop_info (irange &r, tree name,
+fold_using_range::range_of_ssa_name_with_loop_info (vrange &r, tree name,
 						    class loop *l, gphi *phi,
 						    fur_source &src)
 {
@@ -1341,24 +1362,27 @@ fold_using_range::range_of_ssa_name_with_loop_info (irange &r, tree name,
   tree min, max, type = TREE_TYPE (name);
   if (bounds_of_var_in_loop (&min, &max, src.query (), l, phi, name))
     {
-      if (TREE_CODE (min) != INTEGER_CST)
+      if (!is_gimple_constant (min))
 	{
 	  if (src.query ()->range_of_expr (r, min, phi) && !r.undefined_p ())
-	    min = wide_int_to_tree (type, r.lower_bound ());
+	    min = tree_lower_bound (r, type);
 	  else
 	    min = vrp_val_min (type);
 	}
-      if (TREE_CODE (max) != INTEGER_CST)
+      if (!is_gimple_constant (max))
 	{
 	  if (src.query ()->range_of_expr (r, max, phi) && !r.undefined_p ())
-	    max = wide_int_to_tree (type, r.upper_bound ());
+	    max = tree_upper_bound (r, type);
 	  else
 	    max = vrp_val_max (type);
 	}
-      r.set (min, max);
+      if (min && max)
+	{
+	  r.set (min, max);
+	  return;
+	}
     }
-  else
-    r.set_varying (type);
+  r.set_varying (type);
 }
 
 // -----------------------------------------------------------------------
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index fbf66275f74..c2f381dffec 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -173,7 +173,7 @@ protected:
   void range_of_builtin_ubsan_call (irange &r, gcall *call, tree_code code,
 				    fur_source &src);
   bool range_of_phi (vrange &r, gphi *phi, fur_source &src);
-  void range_of_ssa_name_with_loop_info (irange &, tree, class loop *, gphi *,
+  void range_of_ssa_name_with_loop_info (vrange &, tree, class loop *, gphi *,
 					 fur_source &src);
   void relation_fold_and_or (irange& lhs_range, gimple *s, fur_source &src);
 };
-- 
2.37.1

Reply via email to