[PATCH 2/4] math: Optimize double ilogb/llogb
Wilco Dijkstra
Wilco.Dijkstra@arm.com
Mon Apr 28 15:25:22 GMT 2025
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.
> +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