[libc++] Use builtins in more math.h functions.

Not using builtins doesn't always imply worse code,
but for e. g. isinf, this is 30%+ faster.

Before:
name        time/op
BM_isinf     2.14ns ± 2%

After:
name        time/op
BM_isinf     1.33ns ± 2%

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D88854

GitOrigin-RevId: c81d52997ac0d1206ea0fd4935964f4c8661daed
diff --git a/include/math.h b/include/math.h
index 1603d57..b22c927 100644
--- a/include/math.h
+++ b/include/math.h
@@ -318,7 +318,11 @@
 bool
 __libcpp_signbit(_A1 __lcpp_x) _NOEXCEPT
 {
+#if __has_builtin(__builtin_signbit)
+    return __builtin_signbit(__lcpp_x);
+#else
     return signbit(__lcpp_x);
+#endif
 }
 
 #undef signbit
@@ -380,7 +384,12 @@
 int
 __libcpp_fpclassify(_A1 __lcpp_x) _NOEXCEPT
 {
+#if __has_builtin(__builtin_fpclassify)
+  return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL,
+                                FP_ZERO, __lcpp_x);
+#else
     return fpclassify(__lcpp_x);
+#endif
 }
 
 #undef fpclassify
@@ -426,7 +435,11 @@
 bool
 __libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT
 {
+#if __has_builtin(__builtin_isfinite)
+    return __builtin_isfinite(__lcpp_x);
+#else
     return isfinite(__lcpp_x);
+#endif
 }
 
 #undef isfinite
@@ -460,7 +473,11 @@
 bool
 __libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT
 {
+#if __has_builtin(__builtin_isinf)
+    return __builtin_isinf(__lcpp_x);
+#else
     return isinf(__lcpp_x);
+#endif
 }
 
 #undef isinf
@@ -556,7 +573,11 @@
 bool
 __libcpp_isnormal(_A1 __lcpp_x) _NOEXCEPT
 {
+#if __has_builtin(__builtin_isnormal)
+    return __builtin_isnormal(__lcpp_x);
+#else
     return isnormal(__lcpp_x);
+#endif
 }
 
 #undef isnormal
@@ -1101,11 +1122,19 @@
 
 inline _LIBCPP_INLINE_VISIBILITY float copysign(float __lcpp_x,
                                                 float __lcpp_y) _NOEXCEPT {
+#if __has_builtin(__builtin_copysignf)
+  return __builtin_copysignf(__lcpp_x, __lcpp_y);
+#else
   return ::copysignf(__lcpp_x, __lcpp_y);
+#endif
 }
 inline _LIBCPP_INLINE_VISIBILITY long double
 copysign(long double __lcpp_x, long double __lcpp_y) _NOEXCEPT {
+#if __has_builtin(__builtin_copysignl)
+  return __builtin_copysignl(__lcpp_x, __lcpp_y);
+#else
   return ::copysignl(__lcpp_x, __lcpp_y);
+#endif
 }
 
 template <class _A1, class _A2>
@@ -1121,7 +1150,11 @@
     typedef typename std::__promote<_A1, _A2>::type __result_type;
     static_assert((!(std::_IsSame<_A1, __result_type>::value &&
                      std::_IsSame<_A2, __result_type>::value)), "");
+#if __has_builtin(__builtin_copysign)
+    return __builtin_copysign((__result_type)__lcpp_x, (__result_type)__lcpp_y);
+#else
     return ::copysign((__result_type)__lcpp_x, (__result_type)__lcpp_y);
+#endif
 }
 
 // erf
@@ -1187,8 +1220,22 @@
 
 // fma
 
-inline _LIBCPP_INLINE_VISIBILITY float       fma(float __lcpp_x, float __lcpp_y, float __lcpp_z) _NOEXCEPT                   {return ::fmaf(__lcpp_x, __lcpp_y, __lcpp_z);}
-inline _LIBCPP_INLINE_VISIBILITY long double fma(long double __lcpp_x, long double __lcpp_y, long double __lcpp_z) _NOEXCEPT {return ::fmal(__lcpp_x, __lcpp_y, __lcpp_z);}
+inline _LIBCPP_INLINE_VISIBILITY float       fma(float __lcpp_x, float __lcpp_y, float __lcpp_z) _NOEXCEPT
+{
+#if __has_builtin(__builtin_fmaf)
+    return __builtin_fmaf(__lcpp_x, __lcpp_y, __lcpp_z);
+#else
+    return ::fmaf(__lcpp_x, __lcpp_y, __lcpp_z);
+#endif
+}
+inline _LIBCPP_INLINE_VISIBILITY long double fma(long double __lcpp_x, long double __lcpp_y, long double __lcpp_z) _NOEXCEPT
+{
+#if __has_builtin(__builtin_fmal)
+    return __builtin_fmal(__lcpp_x, __lcpp_y, __lcpp_z);
+#else
+    return ::fmal(__lcpp_x, __lcpp_y, __lcpp_z);
+#endif
+}
 
 template <class _A1, class _A2, class _A3>
 inline _LIBCPP_INLINE_VISIBILITY
