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
