[gcc r17-3147] [frange] Convert the float 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:c4317bd77775db690a4f63cfe619ba09018899ad

commit r17-3147-gc4317bd77775db690a4f63cfe619ba09018899ad
Author: Aldy Hernandez <[email protected]>
Date:   Fri Aug 7 09:48:10 2026 +0000

    [frange] Convert the float to float cast to sub-ranges.
    
    Tested on ppc64le Linux.
    
    gcc/ChangeLog:
    
            * range-op-float.cc (operator_cast::fold_range): Convert each
            sub-range and union the results.
            (range_op_float_tests): New test.

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

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 30d22a98ae55..75514c0603ee 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -2855,7 +2855,6 @@ bool
 operator_cast::fold_range (frange &r, tree type, const frange &op1,
 			   const frange &, relation_trio) const
 {
-  REAL_VALUE_TYPE lb, ub;
   enum machine_mode mode = TYPE_MODE (type);
   bool mode_composite = MODE_COMPOSITE_P (mode);
 
@@ -2872,46 +2871,53 @@ operator_cast::fold_range (frange &r, tree type, const frange &op1,
       return true;
     }
 
-  const REAL_VALUE_TYPE &lh_lb = op1.lower_bound ();
-  const REAL_VALUE_TYPE &lh_ub = op1.upper_bound ();
-  real_convert (&lb, mode, &lh_lb);
-  real_convert (&ub, mode, &lh_ub);
-
-  if (flag_rounding_math)
+  r.set_undefined ();
+  for (unsigned i = 0; i < op1.num_pairs (); ++i)
     {
-      if (real_less (&lh_lb, &lb))
+      REAL_VALUE_TYPE lb, ub;
+      const REAL_VALUE_TYPE &lh_lb = op1.lower_bound (i);
+      const REAL_VALUE_TYPE &lh_ub = op1.upper_bound (i);
+      real_convert (&lb, mode, &lh_lb);
+      real_convert (&ub, mode, &lh_ub);
+
+      if (flag_rounding_math)
 	{
-	  if (mode_composite
-	      && (real_isdenormal (&lb, mode) || real_iszero (&lb)))
+	  if (real_less (&lh_lb, &lb))
 	    {
-	      // IBM extended denormals only have DFmode precision.
-	      REAL_VALUE_TYPE tmp, tmp2;
-	      real_convert (&tmp2, DFmode, &lh_lb);
-	      real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
-			      &dconstninf);
-	      real_convert (&lb, mode, &tmp);
+	      if (mode_composite
+		  && (real_isdenormal (&lb, mode) || real_iszero (&lb)))
+		{
+		  // IBM extended denormals only have DFmode precision.
+		  REAL_VALUE_TYPE tmp, tmp2;
+		  real_convert (&tmp2, DFmode, &lh_lb);
+		  real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
+				  &dconstninf);
+		  real_convert (&lb, mode, &tmp);
+		}
+	      else
+		frange_nextafter (mode, lb, dconstninf);
 	    }
-	  else
-	    frange_nextafter (mode, lb, dconstninf);
-	}
-      if (real_less (&ub, &lh_ub))
-	{
-	  if (mode_composite
-	      && (real_isdenormal (&ub, mode) || real_iszero (&ub)))
+	  if (real_less (&ub, &lh_ub))
 	    {
-	      // IBM extended denormals only have DFmode precision.
-	      REAL_VALUE_TYPE tmp, tmp2;
-	      real_convert (&tmp2, DFmode, &lh_ub);
-	      real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
-			      &dconstinf);
-	      real_convert (&ub, mode, &tmp);
+	      if (mode_composite
+		  && (real_isdenormal (&ub, mode) || real_iszero (&ub)))
+		{
+		  // IBM extended denormals only have DFmode precision.
+		  REAL_VALUE_TYPE tmp, tmp2;
+		  real_convert (&tmp2, DFmode, &lh_ub);
+		  real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
+				  &dconstinf);
+		  real_convert (&ub, mode, &tmp);
+		}
+	      else
+		frange_nextafter (mode, ub, dconstinf);
 	    }
-	  else
-	    frange_nextafter (mode, ub, dconstinf);
 	}
-    }
 
-  r.set (type, lb, ub, op1.get_nan_state ());
+      frange tmp;
+      tmp.set (type, lb, ub, op1.get_nan_state ());
+      r.union_ (tmp);
+    }
 
   if (flag_trapping_math
       && MODE_HAS_INFINITIES (TYPE_MODE (type))
@@ -3266,6 +3272,15 @@ range_op_float_tests ()
   i0.union_ (i1);
   range_op_handler (FLOAT_EXPR).fold_range (r, float_type_node, i0, trange);
   ASSERT_EQ (r.num_pairs (), 2);
+
+  // Casting the double range [1,2] U [10,11] to float stays two pieces rather
+  // than collapsing to the hull [1, 11].
+  r0 = frange_float ("1.0", "2.0", double_type_node);
+  r1 = frange_float ("10.0", "11.0", double_type_node);
+  r0.union_ (r1);
+  r0.clear_nan ();
+  range_op_handler (CONVERT_EXPR).fold_range (r, float_type_node, r0, r0);
+  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.