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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.