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
