[libc-commits] [libc] [libc] Make ffma functions constexpr (PR #226872)

via libc-commits libc-commits at lists.llvm.org
Sun Sep 27 19:50:47 PDT 2026


https://github.com/user1342234 created https://github.com/llvm/llvm-project/pull/226872

Make ffma functions constexpr along with tests

Notes:
`libc/src/__support/FPUtil/generic/FMA.h` - The new check supports more types such as emulated `Float128`

>From b1061a4a768313d6073f81e7939182826d6063c8 Mon Sep 17 00:00:00 2001
From: abu <ayywarepremium at gmail.com>
Date: Sun, 27 Sep 2026 18:08:03 -0700
Subject: [PATCH 1/3] Check zero bits without using operator==

---
 libc/src/__support/FPUtil/generic/FMA.h | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index f08f92d8febc0a..795d8227b4b1e6 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -29,10 +29,10 @@ namespace fputil {
 namespace generic {
 
 template <typename OutType, typename InType>
-LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
-                                 cpp::is_floating_point_v<InType> &&
-                                 sizeof(OutType) <= sizeof(InType),
-                             OutType>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
+                                           cpp::is_floating_point_v<InType> &&
+                                           sizeof(OutType) <= sizeof(InType),
+                                       OutType>
 fma(InType x, InType y, InType z);
 
 // TODO(lntue): Implement fmaf that is correctly rounded to all rounding modes.
@@ -105,10 +105,10 @@ shift_mantissa(int shift_length, T &mant) {
 } // namespace internal
 
 template <typename OutType, typename InType>
-LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
-                                 cpp::is_floating_point_v<InType> &&
-                                 sizeof(OutType) <= sizeof(InType),
-                             OutType>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
+                                           cpp::is_floating_point_v<InType> &&
+                                           sizeof(OutType) <= sizeof(InType),
+                                       OutType>
 fma(InType x, InType y, InType z) {
   using OutFPBits = FPBits<OutType>;
   using OutStorageType = typename OutFPBits::StorageType;
@@ -157,7 +157,7 @@ fma(InType x, InType y, InType z) {
     }
   }
 
-  if (LIBC_UNLIKELY(x == 0 || y == 0 || z == 0))
+  if (LIBC_UNLIKELY(x_bits.is_zero() || y_bits.is_zero() || z_bits.is_zero()))
     return cast<OutType>(x * y + z);
 
   int x_exp = 0;

>From c5c462dae0445c5449f12e2f8221979d63d5be31 Mon Sep 17 00:00:00 2001
From: abu <ayywarepremium at gmail.com>
Date: Sun, 27 Sep 2026 18:10:39 -0700
Subject: [PATCH 2/3] Add constexpr support

---
 libc/src/__support/FPUtil/FMA.h    | 2 +-
 libc/src/__support/math/ffma.h     | 2 +-
 libc/src/__support/math/ffmaf128.h | 2 +-
 libc/src/__support/math/ffmal.h    | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/FMA.h b/libc/src/__support/FPUtil/FMA.h
index 2cafb4c0974e31..189232190acf03 100644
--- a/libc/src/__support/FPUtil/FMA.h
+++ b/libc/src/__support/FPUtil/FMA.h
@@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
 
 template <typename OutType, typename InType>
-LIBC_INLINE OutType fma(InType x, InType y, InType z) {
+LIBC_INLINE constexpr OutType fma(InType x, InType y, InType z) {
   return generic::fma<OutType>(x, y, z);
 }
 
diff --git a/libc/src/__support/math/ffma.h b/libc/src/__support/math/ffma.h
index 64431e8bec4070..d924921a906c04 100644
--- a/libc/src/__support/math/ffma.h
+++ b/libc/src/__support/math/ffma.h
@@ -16,7 +16,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE float ffma(double x, double y, double z) {
+LIBC_INLINE constexpr float ffma(double x, double y, double z) {
   return fputil::fma<float>(x, y, z);
 }
 
diff --git a/libc/src/__support/math/ffmaf128.h b/libc/src/__support/math/ffmaf128.h
index 5714421a60ba94..f3e2ec3c8c2f12 100644
--- a/libc/src/__support/math/ffmaf128.h
+++ b/libc/src/__support/math/ffmaf128.h
@@ -21,7 +21,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE float ffmaf128(float128 x, float128 y, float128 z) {
+LIBC_INLINE constexpr float ffmaf128(float128 x, float128 y, float128 z) {
   return fputil::fma<float>(x, y, z);
 }
 
diff --git a/libc/src/__support/math/ffmal.h b/libc/src/__support/math/ffmal.h
index b03c45ea25cf2d..c5328fb62d5e9c 100644
--- a/libc/src/__support/math/ffmal.h
+++ b/libc/src/__support/math/ffmal.h
@@ -17,7 +17,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE float ffmal(long double x, long double y, long double z) {
+LIBC_INLINE constexpr float ffmal(long double x, long double y, long double z) {
   return fputil::fma<float>(x, y, z);
 }
 

>From 9535fc27203c2ee8018ead7ed27c2b9eee74a11c Mon Sep 17 00:00:00 2001
From: abu <ayywarepremium at gmail.com>
Date: Sun, 27 Sep 2026 18:11:02 -0700
Subject: [PATCH 3/3] Add shared constexpr tests

---
 libc/test/shared/shared_math_constexpr_test.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libc/test/shared/shared_math_constexpr_test.cpp b/libc/test/shared/shared_math_constexpr_test.cpp
index ec7f99a9ff40c0..9848b5f2a4d68b 100644
--- a/libc/test/shared/shared_math_constexpr_test.cpp
+++ b/libc/test/shared/shared_math_constexpr_test.cpp
@@ -31,6 +31,7 @@ static_assert(1.0 == LIBC_NAMESPACE::shared::fabs(-1.0));
 static_assert(1.0 == LIBC_NAMESPACE::shared::fdim(1.0, 0.0));
 static_assert(bfloat16(0.0) == LIBC_NAMESPACE::shared::bf16sub(0.0, 0.0));
 static_assert(0.0f == LIBC_NAMESPACE::shared::fdiv(0.0, 1.0));
+static_assert(0.0f == LIBC_NAMESPACE::shared::ffma(0.0, 0.0, 0.0));
 static_assert(1.0 == LIBC_NAMESPACE::shared::floor(1.2));
 static_assert(2.0 == LIBC_NAMESPACE::shared::fmaximum_mag_num(1.0, 2.0));
 static_assert(0.0 == LIBC_NAMESPACE::shared::log(1.0));
@@ -316,6 +317,7 @@ static_assert(1.0L == LIBC_NAMESPACE::shared::fabsl(-1.0L));
 static_assert(0.0f == LIBC_NAMESPACE::shared::faddl(0.0L, 0.0L));
 static_assert(1.0L == LIBC_NAMESPACE::shared::fdiml(1.0L, 0.0L));
 static_assert(0.0f == LIBC_NAMESPACE::shared::fdivl(0.0L, 1.0L));
+static_assert(0.0f == LIBC_NAMESPACE::shared::ffmal(0.0L, 0.0, 0.0L));
 static_assert(0.0L == LIBC_NAMESPACE::shared::floorl(0.0L));
 static_assert(bfloat16(0.0) == LIBC_NAMESPACE::shared::bf16subl(0.0L, 0.0L));
 static_assert(0.0L == LIBC_NAMESPACE::shared::sqrtl(0.0L));
@@ -473,6 +475,9 @@ static_assert(0.0f ==
               LIBC_NAMESPACE::shared::faddf128(float128(0.0), float128(0.0)));
 static_assert(0.0f ==
               LIBC_NAMESPACE::shared::fdivf128(float128(0.0), float128(1.0)));
+static_assert(0.0f == LIBC_NAMESPACE::shared::ffmaf128(float128(0.0),
+                                                       float128(0.0),
+                                                       float128(0.0)));
 static_assert(bfloat16(0.0) ==
               LIBC_NAMESPACE::shared::bf16subf128(float128(0.0),
                                                   float128(0.0)));



More information about the libc-commits mailing list