https://gcc.gnu.org/g:2c3ff1f475d11a5576adf4c72e8bd5b74ce5b060

commit r17-3148-g2c3ff1f475d11a5576adf4c72e8bd5b74ce5b060
Author: Aldy Hernandez <[email protected]>
Date:   Fri Aug 7 09:50:26 2026 +0000

    [frange] Convert the float to int 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 | 56 +++++++++++++++++++++++++++++++++------------------
 1 file changed, 36 insertions(+), 20 deletions(-)

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 75514c0603ee..156b4f766db9 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -2991,31 +2991,37 @@ operator_cast::fold_range (irange &r, tree type, const 
frange &op1,
       r.set_varying (type);
       return true;
     }
-  REAL_VALUE_TYPE lb, ub;
-  real_trunc (&lb, VOIDmode, &op1.lower_bound ());
-  real_trunc (&ub, VOIDmode, &op1.upper_bound ());
   REAL_VALUE_TYPE l, u;
   l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
-  if (real_less (&lb, &l))
-    {
-      r.set_varying (type);
-      return true;
-    }
   u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
-  if (real_less (&u, &ub))
-    {
-      r.set_varying (type);
-      return true;
-    }
-  bool fail = false;
-  wide_int wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
-  wide_int wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
-  if (fail)
+
+  r.set_undefined ();
+  for (unsigned i = 0; i < op1.num_pairs (); ++i)
     {
-      r.set_varying (type);
-      return true;
+      REAL_VALUE_TYPE lb, ub;
+      real_trunc (&lb, VOIDmode, &op1.lower_bound (i));
+      real_trunc (&ub, VOIDmode, &op1.upper_bound (i));
+      if (real_less (&lb, &l))
+       {
+         r.set_varying (type);
+         return true;
+       }
+      if (real_less (&u, &ub))
+       {
+         r.set_varying (type);
+         return true;
+       }
+      bool fail = false;
+      wide_int wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
+      wide_int wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
+      if (fail)
+       {
+         r.set_varying (type);
+         return true;
+       }
+      int_range<2> tmp (type, wlb, wub);
+      r.union_ (tmp);
     }
-  r.set (type, wlb, wub);
   return true;
 }
 
@@ -3281,6 +3287,16 @@ range_op_float_tests ()
   r0.clear_nan ();
   range_op_handler (CONVERT_EXPR).fold_range (r, float_type_node, r0, r0);
   ASSERT_EQ (r.num_pairs (), 2);
+
+  // Cast conversion of (int)([1.0,2.0] U [10.0,11.0]) stays two pieces.
+  r0 = frange_float ("1.0", "2.0");
+  r1 = frange_float ("10.0", "11.0");
+  r0.union_ (r1);
+  r0.clear_nan ();
+  int_range<2> ir, ir_op2;
+  range_op_handler (FIX_TRUNC_EXPR).fold_range (ir, integer_type_node,
+                                               r0, ir_op2);
+  ASSERT_EQ (ir.num_pairs (), 2);
 }
 
 } // namespace selftest

Reply via email to