8a984d
commit 56c81132ccc6f468fa4fc29c536db060e18e9d87
8a984d
Author: Raphael Moreira Zinsly <rzinsly@linux.ibm.com>
8a984d
Date:   Tue Feb 23 14:14:37 2021 -0300
8a984d
8a984d
    powerpc: Add optimized ilogb* for POWER9
8a984d
    
8a984d
    The instructions xsxexpdp and xsxexpqp introduced on POWER9 extract
8a984d
    the exponent from a double-precision and quad-precision floating-point
8a984d
    respectively, thus they can be used to improve ilogb, ilogbf and ilogbf128.
8a984d
8a984d
diff --git a/sysdeps/powerpc/fpu/math_private.h b/sysdeps/powerpc/fpu/math_private.h
8a984d
index e642d6c8237578ea..5bbc468829062a48 100644
8a984d
--- a/sysdeps/powerpc/fpu/math_private.h
8a984d
+++ b/sysdeps/powerpc/fpu/math_private.h
8a984d
@@ -26,7 +26,28 @@
8a984d
 
8a984d
 #include_next <math_private.h>
8a984d
 
8a984d
-#if defined _ARCH_PWR9 && __HAVE_DISTINCT_FLOAT128
8a984d
+#ifdef _ARCH_PWR9
8a984d
+
8a984d
+#if __GNUC_PREREQ (8, 0)
8a984d
+# define _GL_HAS_BUILTIN_ILOGB 1
8a984d
+#elif defined __has_builtin
8a984d
+# define _GL_HAS_BUILTIN_ILOGB __has_builtin (__builtin_vsx_scalar_extract_exp)
8a984d
+#else
8a984d
+# define _GL_HAS_BUILTIN_ILOGB 0
8a984d
+#endif
8a984d
+
8a984d
+#define __builtin_test_dc_ilogbf __builtin_test_dc_ilogb
8a984d
+#define __builtin_ilogbf __builtin_ilogb
8a984d
+
8a984d
+#define __builtin_test_dc_ilogb(x, y) \
8a984d
+        __builtin_vsx_scalar_test_data_class_dp(x, y)
8a984d
+#define __builtin_ilogb(x) __builtin_vsx_scalar_extract_exp(x) - 0x3ff
8a984d
+
8a984d
+#define __builtin_test_dc_ilogbf128(x, y) \
8a984d
+        __builtin_vsx_scalar_test_data_class_qp(x, y)
8a984d
+#define __builtin_ilogbf128(x) __builtin_vsx_scalar_extract_expq(x) - 0x3fff
8a984d
+
8a984d
+#if __HAVE_DISTINCT_FLOAT128
8a984d
 extern __always_inline _Float128
8a984d
 __ieee754_sqrtf128 (_Float128 __x)
8a984d
 {
8a984d
@@ -35,6 +56,9 @@ __ieee754_sqrtf128 (_Float128 __x)
8a984d
   return __z;
8a984d
 }
8a984d
 #endif
8a984d
+#else /* !_ARCH_PWR9 */
8a984d
+#define _GL_HAS_BUILTIN_ILOGB 0
8a984d
+#endif
8a984d
 
8a984d
 #if defined _ARCH_PWR5X
8a984d
 
8a984d
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/w_ilogb_template.c b/sysdeps/powerpc/powerpc64/le/fpu/w_ilogb_template.c
8a984d
new file mode 100644
8a984d
index 0000000000000000..b5c1c0aa9db86f3d
8a984d
--- /dev/null
8a984d
+++ b/sysdeps/powerpc/powerpc64/le/fpu/w_ilogb_template.c
8a984d
@@ -0,0 +1,30 @@
8a984d
+#include <math.h>
8a984d
+#include <errno.h>
8a984d
+#include <limits.h>
8a984d
+#include <math_private.h>
8a984d
+#include <fenv.h>
8a984d
+
8a984d
+#if _GL_HAS_BUILTIN_ILOGB
8a984d
+int
8a984d
+M_DECL_FUNC (__ilogb) (FLOAT x)
8a984d
+{
8a984d
+  int r;
8a984d
+  /* Check for exceptional cases.  */
8a984d
+  if (! M_SUF(__builtin_test_dc_ilogb) (x, 0x7f))
8a984d
+    r = M_SUF (__builtin_ilogb) (x);
8a984d
+  else
8a984d
+    /* Fallback to the generic ilogb if x is NaN, Inf or subnormal.  */
8a984d
+    r = M_SUF (__ieee754_ilogb) (x);
8a984d
+  if (__builtin_expect (r == FP_ILOGB0, 0)
8a984d
+      || __builtin_expect (r == FP_ILOGBNAN, 0)
8a984d
+      || __builtin_expect (r == INT_MAX, 0))
8a984d
+    {
8a984d
+      __set_errno (EDOM);
8a984d
+      __feraiseexcept (FE_INVALID);
8a984d
+    }
8a984d
+  return r;
8a984d
+}
8a984d
+declare_mgen_alias (__ilogb, ilogb)
8a984d
+#else
8a984d
+#include <math/w_ilogb_template.c>
8a984d
+#endif
8a984d
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/w_ilogbl.c b/sysdeps/powerpc/powerpc64/le/fpu/w_ilogbl.c
8a984d
new file mode 100644
8a984d
index 0000000000000000..205f154f0089a269
8a984d
--- /dev/null
8a984d
+++ b/sysdeps/powerpc/powerpc64/le/fpu/w_ilogbl.c
8a984d
@@ -0,0 +1,4 @@
8a984d
+/* Skip the optimization for long double as ibm128 does not provide an
8a984d
+   optimized builtin. */
8a984d
+#include <math-type-macros-ldouble.h>
8a984d
+#include <math/w_ilogb_template.c>