[gcc r17-3055] [frange] Convert the int to float cast to sub-ranges.

Aldy Hernandez via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:5038e4ade5289798cdeb30723facb481d707c426

commit r17-3055-g5038e4ade5289798cdeb30723facb481d707c426
Author: Aldy Hernandez <[email protected]>
Date:   Tue Aug 4 14:00:39 2026 +0000

    [frange] Convert the int to float cast to sub-ranges.
    
    operator_cast::fold_range for an integer operand converted only the
    [lower, upper] hull of the integer range.  Convert  sub-ranges.
    
    Tested on ppc64le Linux: regstrap and LAPACK.
    
    gcc/ChangeLog:
    
            * range-op-float.cc (operator_cast::fold_range): Convert each
            integer sub-range and union the results.
            (range_op_float_tests): New test.

Diff:
---
 gcc/range-op-float.cc | 48 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 32 insertions(+), 16 deletions(-)

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index c3a287fbf501..b03f1e97449c 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -3128,25 +3128,31 @@ operator_cast::fold_range (frange &r, tree type, const irange &op1,
 {
   if (empty_range_varying (r, type, op1, op1))
     return true;
-  REAL_VALUE_TYPE lb, ub;
-  wide_int op1_lb = op1.lower_bound ();
-  wide_int op1_ub = op1.upper_bound ();
   tree op1_type = op1.type ();
-  enum machine_mode mode = flag_rounding_math ? VOIDmode : TYPE_MODE (type);
-  real_from_integer (&lb, mode, op1_lb, TYPE_SIGN (op1_type));
-  real_from_integer (&ub, mode, op1_ub, TYPE_SIGN (op1_type));
-  if (flag_rounding_math)
+  r.set_undefined ();
+  for (unsigned i = 0; i < op1.num_pairs (); ++i)
     {
-      REAL_VALUE_TYPE lbo = lb, ubo = ub;
-      mode = TYPE_MODE (type);
-      real_convert (&lb, mode, &lb);
-      real_convert (&ub, mode, &ub);
-      if (real_less (&lbo, &lb))
-	frange_nextafter (mode, lb, dconstninf);
-      if (real_less (&ub, &ubo))
-	frange_nextafter (mode, ub, dconstinf);
+      REAL_VALUE_TYPE lb, ub;
+      wide_int op1_lb = op1.lower_bound (i);
+      wide_int op1_ub = op1.upper_bound (i);
+      enum machine_mode mode = flag_rounding_math ? VOIDmode : TYPE_MODE (type);
+      real_from_integer (&lb, mode, op1_lb, TYPE_SIGN (op1_type));
+      real_from_integer (&ub, mode, op1_ub, TYPE_SIGN (op1_type));
+      if (flag_rounding_math)
+	{
+	  REAL_VALUE_TYPE lbo = lb, ubo = ub;
+	  mode = TYPE_MODE (type);
+	  real_convert (&lb, mode, &lb);
+	  real_convert (&ub, mode, &ub);
+	  if (real_less (&lbo, &lb))
+	    frange_nextafter (mode, lb, dconstninf);
+	  if (real_less (&ub, &ubo))
+	    frange_nextafter (mode, ub, dconstinf);
+	}
+      frange tmp;
+      tmp.set (type, lb, ub, nan_state (false));
+      r.union_ (tmp);
     }
-  r.set (type, lb, ub, nan_state (false));
   if (r.undefined_p ())
     r.set_varying (type);
   return true;
@@ -3308,6 +3314,16 @@ range_op_float_tests ()
   r0.clear_nan ();
   range_op_handler (ABS_EXPR).fold_range (r, float_type_node, r0, trange);
   ASSERT_EQ (r.num_pairs (), 2);
+
+  // (float)([1, 4] U [6, 10]) keeps the gap.
+  unsigned iprec = TYPE_PRECISION (integer_type_node);
+  int_range<2> i0 (integer_type_node,
+		   wi::shwi (1, iprec), wi::shwi (4, iprec));
+  int_range<2> i1 (integer_type_node,
+		   wi::shwi (6, iprec), wi::shwi (10, iprec));
+  i0.union_ (i1);
+  range_op_handler (FLOAT_EXPR).fold_range (r, float_type_node, i0, trange);
+  ASSERT_EQ (r.num_pairs (), 2);
 }
 
 } // namespace selftest
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.