[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