@@ -1205,7 +1252,11 @@
     static_assert((!(std::_IsSame<_A1, __result_type>::value &&
                      std::_IsSame<_A2, __result_type>::value &&
                      std::_IsSame<_A3, __result_type>::value)), "");
+#if __has_builtin(__builtin_fma)
+    return __builtin_fma((__result_type)__lcpp_x, (__result_type)__lcpp_y, (__result_type)__lcpp_z);
+#else
     return ::fma((__result_type)__lcpp_x, (__result_type)__lcpp_y, (__result_type)__lcpp_z);
+#endif
 }
 
 // fmax
@@ -1293,23 +1344,65 @@
 
 // llrint
 
-inline _LIBCPP_INLINE_VISIBILITY long long llrint(float __lcpp_x) _NOEXCEPT       {return ::llrintf(__lcpp_x);}
-inline _LIBCPP_INLINE_VISIBILITY long long llrint(long double __lcpp_x) _NOEXCEPT {return ::llrintl(__lcpp_x);}
+inline _LIBCPP_INLINE_VISIBILITY long long llrint(float __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_llrintf)
+    return __builtin_llrintf(__lcpp_x);
+#else
+    return ::llrintf(__lcpp_x);
+#endif
+}
+inline _LIBCPP_INLINE_VISIBILITY long long llrint(long double __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_llrintl)
+    return __builtin_llrintl(__lcpp_x);
+#else
+    return ::llrintl(__lcpp_x);
+#endif
+}
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
 typename std::enable_if<std::is_integral<_A1>::value, long long>::type
-llrint(_A1 __lcpp_x) _NOEXCEPT {return ::llrint((double)__lcpp_x);}
+llrint(_A1 __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_llrint)
+    return __builtin_llrint((double)__lcpp_x);
+#else
+    return ::llrint((double)__lcpp_x);
+#endif
+}
 
 // llround
 
-inline _LIBCPP_INLINE_VISIBILITY long long llround(float __lcpp_x) _NOEXCEPT       {return ::llroundf(__lcpp_x);}
-inline _LIBCPP_INLINE_VISIBILITY long long llround(long double __lcpp_x) _NOEXCEPT {return ::llroundl(__lcpp_x);}
+inline _LIBCPP_INLINE_VISIBILITY long long llround(float __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_llroundf)
+    return __builtin_llroundf(__lcpp_x);
+#else
+    return ::llroundf(__lcpp_x);
+#endif
+}
+inline _LIBCPP_INLINE_VISIBILITY long long llround(long double __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_llroundl)
+    return __builtin_llroundl(__lcpp_x);
+#else
+    return ::llroundl(__lcpp_x);
+#endif
+}
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
 typename std::enable_if<std::is_integral<_A1>::value, long long>::type
-llround(_A1 __lcpp_x) _NOEXCEPT {return ::llround((double)__lcpp_x);}
+llround(_A1 __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_llround)
+    return __builtin_llround((double)__lcpp_x);
+#else
+    return ::llround((double)__lcpp_x);
+#endif
+}
 
 // log1p
 
@@ -1343,23 +1436,65 @@
 
 // lrint
 
-inline _LIBCPP_INLINE_VISIBILITY long lrint(float __lcpp_x) _NOEXCEPT       {return ::lrintf(__lcpp_x);}
-inline _LIBCPP_INLINE_VISIBILITY long lrint(long double __lcpp_x) _NOEXCEPT {return ::lrintl(__lcpp_x);}
+inline _LIBCPP_INLINE_VISIBILITY long lrint(float __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_lrintf)
+    return __builtin_lrintf(__lcpp_x);
+#else
+    return ::lrintf(__lcpp_x);
+#endif
+}
+inline _LIBCPP_INLINE_VISIBILITY long lrint(long double __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_lrintl)
+    return __builtin_lrintl(__lcpp_x);
+#else
+    return ::lrintl(__lcpp_x);
+#endif
+}
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
 typename std::enable_if<std::is_integral<_A1>::value, long>::type
-lrint(_A1 __lcpp_x) _NOEXCEPT {return ::lrint((double)__lcpp_x);}
+lrint(_A1 __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_lrint)
+    return __builtin_lrint((double)__lcpp_x);
+#else
+    return ::lrint((double)__lcpp_x);
+#endif
+}
 
 // lround
 
