Re: [PATCH] gimple-range-op: Use widen method even for sqrt reverse op [PR126534]
Aldy Hernandez <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Organization | 0xc0ffee (Drinkers Anonymous) |
| Message-ID | <[email protected]> |
On 2026-08-07 17:30, Jakub Jelinek wrote: > Hi! > > For glibc the target hook returns 0 for sqrt precision (i.e. 0.5ulp > precise), but we didn't apply the +-0.5ulp widening when doing > reverse op and so still came up with a wrong range, even with 0.5ulp > precision certain values around 25.0 result in sqrt (x) being 5.0. > Even if the hook returns non-zero, I'd say more reasonable handling > of it is that it is say worst case 1ulp (or 2ulps etc.) from the > correct result (i.e. half ulp precise), rather than just 1ulp from > mathematically exact result. > > So, the following patch uses the newly added widen method to add > this 0.5ulp before we feed it into frange_arithmetic. > > Ok for trunk if it passes bootstrap/regtest? > > 2026-08-07 Jakub Jelinek <[email protected]> > > PR tree-optimization/126534 > * gimple-range-op.cc (cfn_sqrt::op1_range): Widen lb or ub > by further 0.5ulp or 1ulp before squaring it. > > * gcc.dg/pr126534.c: New test. > > --- gcc/gimple-range-op.cc.jj 2026-03-27 10:17:14.167330201 +0100 > +++ gcc/gimple-range-op.cc 2026-08-07 17:11:25.720918034 +0200 > @@ -573,7 +573,10 @@ public: > frange_nextafter (TYPE_MODE (type), lb, dconstninf); > if (real_less (&dconst0, &lb)) > { > - REAL_VALUE_TYPE op = lb; > + frange wlhs (type, lb, dconstinf); > + wlhs.clear_nan (); > + wlhs.widen (type); > + REAL_VALUE_TYPE op = wlhs.lower_bound (); > frange_arithmetic (MULT_EXPR, type, lb, op, op, dconstninf); > } > else > @@ -587,7 +590,10 @@ public: > frange_nextafter (TYPE_MODE (type), ub, dconstinf); > if (real_isfinite (&ub)) > { > - REAL_VALUE_TYPE op = ub; > + frange wlhs (type, dconstninf, ub); > + wlhs.clear_nan (); > + wlhs.widen (type); > + REAL_VALUE_TYPE op = wlhs.upper_bound (); > frange_arithmetic (MULT_EXPR, type, ub, op, op, dconstinf); > } > else > --- gcc/testsuite/gcc.dg/pr126534.c.jj 2026-08-07 17:16:40.246010859 > +0200 > +++ gcc/testsuite/gcc.dg/pr126534.c 2026-08-07 17:16:24.296208995 +0200 > @@ -0,0 +1,45 @@ > +/* PR tree-optimization/126534 */ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +[[gnu::noipa]] int > +foo (double x) > +{ > + double y = __builtin_sqrt (x); > + if (y <= 5.0) > + { > + if (x > 25.0) > + return 1; > + return 2; > + } > + return 3; > +} > + > +[[gnu::noipa]] int > +bar (double x) > +{ > + double y = __builtin_sqrt (x); > + if (y >= 5.0) > + { > + if (x < 25.0) > + return 1; > + return 2; > + } > + return 3; > +} > + > +int > +main () > +{ > +#if __DBL_MANT_DIG__ == 53 && __DBL_MAX_EXP__ == 1024 && > __FLT_EVAL_METHOD__ == 0 > + volatile double x = 0x1.9000000000001p+4; > + volatile double y = 0x1.8ffffffffffffp+4; > + if (__builtin_sqrt (x) == 5.0 && __builtin_sqrt (y) == 5.0) > + { > + if (foo (0x1.9000000000001p+4) != 1) /* 25.000000000000004 */ > + __builtin_abort (); > + if (bar (0x1.8ffffffffffffp+4) != 1) /* 24.999999999999996 */ > + __builtin_abort (); > + } > +#endif > +} > > Jakub LGTM