Re: [PATCH] range-op-float: Fix up inf handling in reverse narrowing float to float cast [PR126464]
Torbjorn SVENSSON <[email protected]> Tue, 4 Aug 2026 14:13:19 +0200
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
Hello, This causes regression on most (all?) arm-none-eabi targets. Testing gcc.dg/pr126464.c doing compile Executing on host: /build/r16-9480-g967a69a03886ebd6/bin/arm-none-eabi-gcc /build/gcc_src/gcc/testsuite/gcc.dg/pr126464.c -mthumb -march=armv6s-m -mcpu=cortex-m0 -mfloat-abi=soft -mfpu=auto -dumpbase "" -fdiagnostics-plain-output -O2 --specs=rdimon.specs -Wl,--start-group -lc -lm -Wl,--end-group --specs=nosys.specs -Wl,--allow-multiple-definition -Wl,-u,_isatty,-u,_fstat -Wl,-wrap,exit -Wl,-wrap,_exit -Wl,-wrap,main -Wl,-wrap,abort -Wl,gcc_tg.o -lm -T qemu.ld -o ./pr126464.exe (timeout = 800) ... status 0 FAIL: gcc.dg/pr126464.c (test for excess errors) Excess errors: /build/gcc_src/gcc/testsuite/gcc.dg/pr126464.c:56:3: warning: floating constant exceeds range of 'long double' [-Woverflow] /build/gcc_src/gcc/testsuite/gcc.dg/pr126464.c:57:7: warning: floating constant exceeds range of 'long double' [-Woverflow] /build/gcc_src/gcc/testsuite/gcc.dg/pr126464.c:58:7: warning: floating constant exceeds range of 'long double' [-Woverflow] /build/gcc_src/gcc/testsuite/gcc.dg/pr126464.c:58:7: warning: floating constant exceeds range of 'long double' [-Woverflow] /build/gcc_src/gcc/testsuite/gcc.dg/pr126464.c:59:11: warning: floating constant exceeds range of 'long double' [-Woverflow] /build/gcc_src/gcc/testsuite/gcc.dg/pr126464.c:59:11: warning: floating constant exceeds range of 'long double' [-Woverflow] I've seen this in both r16-9480-g967a69a03886ebd6 and r17-2833-g32657f29f91871. Kind regards, Torbjörn On 2026-07-30 09:31, Richard Biener wrote: > On Wed, Jul 29, 2026 at 9:05 PM Jakub Jelinek <[email protected]> wrote: >> >> Hi! >> >> The following testcase is miscompiled since my r16-1108 change. >> The problem is if we handle a reverse of a narrowing float to float cast >> (in the example there are double -> float and long double -> double >> cast) and the lhs range is [-inf, -inf] or [+inf, +inf] (note, regardless >> of whether some NaNs are allowed or not, so not necessarily >> lhs.known_isinf ()), then handling that range in the wider type also >> as [-inf, -inf] or [+inf, +inf] is wrong, e.g. for the double -> float >> conversion, [-inf, -0x0.ffffff8p+128] double range could map to just >> that [-inf, -inf]. We have already float_widen_lhs_range function >> but that just extends the range by +/-1ulp or 0.5ulp if the bounds >> are finite. If the range isn't singleton (except for optional NaN), >> then the minimum (or maximum) finite is already in the range, so this just >> extends the case where they are singleton. >> I don't know how to portably figure out that 0x0.ffffff8p+128 for >> double -> float (especially when in float_widen_lhs_range we don't know >> yet the wider type), so the patch just uses the +/-1ulp extension (i.e. >> [-inf, min_finite] or [+inf, max_finite] case. >> >> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/16.2? > > LGTM. > > Richard. > >> 2026-07-29 Jakub Jelinek <[email protected]> >> >> PR tree-optimization/126464 >> * range-op-float.cc (float_widen_lhs_range): Add also_inf argument >> defaulted to false, if true, extend even lb of +inf and ub of -inf. >> (operator_cast::op1_range): Adjust float_widen_lhs_range caller. >> >> * gcc.dg/pr126464.c: New test. >> >> --- gcc/range-op-float.cc.jj 2026-05-06 17:43:14.667261681 +0200 >> +++ gcc/range-op-float.cc 2026-07-29 14:10:58.343016627 +0200 >> @@ -2374,14 +2374,14 @@ zero_to_inf_range (REAL_VALUE_TYPE &lb, >> in each direction. See PR109008 for more details. */ >> >> static frange >> -float_widen_lhs_range (tree type, const frange &lhs) >> +float_widen_lhs_range (tree type, const frange &lhs, bool also_inf = false) >> { >> frange ret = lhs; >> if (lhs.known_isnan ()) >> return ret; >> REAL_VALUE_TYPE lb = lhs.lower_bound (); >> REAL_VALUE_TYPE ub = lhs.upper_bound (); >> - if (real_isfinite (&lb)) >> + if (real_isfinite (&lb) || (also_inf && !real_isneg (&lb))) >> { >> frange_nextafter (TYPE_MODE (type), lb, dconstninf); >> if (real_isinf (&lb)) >> @@ -2395,7 +2395,9 @@ float_widen_lhs_range (tree type, const >> lb = dconstm1; >> SET_REAL_EXP (&lb, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1); >> } >> - if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type))) >> + if (!flag_rounding_math >> + && !MODE_COMPOSITE_P (TYPE_MODE (type)) >> + && (!also_inf || real_isfinite (&lhs.lower_bound ()))) >> { >> /* If not -frounding-math nor IBM double double, actually widen >> just by 0.5ulp rather than 1ulp. */ >> @@ -2404,7 +2406,7 @@ float_widen_lhs_range (tree type, const >> real_arithmetic (&lb, RDIV_EXPR, &tem, &dconst2); >> } >> } >> - if (real_isfinite (&ub)) >> + if (real_isfinite (&ub) || (also_inf && real_isneg (&ub))) >> { >> frange_nextafter (TYPE_MODE (type), ub, dconstinf); >> if (real_isinf (&ub)) >> @@ -2413,7 +2415,9 @@ float_widen_lhs_range (tree type, const >> ub = dconst1; >> SET_REAL_EXP (&ub, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1); >> } >> - if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type))) >> + if (!flag_rounding_math >> + && !MODE_COMPOSITE_P (TYPE_MODE (type)) >> + && (!also_inf || real_isfinite (&lhs.upper_bound ()))) >> { >> /* If not -frounding-math nor IBM double double, actually widen >> just by 0.5ulp rather than 1ulp. */ >> @@ -3022,7 +3026,7 @@ operator_cast::op1_range (frange &r, tre >> else >> { >> rm = true; >> - wlhs = float_widen_lhs_range (lhs_type, lhs); >> + wlhs = float_widen_lhs_range (lhs_type, lhs, true); >> } >> auto save_flag_rounding_math = flag_rounding_math; >> flag_rounding_math = rm; >> --- gcc/testsuite/gcc.dg/pr126464.c.jj 2026-07-29 14:29:17.256893972 +0200 >> +++ gcc/testsuite/gcc.dg/pr126464.c 2026-07-29 14:30:04.502287539 +0200 >> @@ -0,0 +1,61 @@ >> +/* PR tree-optimization/126464 */ >> +/* { dg-do run } */ >> +/* { dg-options "-O2" } */ >> +/* { dg-add-options ieee } */ >> +/* { dg-skip-if "not IEEE float" { "pdp11-*-*" } } */ >> + >> +[[gnu::noipa]] double >> +foo (double x) >> +{ >> + float y = (float) x; >> + >> + if (y == -__builtin_inff ()) >> + return x * 0.5; >> + return y; >> +} >> + >> +[[gnu::noipa]] long double >> +bar (long double x) >> +{ >> + double y = (double) x; >> + >> + if (y == __builtin_inf ()) >> + return x * 0.5L; >> + return y; >> +} >> + >> +[[gnu::noipa]] double >> +baz (double x) >> +{ >> + float y = (float) x; >> + >> + if (y == __builtin_inff ()) >> + return x * 0.5; >> + return y; >> +} >> + >> +[[gnu::noipa]] long double >> +qux (long double x) >> +{ >> + double y = (double) x; >> + >> + if (y == -__builtin_inf ()) >> + return x * 0.5L; >> + return y; >> +} >> + >> +int >> +main () >> +{ >> + if (!__builtin_isinf ((double) 1e300) >> + && __builtin_isinf ((float) 1e300) >> + && (foo (-1e300) != -5e299 >> + || baz (1e300) != 5e299)) >> + __builtin_abort (); >> + >> + if (!__builtin_isinf ((long double) 1e4000L) >> + && __builtin_isinf ((double) 1e4000L) >> + && (bar (1e4000L) != 5e3999L >> + || qux (-1e4000L) != -5e3999L)) >> + __builtin_abort (); >> +} >> >> Jakub >>