[llvm-branch-commits] [libc] [libc][math] Qualify ceil functions to constexpr (PR #184948)

Muhammad Bassiouni via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Mar 5 21:15:28 PST 2026


https://github.com/bassiounix updated https://github.com/llvm/llvm-project/pull/184948

>From b6c06fd32dac427eedb6138bafed18e75115479f Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Fri, 6 Mar 2026 06:50:37 +0200
Subject: [PATCH 1/2] [libc][math] Qualify ceil functions to constexpr

---
 libc/src/__support/CPP/bit.h                  | 10 +--
 .../FPUtil/NearestIntegerOperations.h         | 16 ++---
 libc/src/__support/FPUtil/bfloat16.h          | 22 +++----
 .../__support/FPUtil/comparison_operations.h  | 14 ++--
 libc/src/__support/FPUtil/generic/add_sub.h   | 26 ++++----
 libc/src/__support/FPUtil/generic/div.h       |  8 +--
 libc/src/__support/FPUtil/generic/mul.h       |  8 +--
 libc/src/__support/FPUtil/rounding_mode.h     | 10 +--
 libc/src/__support/math/ceil.h                |  5 +-
 libc/src/__support/math/ceilbf16.h            |  2 +-
 libc/src/__support/math/ceilf.h               |  5 +-
 libc/src/__support/math/ceilf128.h            |  2 +-
 libc/src/__support/math/ceilf16.h             |  5 +-
 libc/src/__support/math/ceill.h               | 14 +++-
 libc/test/shared/shared_math_test.cpp         | 66 +++++++++++++++++--
 15 files changed, 141 insertions(+), 72 deletions(-)

diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h
index d4de6769e8637..aa340b380fd32 100644
--- a/libc/src/__support/CPP/bit.h
+++ b/libc/src/__support/CPP/bit.h
@@ -27,8 +27,9 @@ namespace cpp {
 #endif
 
 template <unsigned N>
-LIBC_INLINE static void inline_copy(const char *from, char *to) {
-#if __has_builtin(__builtin_memcpy_inline)
+LIBC_INLINE LIBC_CONSTEXPR void inline_copy(const char *from, char *to) {
+#if __has_builtin(__builtin_memcpy_inline) &&                                  \
+    !defined(LIBC_HAS_CONSTANT_EVALUATION)
   __builtin_memcpy_inline(to, from, N);
 #else
   for (unsigned i = 0; i < N; ++i)
@@ -39,14 +40,15 @@ LIBC_INLINE static void inline_copy(const char *from, char *to) {
 // This implementation of bit_cast requires trivially-constructible To, to avoid
 // UB in the implementation.
 template <typename To, typename From>
-LIBC_INLINE static constexpr cpp::enable_if_t<
+LIBC_INLINE constexpr cpp::enable_if_t<
     (sizeof(To) == sizeof(From)) &&
         cpp::is_trivially_constructible<To>::value &&
         cpp::is_trivially_copyable<To>::value &&
         cpp::is_trivially_copyable<From>::value,
     To>
 bit_cast(const From &from) {
-#if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC)
+#if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC) ||     \
+    defined(LIBC_HAS_CONSTANT_EVALUATION)
   return __builtin_bit_cast(To, from);
 #else
   To to{};
diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h
index 93166614cc12a..4637b46bc9473 100644
--- a/libc/src/__support/FPUtil/NearestIntegerOperations.h
+++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
 
 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE T trunc(T x) {
+LIBC_INLINE constexpr T trunc(T x) {
   using StorageType = typename FPBits<T>::StorageType;
   FPBits<T> bits(x);
 
@@ -52,7 +52,7 @@ LIBC_INLINE T trunc(T x) {
 }
 
 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE T ceil(T x) {
+LIBC_INLINE constexpr T ceil(T x) {
   using StorageType = typename FPBits<T>::StorageType;
   FPBits<T> bits(x);
 
@@ -95,7 +95,7 @@ LIBC_INLINE T ceil(T x) {
 }
 
 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE T floor(T x) {
+LIBC_INLINE constexpr T floor(T x) {
   FPBits<T> bits(x);
   if (bits.is_neg()) {
     return -ceil(-x);
@@ -105,7 +105,7 @@ LIBC_INLINE T floor(T x) {
 }
 
 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE T round(T x) {
+LIBC_INLINE constexpr T round(T x) {
   using StorageType = typename FPBits<T>::StorageType;
   FPBits<T> bits(x);
 
@@ -244,7 +244,7 @@ round_using_specific_rounding_mode(T x, int rnd) {
 }
 
 template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, T>
 round_using_current_rounding_mode(T x) {
   int rounding_mode = quick_get_round();
 
@@ -350,7 +350,7 @@ template <typename FloatType, typename IntType,
           cpp::enable_if_t<cpp::is_floating_point_v<FloatType> &&
                                cpp::is_integral_v<IntType>,
                            int> = 0>
-LIBC_INLINE IntType rounded_float_to_signed_integer(FloatType x) {
+LIBC_INLINE constexpr IntType rounded_float_to_signed_integer(FloatType x) {
   constexpr IntType INTEGER_MIN = (IntType(1) << (sizeof(IntType) * 8 - 1));
   constexpr IntType INTEGER_MAX = -(INTEGER_MIN + 1);
   FPBits<FloatType> bits(x);
@@ -390,7 +390,7 @@ template <typename FloatType, typename IntType,
           cpp::enable_if_t<cpp::is_floating_point_v<FloatType> &&
                                cpp::is_integral_v<IntType>,
                            int> = 0>
-LIBC_INLINE IntType round_to_signed_integer(FloatType x) {
+LIBC_INLINE constexpr IntType round_to_signed_integer(FloatType x) {
   return internal::rounded_float_to_signed_integer<FloatType, IntType>(
       round(x));
 }
@@ -399,7 +399,7 @@ template <typename FloatType, typename IntType,
           cpp::enable_if_t<cpp::is_floating_point_v<FloatType> &&
                                cpp::is_integral_v<IntType>,
                            int> = 0>
-LIBC_INLINE IntType
+LIBC_INLINE constexpr IntType
 round_to_signed_integer_using_current_rounding_mode(FloatType x) {
   return internal::rounded_float_to_signed_integer<FloatType, IntType>(
       round_using_current_rounding_mode(x));
diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index 7d64b441bf9b2..5c8f3b7e6c77a 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -68,27 +68,27 @@ struct BFloat16 {
     return static_cast<T>(static_cast<float>(*this));
   }
 
-  LIBC_INLINE bool operator==(BFloat16 other) const {
+  LIBC_INLINE constexpr bool operator==(BFloat16 other) const {
     return fputil::equals(*this, other);
   }
 
-  LIBC_INLINE bool operator!=(BFloat16 other) const {
+  LIBC_INLINE constexpr bool operator!=(BFloat16 other) const {
     return !fputil::equals(*this, other);
   }
 
-  LIBC_INLINE bool operator<(BFloat16 other) const {
+  LIBC_INLINE constexpr bool operator<(BFloat16 other) const {
     return fputil::less_than(*this, other);
   }
 
-  LIBC_INLINE bool operator<=(BFloat16 other) const {
+  LIBC_INLINE constexpr bool operator<=(BFloat16 other) const {
     return fputil::less_than_or_equals(*this, other);
   }
 
-  LIBC_INLINE bool operator>(BFloat16 other) const {
+  LIBC_INLINE constexpr bool operator>(BFloat16 other) const {
     return fputil::greater_than(*this, other);
   }
 
-  LIBC_INLINE bool operator>=(BFloat16 other) const {
+  LIBC_INLINE constexpr bool operator>=(BFloat16 other) const {
     return fputil::greater_than_or_equals(*this, other);
   }
 
@@ -98,23 +98,23 @@ struct BFloat16 {
     return result.get_val();
   }
 
-  LIBC_INLINE BFloat16 operator+(BFloat16 other) const {
+  LIBC_INLINE constexpr BFloat16 operator+(BFloat16 other) const {
     return fputil::generic::add<BFloat16>(*this, other);
   }
 
-  LIBC_INLINE BFloat16 operator-(BFloat16 other) const {
+  LIBC_INLINE constexpr BFloat16 operator-(BFloat16 other) const {
     return fputil::generic::sub<BFloat16>(*this, other);
   }
 
-  LIBC_INLINE BFloat16 operator*(BFloat16 other) const {
+  LIBC_INLINE constexpr BFloat16 operator*(BFloat16 other) const {
     return fputil::generic::mul<bfloat16>(*this, other);
   }
 
-  LIBC_INLINE BFloat16 operator/(BFloat16 other) const {
+  LIBC_INLINE constexpr BFloat16 operator/(BFloat16 other) const {
     return fputil::generic::div<bfloat16>(*this, other);
   }
 
-  LIBC_INLINE BFloat16 &operator*=(const BFloat16 &other) {
+  LIBC_INLINE constexpr BFloat16 &operator*=(const BFloat16 &other) {
     *this = *this * other;
     return *this;
   }
diff --git a/libc/src/__support/FPUtil/comparison_operations.h b/libc/src/__support/FPUtil/comparison_operations.h
index ff62ce085513b..01092b4ae6efe 100644
--- a/libc/src/__support/FPUtil/comparison_operations.h
+++ b/libc/src/__support/FPUtil/comparison_operations.h
@@ -26,8 +26,8 @@ namespace fputil {
 //    (iii) -inf != +inf
 // 3. Any comparison with NaN returns false
 template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x,
-                                                                       T y) {
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+equals(T x, T y) {
   using FPBits = FPBits<T>;
   FPBits x_bits(x);
   FPBits y_bits(y);
@@ -52,8 +52,8 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x,
 // 2. x < +inf (x != +inf)
 // 3. Any comparison with NaN return false
 template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
-                                                                          T y) {
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+less_than(T x, T y) {
   using FPBits = FPBits<T>;
   FPBits x_bits(x);
   FPBits y_bits(y);
@@ -87,7 +87,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
 // Implements compareSignalingGreater predicate
 // x < y => y > x
 template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
 greater_than(T x, T y) {
   return less_than(y, x);
 }
@@ -95,7 +95,7 @@ greater_than(T x, T y) {
 // Implements compareSignalingLessEqual predicate
 // x <= y => (x < y) || (x == y)
 template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
 less_than_or_equals(T x, T y) {
   return less_than(x, y) || equals(x, y);
 }
@@ -103,7 +103,7 @@ less_than_or_equals(T x, T y) {
 // Implements compareSignalingGreaterEqual predicate
 // x >= y => (x > y) || (x == y) => (y < x) || (x == y)
 template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
 greater_than_or_equals(T x, T y) {
   return less_than(y, x) || equals(x, y);
 }
diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index 9f3ecff0eb233..9ba3bb93228ff 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -27,10 +27,10 @@ namespace LIBC_NAMESPACE_DECL {
 namespace fputil::generic {
 
 template <bool IsSub, 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>
 add_or_sub(InType x, InType y) {
   using OutFPBits = FPBits<OutType>;
   using OutStorageType = typename OutFPBits::StorageType;
@@ -175,7 +175,7 @@ add_or_sub(InType x, InType y) {
 
     InStorageType aligned_min_mant = static_cast<InStorageType>(
         min_mant >> cpp::min(alignment, RESULT_MANTISSA_LEN));
-    bool aligned_min_mant_sticky;
+    bool aligned_min_mant_sticky{};
 
     if (alignment <= GUARD_BITS_LEN)
       aligned_min_mant_sticky = false;
@@ -201,19 +201,19 @@ add_or_sub(InType x, InType y) {
 }
 
 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>
 add(InType x, InType y) {
   return add_or_sub</*IsSub=*/false, OutType>(x, y);
 }
 
 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>
 sub(InType x, InType y) {
   return add_or_sub</*IsSub=*/true, OutType>(x, y);
 }
diff --git a/libc/src/__support/FPUtil/generic/div.h b/libc/src/__support/FPUtil/generic/div.h
index bf7d0b7112ca9..85026bb3fd40f 100644
--- a/libc/src/__support/FPUtil/generic/div.h
+++ b/libc/src/__support/FPUtil/generic/div.h
@@ -26,10 +26,10 @@ namespace LIBC_NAMESPACE_DECL {
 namespace fputil::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>
 div(InType x, InType y) {
   using OutFPBits = FPBits<OutType>;
   using OutStorageType = typename OutFPBits::StorageType;
diff --git a/libc/src/__support/FPUtil/generic/mul.h b/libc/src/__support/FPUtil/generic/mul.h
index 20d9a77792762..22c6859946180 100644
--- a/libc/src/__support/FPUtil/generic/mul.h
+++ b/libc/src/__support/FPUtil/generic/mul.h
@@ -25,10 +25,10 @@ namespace LIBC_NAMESPACE_DECL {
 namespace fputil::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>
 mul(InType x, InType y) {
   using OutFPBits = FPBits<OutType>;
   using OutStorageType = typename OutFPBits::StorageType;
diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index fdc84986a4781..92061ea13e203 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -80,7 +80,7 @@ LIBC_INLINE int quick_get_round() {
 
 } // namespace generic
 
-LIBC_INLINE static constexpr bool fenv_is_round_up() {
+LIBC_INLINE constexpr bool fenv_is_round_up() {
   if (cpp::is_constant_evaluated()) {
     return false;
   } else {
@@ -88,7 +88,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_up() {
   }
 }
 
-LIBC_INLINE static constexpr bool fenv_is_round_down() {
+LIBC_INLINE constexpr bool fenv_is_round_down() {
   if (cpp::is_constant_evaluated()) {
     return false;
   } else {
@@ -96,7 +96,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_down() {
   }
 }
 
-LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
+LIBC_INLINE constexpr bool fenv_is_round_to_nearest() {
   if (cpp::is_constant_evaluated()) {
     return true;
   } else {
@@ -104,7 +104,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
   }
 }
 
-LIBC_INLINE static constexpr bool fenv_is_round_to_zero() {
+LIBC_INLINE constexpr bool fenv_is_round_to_zero() {
   if (cpp::is_constant_evaluated()) {
     return false;
   } else {
@@ -113,7 +113,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_zero() {
 }
 
 // Quick free standing get rounding mode based on the above observations.
-LIBC_INLINE static constexpr int quick_get_round() {
+LIBC_INLINE constexpr int quick_get_round() {
   if (cpp::is_constant_evaluated()) {
     return FE_TONEAREST;
   } else {
diff --git a/libc/src/__support/math/ceil.h b/libc/src/__support/math/ceil.h
index 71b89a76c1d25..a00337a597df1 100644
--- a/libc/src/__support/math/ceil.h
+++ b/libc/src/__support/math/ceil.h
@@ -15,8 +15,9 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
-LIBC_INLINE double ceil(double x) {
-#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC
+LIBC_INLINE LIBC_CONSTEXPR double ceil(double x) {
+#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) &&                       \
+    !defined(LIBC_HAS_CONSTANT_EVALUATION)
   return __builtin_ceil(x);
 #else
   return fputil::ceil(x);
diff --git a/libc/src/__support/math/ceilbf16.h b/libc/src/__support/math/ceilbf16.h
index bdb7dfee6a325..05d21f895efb0 100644
--- a/libc/src/__support/math/ceilbf16.h
+++ b/libc/src/__support/math/ceilbf16.h
@@ -16,7 +16,7 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
-LIBC_INLINE bfloat16 ceilbf16(bfloat16 x) { return fputil::ceil(x); }
+LIBC_INLINE constexpr bfloat16 ceilbf16(bfloat16 x) { return fputil::ceil(x); }
 
 } // namespace math
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/math/ceilf.h b/libc/src/__support/math/ceilf.h
index 58710b9bfc126..25d1180f746df 100644
--- a/libc/src/__support/math/ceilf.h
+++ b/libc/src/__support/math/ceilf.h
@@ -15,8 +15,9 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
-LIBC_INLINE float ceilf(float x) {
-#ifdef __LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC
+LIBC_INLINE LIBC_CONSTEXPR float ceilf(float x) {
+#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) &&                       \
+    !defined(LIBC_HAS_CONSTANT_EVALUATION)
   return __builtin_ceilf(x);
 #else
   return fputil::ceil(x);
diff --git a/libc/src/__support/math/ceilf128.h b/libc/src/__support/math/ceilf128.h
index d717379745371..8877594d58d68 100644
--- a/libc/src/__support/math/ceilf128.h
+++ b/libc/src/__support/math/ceilf128.h
@@ -19,7 +19,7 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
-LIBC_INLINE float128 ceilf128(float128 x) { return fputil::ceil(x); }
+LIBC_INLINE constexpr float128 ceilf128(float128 x) { return fputil::ceil(x); }
 
 } // namespace math
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/math/ceilf16.h b/libc/src/__support/math/ceilf16.h
index c5a8e432b1fe6..899cab6abdda6 100644
--- a/libc/src/__support/math/ceilf16.h
+++ b/libc/src/__support/math/ceilf16.h
@@ -21,9 +21,10 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
-LIBC_INLINE float16 ceilf16(float16 x) {
+LIBC_INLINE LIBC_CONSTEXPR float16 ceilf16(float16 x) {
 #if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) &&                       \
-    defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
+    defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS) &&                           \
+    !defined(LIBC_HAS_CONSTANT_EVALUATION)
   return fputil::cast<float16>(__builtin_ceilf(x));
 #else
   return fputil::ceil(x);
diff --git a/libc/src/__support/math/ceill.h b/libc/src/__support/math/ceill.h
index 8b1287a024ccf..4cec6b8e0671f 100644
--- a/libc/src/__support/math/ceill.h
+++ b/libc/src/__support/math/ceill.h
@@ -15,7 +15,19 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
-LIBC_INLINE long double ceill(long double x) { return fputil::ceil(x); }
+// TODO(bassiounix): Re-enable long double tests on X86 once float80 is complete
+#if !(defined(linux) && (defined(__x86_64__) || defined(__i386__)))
+
+LIBC_INLINE constexpr long double ceill(long double x) {
+
+#else
+
+LIBC_INLINE long double ceill(long double x) {
+
+#endif
+
+  return fputil::ceil(x);
+}
 
 } // namespace math
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 793c06c2a7c69..aafed26dbe15a 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -8,14 +8,72 @@
 
 #define LIBC_ENABLE_CONSTEXPR 1
 
+// TODO(bassiounix): Cleanup include headers once constexpr refactor is done.
+#include "shared/math/ceil.h"
+#include "shared/math/ceilbf16.h"
+#include "shared/math/ceilf.h"
+#include "shared/math/ceilf128.h"
+#include "shared/math/ceilf16.h"
+#include "shared/math/ceill.h"
 #include "shared/math/log.h"
 
 #ifdef LIBC_HAS_CONSTANT_EVALUATION
 
-//===-- Double Tests ------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+//                       Double Tests
+//===----------------------------------------------------------------------===//
 
+static_assert(0x0p+0 == LIBC_NAMESPACE::shared::ceil(0.0));
 static_assert(0x0p+0 == LIBC_NAMESPACE::shared::log(1.0));
 
+//===----------------------------------------------------------------------===//
+//                       Float Tests
+//===----------------------------------------------------------------------===//
+
+static_assert(0x0p+0f == LIBC_NAMESPACE::shared::ceilf(0.0f));
+
+//===----------------------------------------------------------------------===//
+//                       Float16 Tests
+//===----------------------------------------------------------------------===//
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+static_assert(0x0p+0f16 == LIBC_NAMESPACE::shared::ceilf16(0.0f16));
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+//===----------------------------------------------------------------------===//
+//                       Long Double Tests
+//===----------------------------------------------------------------------===//
+
+// Temporarily disable long double tests on x86 and x86_64
+// TODO(bassiounix): Re-enable long double tests on X86 once GSoC26 float80/128
+// project is complete.
+#if !(defined(linux) && (defined(__x86_64__) || defined(__i386__)))
+
+static_assert(0x0p+0L == LIBC_NAMESPACE::shared::ceill(0.0L));
+
+#endif // defined(linux) && (defined(__x86_64__) || defined(__i386__))
+
+//===----------------------------------------------------------------------===//
+//                       Float128 Tests
+//===----------------------------------------------------------------------===//
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+
+static_assert(float128(0x0p+0) ==
+              LIBC_NAMESPACE::shared::ceilf128(float128(0.0)));
+
+#endif // LIBC_TYPES_HAS_FLOAT128
+
+//===----------------------------------------------------------------------===//
+//                       BFloat16 Tests
+//===----------------------------------------------------------------------===//
+
+static_assert(bfloat16(0x0p+0) ==
+              LIBC_NAMESPACE::shared::ceilbf16(bfloat16(0.0)));
+
+//===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 
 #endif // LIBC_HAS_CONSTANT_EVALUATION
@@ -130,7 +188,6 @@ TEST(LlvmLibcSharedMathTest, AllFloat16) {
                                                        &canonicalizef16_x));
   EXPECT_FP_EQ(0x0p+0f16, canonicalizef16_cx);
 
-  EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::ceilf16(0.0f16));
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::fdimf16(0.0f16, 0.0f16));
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::floorf16(0.0f16));
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::fmaxf16(0.0f16, 0.0f16));
@@ -221,7 +278,6 @@ TEST(LlvmLibcSharedMathTest, AllFloat) {
 
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::bf16mulf(0.0f, 0.0f));
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::bf16subf(0.0f, 0.0f));
-  EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::ceilf(0.0f));
   EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::fdimf(0.0f, 0.0f));
   EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::floorf(0.0f));
   EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::fmaxf(0.0f, 0.0f));
@@ -283,7 +339,6 @@ TEST(LlvmLibcSharedMathTest, AllDouble) {
 
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::bf16mul(0.0, 0.0));
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::bf16sub(0.0, 0.0));
-  EXPECT_FP_EQ(0x0p+0, LIBC_NAMESPACE::shared::ceil(0.0));
   EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::shared::fadd(0.0, 0.0));
   EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::shared::fdim(0.0, 0.0));
   EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::shared::floor(0.0));
@@ -322,7 +377,6 @@ TEST(LlvmLibcSharedMathTest, AllLongDouble) {
   EXPECT_FP_EQ(0x0p+0L, canonicalizel_cx);
 
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::bf16mull(0.0L, 0.0L));
-  EXPECT_FP_EQ(0x0p+0L, LIBC_NAMESPACE::shared::ceill(0.0L));
   EXPECT_FP_EQ(0x0p+0L, LIBC_NAMESPACE::shared::faddl(0.0L, 0.0L));
   EXPECT_FP_EQ(0x0p+0L, LIBC_NAMESPACE::shared::fdiml(0.0L, 0.0L));
   EXPECT_FP_EQ(0x0p+0L, LIBC_NAMESPACE::shared::floorl(0.0L));
@@ -386,7 +440,6 @@ TEST(LlvmLibcSharedMathTest, AllFloat128) {
                                   float128(0.0), float128(0.0), float128(0.0)));
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::bf16mulf128(
                                   float128(0.0), float128(0.0)));
-  EXPECT_FP_EQ(float128(0.0), LIBC_NAMESPACE::shared::ceilf128(float128(0.0)));
   EXPECT_FP_EQ(float128(0.0),
                LIBC_NAMESPACE::shared::faddf128(float128(0.0), float128(0.0)));
   EXPECT_FP_EQ(float128(0.0), LIBC_NAMESPACE::shared::floorf128(float128(0.0)));
@@ -436,7 +489,6 @@ TEST(LlvmLibcSharedMathTest, AllBFloat16) {
   EXPECT_FP_EQ(bfloat16(5.0), LIBC_NAMESPACE::shared::bf16addl(2L, 3L));
   EXPECT_FP_EQ(bfloat16(10.0),
                LIBC_NAMESPACE::shared::bf16fmaf(2.0f, 3.0f, 4.0f));
-  EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::ceilbf16(bfloat16(0.0)));
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::floorbf16(bfloat16(0.0)));
   EXPECT_FP_EQ(bfloat16(0.0),
                LIBC_NAMESPACE::shared::fdimbf16(bfloat16(0.0), bfloat16(0.0)));

>From 54e4eeb0fb7e5b3dc29b62a496e6a75e5b96ad99 Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Fri, 6 Mar 2026 07:15:14 +0200
Subject: [PATCH 2/2] reapply static

---
 libc/src/__support/CPP/bit.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h
index aa340b380fd32..0ba8b9219a317 100644
--- a/libc/src/__support/CPP/bit.h
+++ b/libc/src/__support/CPP/bit.h
@@ -40,7 +40,7 @@ LIBC_INLINE LIBC_CONSTEXPR void inline_copy(const char *from, char *to) {
 // This implementation of bit_cast requires trivially-constructible To, to avoid
 // UB in the implementation.
 template <typename To, typename From>
-LIBC_INLINE constexpr cpp::enable_if_t<
+LIBC_INLINE static constexpr cpp::enable_if_t<
     (sizeof(To) == sizeof(From)) &&
         cpp::is_trivially_constructible<To>::value &&
         cpp::is_trivially_copyable<To>::value &&



More information about the llvm-branch-commits mailing list