-inline _LIBCPP_INLINE_VISIBILITY long lround(float __lcpp_x) _NOEXCEPT       {return ::lroundf(__lcpp_x);}
-inline _LIBCPP_INLINE_VISIBILITY long lround(long double __lcpp_x) _NOEXCEPT {return ::lroundl(__lcpp_x);}
+inline _LIBCPP_INLINE_VISIBILITY long lround(float __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_lroundf)
+    return __builtin_lroundf(__lcpp_x);
+#else
+    return ::lroundf(__lcpp_x);
+#endif
+}
+inline _LIBCPP_INLINE_VISIBILITY long lround(long double __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_lroundl)
+    return __builtin_lroundl(__lcpp_x);
+#else
+    return ::lroundl(__lcpp_x);
+#endif
+}
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
 typename std::enable_if<std::is_integral<_A1>::value, long>::type
-lround(_A1 __lcpp_x) _NOEXCEPT {return ::lround((double)__lcpp_x);}
+lround(_A1 __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_lround)
+    return __builtin_lround((double)__lcpp_x);
+#else
+    return ::lround((double)__lcpp_x);
+#endif
+}
 
 // nan
 
@@ -1448,23 +1583,65 @@
 
 // rint
 
-inline _LIBCPP_INLINE_VISIBILITY float       rint(float __lcpp_x) _NOEXCEPT       {return ::rintf(__lcpp_x);}
-inline _LIBCPP_INLINE_VISIBILITY long double rint(long double __lcpp_x) _NOEXCEPT {return ::rintl(__lcpp_x);}
+inline _LIBCPP_INLINE_VISIBILITY float       rint(float __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_rintf)
+    return __builtin_rintf(__lcpp_x);
+#else
+    return ::rintf(__lcpp_x);
+#endif
+}
+inline _LIBCPP_INLINE_VISIBILITY long double rint(long double __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_rintl)
+    return __builtin_rintl(__lcpp_x);
+#else
+    return ::rintl(__lcpp_x);
+#endif
+}
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
 typename std::enable_if<std::is_integral<_A1>::value, double>::type
-rint(_A1 __lcpp_x) _NOEXCEPT {return ::rint((double)__lcpp_x);}
+rint(_A1 __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_rint)
+    return __builtin_rint((double)__lcpp_x);
+#else
+    return ::rint((double)__lcpp_x);
+#endif
+}
 
 // round
 
-inline _LIBCPP_INLINE_VISIBILITY float       round(float __lcpp_x) _NOEXCEPT       {return ::roundf(__lcpp_x);}
-inline _LIBCPP_INLINE_VISIBILITY long double round(long double __lcpp_x) _NOEXCEPT {return ::roundl(__lcpp_x);}
+inline _LIBCPP_INLINE_VISIBILITY float       round(float __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_round)
+    return __builtin_round(__lcpp_x);
+#else
+    return ::round(__lcpp_x);
+#endif
+}
+inline _LIBCPP_INLINE_VISIBILITY long double round(long double __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_roundl)
+    return __builtin_roundl(__lcpp_x);
+#else
+    return ::roundl(__lcpp_x);
+#endif
+}
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
 typename std::enable_if<std::is_integral<_A1>::value, double>::type
-round(_A1 __lcpp_x) _NOEXCEPT {return ::round((double)__lcpp_x);}
+round(_A1 __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_round)
+    return __builtin_round((double)__lcpp_x);
+#else
+    return ::round((double)__lcpp_x);
+#endif
+}
 
 // scalbln
 
@@ -1498,13 +1675,34 @@
 
 // trunc
 
-inline _LIBCPP_INLINE_VISIBILITY float       trunc(float __lcpp_x) _NOEXCEPT       {return ::truncf(__lcpp_x);}
-inline _LIBCPP_INLINE_VISIBILITY long double trunc(long double __lcpp_x) _NOEXCEPT {return ::truncl(__lcpp_x);}
+inline _LIBCPP_INLINE_VISIBILITY float       trunc(float __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_trunc)
+    return __builtin_trunc(__lcpp_x);
+#else
+    return ::trunc(__lcpp_x);
+#endif
+}
+inline _LIBCPP_INLINE_VISIBILITY long double trunc(long double __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_truncl)
+    return __builtin_truncl(__lcpp_x);
+#else
+    return ::truncl(__lcpp_x);
+#endif
+}
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
 typename std::enable_if<std::is_integral<_A1>::value, double>::type
-trunc(_A1 __lcpp_x) _NOEXCEPT {return ::trunc((double)__lcpp_x);}
+trunc(_A1 __lcpp_x) _NOEXCEPT
+{
+#if __has_builtin(__builtin_trunc)
+    return __builtin_trunc((double)__lcpp_x);
+#else
+    return ::trunc((double)__lcpp_x);
+#endif
+}
 
 } // extern "C++"