[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