[PATCH 2/4] math: Optimize double ilogb/llogb

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Mon Apr 28 17:03:41 GMT 2025



On 28/04/25 12:25, Wilco Dijkstra wrote:
> Hi Adhemerval,
> 
> This looks like a good improvement - a few minor comments:
> 
>> +static inline RET_TYPE
> 
> You actually don't want to inline this special case since it forces a frame
> due to the call to __feraiseexcept. The resulting code is significantly less
> efficient than after patch 1.

Ack, I will sent an updated version with all your suggestion.

> 
>> +invalid_ret (RET_TYPE r)
>> +{
>> +  __set_errno (EDOM);
>> +  __feraiseexcept (FE_INVALID);
>> +  return r;
>> +}
> 
> Should these special error handling cases go into math_err[f].c? Or would this
> be the only use of it?
> 
> +RET_TYPE
> +IMPL_NAME (double x)
> +{
> +  uint64_t ux = asuint64 (x);
> +  int ex = (ux & ~SIGN_MASK) >> MANTISSA_WIDTH;
> +  if (ex == 0) /* zero or subnormal */
> 
> I'd use __glibc_unlikely since GCC's static predictor appears to think zero is more common...
> 
> +    {
> +      /* Clear sign and exponent */
> +      ux <<= 12;
> +      if (ux == 0)
> +	return invalid_ret (RET_LOGB0);
> +      /* subnormal  */
> +      return (RET_TYPE)-1023 - stdc_leading_zeros (ux);
> +    }
> +  if (ex == EXPONENT_MASK >> MANTISSA_WIDTH) /* NaN or Inf */
> 
> And here.
> 
> +    return invalid_ret (ux << 12 ? RET_LOGBNAN : RET_LOGMAX);
> +  return ex - 1023;
> +}
> 
> With these changes the function is half the size and the common case is as good
> as it could possibly be:
> 
> 0000000000000040 <__ilogb>:
>   40:	9e660000 	fmov	x0, d0
>   44:	d374f801 	ubfx	x1, x0, #52, #11
>   48:	340000e1 	cbz	w1, 64 <__ilogb+0x24>
>   4c:	510ffc20 	sub	w0, w1, #0x3ff
>   50:	711ffc3f 	cmp	w1, #0x7ff
>   54:	54000040 	b.eq	5c <__ilogb+0x1c>  // b.none
>   58:	d65f03c0 	ret
> 
> Cheers,
> Wilco



More information about the Libc-alpha mailing list