[libc-commits] [libc] [libc][math] Add gcc-7 to 9 compatibility for shared math. (PR #197868)

via libc-commits libc-commits at lists.llvm.org
Fri May 15 08:43:36 PDT 2026


https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/197868

>From e0c77bfd0b8e695764981ab205cf66a8399631c9 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 15 May 2026 05:16:53 +0000
Subject: [PATCH 1/2] [libc][math] Add gcc-7 to 9 compatibility for shared
 math.

---
 .../modules/LLVMLibCCompileOptionRules.cmake  |  5 +-
 libc/cmake/modules/LLVMLibCTestRules.cmake    |  5 +-
 libc/src/__support/CPP/bit.h                  |  8 +--
 libc/src/__support/FPUtil/BasicOperations.h   |  4 +-
 .../FPUtil/DivisionAndRemainderOperations.h   | 11 ++--
 libc/src/__support/FPUtil/FEnvImpl.h          | 19 +++---
 libc/src/__support/FPUtil/FPBits.h            |  5 +-
 libc/src/__support/FPUtil/Hypot.h             | 50 +++++++++-------
 .../FPUtil/NearestIntegerOperations.h         |  5 +-
 libc/src/__support/FPUtil/NormalFloat.h       | 19 +++---
 libc/src/__support/FPUtil/dyadic_float.h      | 11 ++--
 libc/src/__support/FPUtil/generic/FMA.h       |  2 +-
 libc/src/__support/FPUtil/generic/FMod.h      | 13 ++--
 libc/src/__support/FPUtil/generic/add_sub.h   | 14 +++--
 libc/src/__support/FPUtil/generic/div.h       |  8 +--
 libc/src/__support/FPUtil/generic/sqrt.h      | 30 +++++-----
 .../FPUtil/generic/sqrt_80_bit_long_double.h  |  4 +-
 libc/src/__support/FPUtil/rounding_mode.h     | 16 +++--
 libc/src/__support/FPUtil/x86_64/FEnvImpl.h   | 11 ++--
 .../FPUtil/x86_64/fenv_mxcsr_utils.h          |  3 +-
 .../__support/FPUtil/x86_64/fenv_x86_common.h | 29 +++++----
 .../__support/FPUtil/x86_64/fenv_x87_utils.h  |  7 ++-
 libc/src/__support/big_int.h                  | 24 +++++---
 libc/src/__support/integer_to_string.h        |  6 +-
 libc/src/__support/macros/attributes.h        | 13 ++++
 libc/src/__support/macros/optimization.h      |  6 ++
 libc/src/__support/math/acos.h                |  2 +-
 libc/src/__support/math/acosf.h               |  2 +-
 libc/src/__support/math/acoshf.h              |  2 +-
 libc/src/__support/math/asinf.h               |  2 +-
 libc/src/__support/math/asinhf.h              |  2 +-
 libc/src/__support/math/atan.h                |  2 +-
 libc/src/__support/math/atan2.h               |  2 +-
 libc/src/__support/math/atan2f.h              |  2 +-
 libc/src/__support/math/atan2f128.h           | 60 +++++++++----------
 libc/src/__support/math/atanf.h               |  4 +-
 libc/src/__support/math/atanhf.h              |  2 +-
 libc/src/__support/math/cbrt.h                |  2 +-
 libc/src/__support/math/cbrtf.h               |  2 +-
 libc/src/__support/math/cos.h                 |  2 +-
 libc/src/__support/math/cosf.h                |  4 +-
 libc/src/__support/math/coshf.h               |  2 +-
 libc/src/__support/math/cospif.h              |  2 +-
 libc/src/__support/math/erff.h                |  2 +-
 libc/src/__support/math/exp10.h               |  2 +-
 libc/src/__support/math/exp10f.h              |  2 +-
 libc/src/__support/math/exp10m1f.h            |  2 +-
 libc/src/__support/math/exp2.h                |  2 +-
 libc/src/__support/math/exp2f.h               |  2 +-
 libc/src/__support/math/exp2m1f.h             |  2 +-
 libc/src/__support/math/expf.h                |  2 +-
 libc/src/__support/math/expm1.h               |  2 +-
 libc/src/__support/math/expm1f.h              |  2 +-
 libc/src/__support/math/rsqrtf.h              |  2 +-
 libc/src/__support/math/sin.h                 |  2 +-
 libc/src/__support/math/sinhf.h               |  2 +-
 libc/src/__support/math/tan.h                 |  4 +-
 libc/src/__support/math_extras.h              |  4 +-
 libc/src/__support/str_to_integer.h           |  5 +-
 libc/src/string/memory_utils/op_generic.h     |  3 +-
 libc/src/string/memory_utils/utils.h          |  4 ++
 .../memory_utils/x86_64/inline_memcpy.h       |  2 +-
 .../memory_utils/x86_64/inline_strlen.h       |  6 +-
 63 files changed, 274 insertions(+), 204 deletions(-)

diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
index 2fae55997cabb..86edb989ddff0 100644
--- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
+++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
@@ -297,7 +297,10 @@ function(_get_common_compile_options output_var flags)
     list(APPEND compile_options "-Wno-pedantic")
     list(APPEND compile_options "-Wimplicit-fallthrough")
     list(APPEND compile_options "-Wwrite-strings")
-    list(APPEND compile_options "-Wextra-semi")
+    if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
+       (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0"))
+      list(APPEND compile_options "-Wextra-semi")
+    endif()
     if(NOT CMAKE_COMPILER_IS_GNUCXX)
       list(APPEND compile_options "-Wnewline-eof")
       list(APPEND compile_options "-Wnonportable-system-include-path")
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index 034396cba158c..8fc66eb9e1b39 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -59,9 +59,12 @@ function(_get_common_test_compile_options output_var c_test flags)
       list(APPEND compile_options "-Wno-gnu-imaginary-constant")
     endif()
     list(APPEND compile_options "-Wno-pedantic")
+    if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
+       (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0"))
+      list(APPEND compile_options "-Wextra-semi")
+    endif()
     if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
       list(APPEND compile_options "-Wstrict-prototypes")
-      list(APPEND compile_options "-Wextra-semi")
       list(APPEND compile_options "-Wnewline-eof")
       list(APPEND compile_options "-Wnonportable-system-include-path")
       list(APPEND compile_options "-Wthread-safety")
diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h
index 0f71b475bf560..d65d76d229db8 100644
--- a/libc/src/__support/CPP/bit.h
+++ b/libc/src/__support/CPP/bit.h
@@ -114,14 +114,14 @@ countr_zero(T value) {
   // Bisection method.
   unsigned zero_bits = 0;
   unsigned shift = cpp::numeric_limits<T>::digits >> 1;
-  T mask = cpp::numeric_limits<T>::max() >> shift;
+  T mask = static_cast<T>(cpp::numeric_limits<T>::max() >> shift);
   while (shift) {
     if ((value & mask) == 0) {
-      value >>= shift;
+      value = static_cast<T>(value >> shift);
       zero_bits |= shift;
     }
     shift >>= 1;
-    mask >>= shift;
+    mask = static_cast<T>(mask >> shift);
   }
   return static_cast<int>(zero_bits);
 }
@@ -162,7 +162,7 @@ countl_zero(T value) {
   unsigned zero_bits = 0;
   for (unsigned shift = cpp::numeric_limits<T>::digits >> 1; shift;
        shift >>= 1) {
-    T tmp = value >> shift;
+    T tmp = static_cast<T>(value >> shift);
     if (tmp)
       value = tmp;
     else
diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h
index 5b81b921296a0..d22eb6a1be873 100644
--- a/libc/src/__support/FPUtil/BasicOperations.h
+++ b/libc/src/__support/FPUtil/BasicOperations.h
@@ -407,8 +407,8 @@ setpayload(T &res, T pl) {
   }
 
   using StorageType = typename FPBits::StorageType;
-  StorageType v(pl_bits.get_explicit_mantissa() >>
-                (FPBits::FRACTION_LEN - pl_exp));
+  StorageType v = static_cast<StorageType>(pl_bits.get_explicit_mantissa() >>
+                                           (FPBits::FRACTION_LEN - pl_exp));
 
   if constexpr (IsSignaling)
     res = FPBits::signaling_nan(Sign::POS, v).get_val();
diff --git a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
index bc22a2331f12d..a5a83e4f389f3 100644
--- a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
+++ b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
@@ -55,14 +55,15 @@ LIBC_INLINE constexpr T remquo(T x, T y, int &q) {
 
   NormalFloat<T> normalx(xbits), normaly(ybits);
   int exp = normalx.exponent - normaly.exponent;
-  typename NormalFloat<T>::StorageType mx = normalx.mantissa,
-                                       my = normaly.mantissa;
+  using StorageType = typename NormalFloat<T>::StorageType;
+  StorageType mx = normalx.mantissa, my = normaly.mantissa;
 
   q = 0;
   while (exp >= 0) {
     unsigned shift_count = 0;
-    typename NormalFloat<T>::StorageType n = mx;
-    for (shift_count = 0; n < my; n <<= 1, ++shift_count)
+    StorageType n = mx;
+    for (shift_count = 0; n < my;
+         n = static_cast<StorageType>(n << 1), ++shift_count)
       ;
 
     if (static_cast<int>(shift_count) > exp)
@@ -72,7 +73,7 @@ LIBC_INLINE constexpr T remquo(T x, T y, int &q) {
     if (0 <= exp && exp < QUOTIENT_LSB_BITS)
       q |= (1 << exp);
 
-    mx = n - my;
+    mx = static_cast<StorageType>(n - my);
     if (mx == 0) {
       q = result_sign.is_neg() ? -q : q;
       return LIBC_NAMESPACE::fputil::copysign(T(0.0), x);
diff --git a/libc/src/__support/FPUtil/FEnvImpl.h b/libc/src/__support/FPUtil/FEnvImpl.h
index a21f511bd72b8..6f9852fa6c852 100644
--- a/libc/src/__support/FPUtil/FEnvImpl.h
+++ b/libc/src/__support/FPUtil/FEnvImpl.h
@@ -122,8 +122,13 @@ LIBC_INLINE int set_env(const fenv_t *) { return 0; }
 
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
+#if LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
+#define LIBC_FENV_CONSTEXPR constexpr
+#else
+#define LIBC_FENV_CONSTEXPR
+#endif
 
-LIBC_INLINE static constexpr int
+LIBC_INLINE static LIBC_FENV_CONSTEXPR int
 clear_except_if_required([[maybe_unused]] int excepts) {
   if (cpp::is_constant_evaluated()) {
     return 0;
@@ -136,7 +141,7 @@ clear_except_if_required([[maybe_unused]] int excepts) {
   }
 }
 
-LIBC_INLINE static constexpr int
+LIBC_INLINE static LIBC_FENV_CONSTEXPR int
 set_except_if_required([[maybe_unused]] int excepts) {
   if (cpp::is_constant_evaluated()) {
     return 0;
@@ -149,7 +154,7 @@ set_except_if_required([[maybe_unused]] int excepts) {
   }
 }
 
-LIBC_INLINE static constexpr int
+LIBC_INLINE static LIBC_FENV_CONSTEXPR int
 raise_except_if_required([[maybe_unused]] int excepts) {
   if (cpp::is_constant_evaluated()) {
     return 0;
@@ -162,13 +167,13 @@ raise_except_if_required([[maybe_unused]] int excepts) {
   }
 }
 
-LIBC_INLINE static constexpr void
+LIBC_INLINE static LIBC_FENV_CONSTEXPR void
 set_errno_if_required([[maybe_unused]] int err) {
-  if (!cpp::is_constant_evaluated()) {
-#ifndef LIBC_MATH_HAS_NO_ERRNO
+  if (cpp::is_constant_evaluated()) {
+    return;
+  } else {
     if (math_errhandling & MATH_ERRNO)
       libc_errno = err;
-#endif // LIBC_MATH_HAS_NO_ERRNO
   }
 }
 
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 7028fd4f38950..1f2df57307dac 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -757,7 +757,7 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
     int lz =
         UP::FRACTION_LEN + 1 - (UP::STORAGE_LEN - cpp::countl_zero(number));
 
-    number <<= lz;
+    number = static_cast<StorageType>(number << lz);
     ep -= lz;
 
     if (LIBC_LIKELY(ep >= 0)) {
@@ -765,7 +765,8 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
       result.set_significand(number);
       result.set_biased_exponent(static_cast<StorageType>(ep + 1));
     } else {
-      result.set_significand(number >> static_cast<unsigned>(-ep));
+      result.set_significand(
+          static_cast<StorageType>(number >> static_cast<unsigned>(-ep)));
     }
     return RetT(result.uintval());
   }
diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 292140065c754..a3d20cce71132 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -29,7 +29,8 @@ template <typename T>
 LIBC_INLINE T find_leading_one(T mant, int &shift_length) {
   shift_length = 0;
   if (mant > 0) {
-    shift_length = (sizeof(mant) * 8) - 1 - cpp::countl_zero(mant);
+    shift_length = static_cast<int>(
+        (sizeof(mant) * 8) - 1 - static_cast<size_t>(cpp::countl_zero(mant)));
   }
   return static_cast<T>((T(1) << shift_length));
 }
@@ -156,8 +157,8 @@ LIBC_INLINE T hypot(T x, T y) {
   // Add an extra bit to simplify the final rounding bit computation.
   constexpr StorageType ONE = StorageType(1) << (FPBits_t::FRACTION_LEN + 1);
 
-  a_mant <<= 1;
-  b_mant <<= 1;
+  a_mant = static_cast<StorageType>(a_mant << 1);
+  b_mant = static_cast<StorageType>(b_mant << 1);
 
   StorageType leading_one;
   int y_mant_width;
@@ -207,39 +208,43 @@ LIBC_INLINE T hypot(T x, T y) {
     } else {
       // For denormal result, we simply move the leading bit of the result to
       // the left by 1.
-      leading_one <<= 1;
+      leading_one = static_cast<StorageType>(leading_one << 1);
       ++y_mant_width;
     }
   }
 
   StorageType y_new = leading_one;
-  StorageType r = static_cast<StorageType>(sum >> y_mant_width) - leading_one;
-  StorageType tail_bits = static_cast<StorageType>(sum) & (leading_one - 1);
-
-  for (StorageType current_bit = leading_one >> 1; current_bit;
-       current_bit >>= 1) {
-    r = static_cast<StorageType>((r << 1) +
+  StorageType r = static_cast<StorageType>(
+      static_cast<StorageType>(sum >> y_mant_width) - leading_one);
+  StorageType tail_bits =
+      static_cast<StorageType>(static_cast<StorageType>(sum) &
+                               static_cast<StorageType>(leading_one - 1));
+
+  for (StorageType current_bit = static_cast<StorageType>(leading_one >> 1);
+       current_bit; current_bit = static_cast<StorageType>(current_bit >> 1)) {
+    r = static_cast<StorageType>(static_cast<StorageType>(r << 1) +
                                  ((tail_bits & current_bit) ? 1 : 0));
-    StorageType tmp = static_cast<StorageType>((y_new << 1)) +
-                      current_bit; // 2*y_new(n - 1) + 2^(-n)
+    StorageType tmp =
+        static_cast<StorageType>(static_cast<StorageType>(y_new << 1) +
+                                 current_bit); // 2*y_new(n - 1) + 2^(-n)
     if (r >= tmp) {
-      r -= tmp;
-      y_new += current_bit;
+      r = static_cast<StorageType>(r - tmp);
+      y_new = static_cast<StorageType>(y_new + current_bit);
     }
   }
 
-  bool round_bit = y_new & StorageType(1);
-  bool lsb = y_new & StorageType(2);
+  bool round_bit = (y_new & StorageType(1)) != 0;
+  bool lsb = (y_new & StorageType(2)) != 0;
 
   if (y_new >= ONE) {
-    y_new -= ONE;
+    y_new = static_cast<StorageType>(y_new - ONE);
 
     if (out_exp == 0) {
       out_exp = 1;
     }
   }
 
-  y_new >>= 1;
+  y_new = static_cast<StorageType>(y_new >> 1);
 
   // Round to the nearest, tie to even.
   int round_mode = quick_get_round();
@@ -247,16 +252,16 @@ LIBC_INLINE T hypot(T x, T y) {
   case FE_TONEAREST:
     // Round to nearest, ties to even
     if (round_bit && (lsb || sticky_bits || (r != 0)))
-      ++y_new;
+      y_new = static_cast<StorageType>(y_new + 1);
     break;
   case FE_UPWARD:
     if (round_bit || sticky_bits || (r != 0))
-      ++y_new;
+      y_new = static_cast<StorageType>(y_new + 1);
     break;
   }
 
   if (y_new >= (ONE >> 1)) {
-    y_new -= ONE >> 1;
+    y_new = static_cast<StorageType>(y_new - (ONE >> 1));
     ++out_exp;
     if (out_exp >= FPBits_t::MAX_BIASED_EXPONENT) {
       if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
@@ -265,7 +270,8 @@ LIBC_INLINE T hypot(T x, T y) {
     }
   }
 
-  y_new |= static_cast<StorageType>(out_exp) << FPBits_t::FRACTION_LEN;
+  y_new = static_cast<StorageType>(
+      y_new | (static_cast<StorageType>(out_exp) << FPBits_t::FRACTION_LEN));
 
   if (!(round_bit || sticky_bits || (r != 0)))
     fputil::clear_except_if_required(FE_INEXACT);
diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h
index 4637b46bc9473..f5d12eec353bd 100644
--- a/libc/src/__support/FPUtil/NearestIntegerOperations.h
+++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h
@@ -212,8 +212,9 @@ round_using_specific_rounding_mode(T x, int rnd) {
   // If exponent is 0, trimSize will be equal to the mantissa width, and
   // truncIsOdd` will not be correct. So, we handle it as a special case
   // below.
-  StorageType trunc_is_odd =
-      new_bits.get_mantissa() & (StorageType(1) << trim_size);
+  StorageType trunc_is_odd = static_cast<StorageType>(
+      new_bits.get_mantissa() &
+      static_cast<StorageType>(StorageType(1) << trim_size));
 
   switch (rnd) {
   case FP_INT_DOWNWARD:
diff --git a/libc/src/__support/FPUtil/NormalFloat.h b/libc/src/__support/FPUtil/NormalFloat.h
index 5123a3e217f72..35b345ac7b06d 100644
--- a/libc/src/__support/FPUtil/NormalFloat.h
+++ b/libc/src/__support/FPUtil/NormalFloat.h
@@ -52,8 +52,8 @@ template <typename T> struct NormalFloat {
       return;
 
     unsigned normalization_shift = evaluate_normalization_shift(mantissa);
-    mantissa <<= normalization_shift;
-    exponent -= normalization_shift;
+    mantissa = static_cast<StorageType>(mantissa << normalization_shift);
+    exponent -= static_cast<int32_t>(normalization_shift);
   }
 
   LIBC_INLINE constexpr explicit NormalFloat(T x) {
@@ -114,20 +114,21 @@ template <typename T> struct NormalFloat {
       if (shift <= FPBits<T>::FRACTION_LEN + 1) {
         // Generate a subnormal number. Might lead to loss of precision.
         // We round to nearest and round halfway cases to even.
-        const StorageType shift_out_mask =
-            static_cast<StorageType>(StorageType(1) << shift) - 1;
-        const StorageType shift_out_value = mantissa & shift_out_mask;
+        const StorageType shift_out_mask = static_cast<StorageType>(
+            static_cast<StorageType>(StorageType(1) << shift) - 1);
+        const StorageType shift_out_value =
+            static_cast<StorageType>(mantissa & shift_out_mask);
         const StorageType halfway_value =
             static_cast<StorageType>(StorageType(1) << (shift - 1));
         result.set_biased_exponent(0);
-        result.set_mantissa(mantissa >> shift);
+        result.set_mantissa(static_cast<StorageType>(mantissa >> shift));
         StorageType new_mantissa = result.get_mantissa();
         if (shift_out_value > halfway_value) {
-          new_mantissa += 1;
+          new_mantissa = static_cast<StorageType>(new_mantissa + 1);
         } else if (shift_out_value == halfway_value) {
           // Round to even.
           if (result.get_mantissa() & 0x1)
-            new_mantissa += 1;
+            new_mantissa = static_cast<StorageType>(new_mantissa + 1);
         }
         result.set_mantissa(new_mantissa);
         // Adding 1 to mantissa can lead to overflow. This can only happen if
@@ -173,7 +174,7 @@ template <typename T> struct NormalFloat {
   LIBC_INLINE constexpr unsigned evaluate_normalization_shift(StorageType m) {
     unsigned shift = 0;
     for (; (ONE & m) == 0 && (shift < FPBits<T>::FRACTION_LEN);
-         m <<= 1, ++shift)
+         m = static_cast<StorageType>(m << 1), ++shift)
       ;
     return shift;
   }
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 8ce041247716b..e1d5f361751aa 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -124,7 +124,7 @@ template <size_t Bits> struct DyadicFloat {
   LIBC_INLINE constexpr DyadicFloat &shift_left(unsigned shift_length) {
     if (shift_length < Bits) {
       exponent -= static_cast<int>(shift_length);
-      mantissa <<= shift_length;
+      mantissa = static_cast<MantissaType>(mantissa << shift_length);
     } else {
       exponent = 0;
       mantissa = MantissaType(0);
@@ -146,7 +146,7 @@ template <size_t Bits> struct DyadicFloat {
 
   // Assume that it is already normalized.  Output the unbiased exponent.
   LIBC_INLINE constexpr int get_unbiased_exponent() const {
-    return exponent + (Bits - 1);
+    return exponent + static_cast<int>(Bits - 1);
   }
 
   // Produce a correctly rounded DyadicFloat from a too-large mantissa,
@@ -319,7 +319,8 @@ template <size_t Bits> struct DyadicFloat {
     if (LIBC_UNLIKELY(exp_hi <= 0)) {
       // Output is denormal.
       denorm = true;
-      shift = (Bits - PRECISION) + static_cast<uint32_t>(1 - exp_hi);
+      shift = static_cast<uint32_t>((Bits - PRECISION) +
+                                    static_cast<uint32_t>(1 - exp_hi));
 
       exp_hi = FPBits<T>::EXP_BIAS;
     }
@@ -673,8 +674,8 @@ rounded_div(const DyadicFloat<Bits> &af, const DyadicFloat<Bits> &bf) {
   }
 
   DyadicFloat<(Bits * 2)> qbig(qf.sign, qf.exponent - 2, q);
-  return DyadicFloat<Bits>::round(qbig.sign, qbig.exponent + Bits,
-                                  qbig.mantissa, Bits);
+  return DyadicFloat<Bits>::round(
+      qbig.sign, qbig.exponent + static_cast<int>(Bits), qbig.mantissa, Bits);
 }
 
 // Simple polynomial approximation.
diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index 7b46978d0c8af..e06c16ff1021d 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -168,7 +168,7 @@ fma(InType x, InType y, InType z) {
   constexpr InStorageType IMPLICIT_MASK =
       InFPBits::SIG_MASK - InFPBits::FRACTION_MASK;
 
-  constexpr InType DENORMAL_SCALING =
+  const InType DENORMAL_SCALING =
       InFPBits::create_value(
           Sign::POS, InFPBits::FRACTION_LEN + InFPBits::EXP_BIAS, IMPLICIT_MASK)
           .get_val();
diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h
index 1a321231a8eb9..d2a71c8ea8d52 100644
--- a/libc/src/__support/FPUtil/generic/FMod.h
+++ b/libc/src/__support/FPUtil/generic/FMod.h
@@ -212,8 +212,9 @@ class FMod {
       StorageType m_x = sx.get_explicit_mantissa();
       StorageType m_y = sy.get_explicit_mantissa();
       StorageType d = (e_x == e_y)
-                          ? (m_x - m_y)
-                          : static_cast<StorageType>(m_x << (e_x - e_y)) % m_y;
+                          ? static_cast<StorageType>(m_x - m_y)
+                          : static_cast<StorageType>(
+                                static_cast<U>(m_x << (e_x - e_y)) % m_y);
       if (d == 0)
         return FPB::zero();
       // iy - 1 because of "zero power" for number with power 1
@@ -222,7 +223,7 @@ class FMod {
     // Both subnormal special case.
     if (LIBC_UNLIKELY(e_x == 0 && e_y == 0)) {
       FPB d;
-      d.set_mantissa(sx.uintval() % sy.uintval());
+      d.set_mantissa(static_cast<StorageType>(sx.uintval() % sy.uintval()));
       return d;
     }
 
@@ -249,7 +250,7 @@ class FMod {
     {
       // Shift hy right until the end or n = 0
       int right_shift = exp_diff < tail_zeros_m_y ? exp_diff : tail_zeros_m_y;
-      m_y >>= right_shift;
+      m_y = static_cast<U>(m_y >> right_shift);
       exp_diff -= right_shift;
       e_y += right_shift;
     }
@@ -258,11 +259,11 @@ class FMod {
       // Shift hx left until the end or n = 0
       int left_shift =
           exp_diff < DEFAULT_LEAD_ZEROS ? exp_diff : DEFAULT_LEAD_ZEROS;
-      m_x <<= left_shift;
+      m_x = static_cast<U>(m_x << left_shift);
       exp_diff -= left_shift;
     }
 
-    m_x %= m_y;
+    m_x = static_cast<U>(m_x % m_y);
     if (LIBC_UNLIKELY(m_x == 0))
       return FPB::zero();
 
diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index 1dc16e4d4fce4..78b377719207c 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -165,11 +165,13 @@ add_or_sub(InType x, InType y) {
     // min_bits must be subnormal too.
 
     if (is_effectively_add)
-      result_mant = max_bits.get_mantissa() + min_bits.get_mantissa();
+      result_mant = static_cast<InStorageType>(max_bits.get_mantissa() +
+                                               min_bits.get_mantissa());
     else
-      result_mant = max_bits.get_mantissa() - min_bits.get_mantissa();
+      result_mant = static_cast<InStorageType>(max_bits.get_mantissa() -
+                                               min_bits.get_mantissa());
 
-    result_mant <<= GUARD_BITS_LEN;
+    result_mant = static_cast<InStorageType>(result_mant << GUARD_BITS_LEN);
   } else {
     InStorageType max_mant = static_cast<InStorageType>(
         max_bits.get_explicit_mantissa() << GUARD_BITS_LEN);
@@ -196,9 +198,11 @@ add_or_sub(InType x, InType y) {
         static_cast<InStorageType>(static_cast<int>(aligned_min_mant_sticky));
 
     if (is_effectively_add)
-      result_mant = max_mant + (aligned_min_mant | min_mant_sticky);
+      result_mant = static_cast<InStorageType>(
+          max_mant + (aligned_min_mant | min_mant_sticky));
     else
-      result_mant = max_mant - (aligned_min_mant | min_mant_sticky);
+      result_mant = static_cast<InStorageType>(
+          max_mant - (aligned_min_mant | min_mant_sticky));
   }
 
   int result_exp = max_bits.get_explicit_exponent() - RESULT_FRACTION_LEN;
diff --git a/libc/src/__support/FPUtil/generic/div.h b/libc/src/__support/FPUtil/generic/div.h
index 85026bb3fd40f..96e4bdd9687aa 100644
--- a/libc/src/__support/FPUtil/generic/div.h
+++ b/libc/src/__support/FPUtil/generic/div.h
@@ -109,11 +109,11 @@ div(InType x, InType y) {
   InStorageType yd_mant_in = static_cast<InStorageType>(yd.mantissa >> 1);
 
   for (int i = 0; i < NUM_ITERS; ++i) {
-    q <<= 1;
-    r <<= 1;
+    q = static_cast<InStorageType>(q << 1);
+    r = static_cast<InStorageType>(r << 1);
     if (r >= yd_mant_in) {
-      q += 1;
-      r -= yd_mant_in;
+      q = static_cast<InStorageType>(q + 1);
+      r = static_cast<InStorageType>(r - yd_mant_in);
     }
   }
 
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index 4e452a87050b1..e37c318d815dc 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -47,7 +47,7 @@ LIBC_INLINE void normalize(int &exponent,
       cpp::countl_zero(mantissa) -
       (8 * static_cast<int>(sizeof(mantissa)) - 1 - FPBits<T>::FRACTION_LEN);
   exponent -= shift;
-  mantissa <<= shift;
+  mantissa = static_cast<typename FPBits<T>::StorageType>(mantissa << shift);
 }
 
 #ifdef LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64
@@ -63,7 +63,7 @@ LIBC_INLINE void normalize<long double>(int &exponent, UInt128 &mantissa) {
       hi_bits ? (cpp::countl_zero(hi_bits) - 15)
               : (cpp::countl_zero(static_cast<uint64_t>(mantissa)) + 49);
   exponent -= shift;
-  mantissa <<= shift;
+  mantissa = static_cast<typename FPBits<T>::StorageType>(mantissa << shift);
 }
 #endif
 
@@ -92,7 +92,7 @@ sqrt(InType x) {
         DyadicFloat<cpp::bit_ceil(static_cast<size_t>(InFPBits::STORAGE_LEN))>;
 
     constexpr InStorageType ONE = InStorageType(1) << InFPBits::FRACTION_LEN;
-    constexpr auto FLT_NAN = OutFPBits::quiet_nan().get_val();
+    const auto FLT_NAN = OutFPBits::quiet_nan().get_val();
 
     InFPBits bits(x);
 
@@ -122,7 +122,7 @@ sqrt(InType x) {
       // Step 1b: Make sure the exponent is even.
       if (x_exp & 1) {
         --x_exp;
-        x_mant <<= 1;
+        x_mant = static_cast<InStorageType>(x_mant << 1);
       }
 
       // After step 1b, x = 2^(x_exp) * x_mant, where x_exp is even, and
@@ -138,31 +138,31 @@ sqrt(InType x) {
       //   y_n = 1 if 2*r(n-1) >= 2*y(n - 1) + 2^(-n-1)
       //         0 otherwise.
       InStorageType y = ONE;
-      InStorageType r = x_mant - ONE;
+      InStorageType r = static_cast<InStorageType>(x_mant - ONE);
 
       // TODO: Reduce iteration count to OutFPBits::FRACTION_LEN + 2 or + 3.
       for (InStorageType current_bit = ONE >> 1; current_bit;
-           current_bit >>= 1) {
-        r <<= 1;
+           current_bit = static_cast<InStorageType>(current_bit >> 1)) {
+        r = static_cast<InStorageType>(r << 1);
         // 2*y(n - 1) + 2^(-n-1)
         InStorageType tmp = static_cast<InStorageType>((y << 1) + current_bit);
         if (r >= tmp) {
-          r -= tmp;
-          y += current_bit;
+          r = static_cast<InStorageType>(r - tmp);
+          y = static_cast<InStorageType>(y + current_bit);
         }
       }
 
       // We compute one more iteration in order to round correctly.
-      r <<= 2;
-      y <<= 2;
-      InStorageType tmp = y + 1;
+      r = static_cast<InStorageType>(r << 2);
+      y = static_cast<InStorageType>(y << 2);
+      InStorageType tmp = static_cast<InStorageType>(y + 1);
       if (r >= tmp) {
-        r -= tmp;
+        r = static_cast<InStorageType>(r - tmp);
         // Rounding bit.
-        y |= 2;
+        y = static_cast<InStorageType>(y | 2);
       }
       // Sticky bit.
-      y |= static_cast<unsigned int>(r != 0);
+      y = static_cast<InStorageType>(y | static_cast<unsigned int>(r != 0));
 
       DyadicFloat yd(Sign::POS, (x_exp >> 1) - 2 - InFPBits::FRACTION_LEN, y);
       return yd.template as<OutType, /*ShouldSignalExceptions=*/true>();
diff --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
index 0ba836d17a085..e1992ffe996be 100644
--- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
+++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
@@ -27,7 +27,7 @@ LIBC_INLINE void normalize(int &exponent,
       static_cast<size_t>(cpp::countl_zero(static_cast<uint64_t>(mantissa))) -
       (8 * sizeof(uint64_t) - 1 - FPBits<long double>::FRACTION_LEN));
   exponent -= shift;
-  mantissa <<= shift;
+  mantissa = static_cast<FPBits<long double>::StorageType>(mantissa << shift);
 }
 
 // if constexpr statement in sqrt.h still requires x86::sqrt to be declared
@@ -41,7 +41,7 @@ LIBC_INLINE long double sqrt(long double x) {
   using LDBits = FPBits<long double>;
   using StorageType = typename LDBits::StorageType;
   constexpr StorageType ONE = StorageType(1) << int(LDBits::FRACTION_LEN);
-  constexpr auto LDNAN = LDBits::quiet_nan().get_val();
+  const auto LDNAN = LDBits::quiet_nan().get_val();
 
   LDBits bits(x);
 
diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index 92061ea13e203..a66c0214f13c9 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -80,7 +80,13 @@ LIBC_INLINE int quick_get_round() {
 
 } // namespace generic
 
-LIBC_INLINE constexpr bool fenv_is_round_up() {
+#if LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
+#define LIBC_ROUNDING_MODE_CONSTEXPR constexpr
+#else
+#define LIBC_ROUNDING_MODE_CONSTEXPR
+#endif
+
+LIBC_INLINE LIBC_ROUNDING_MODE_CONSTEXPR bool fenv_is_round_up() {
   if (cpp::is_constant_evaluated()) {
     return false;
   } else {
@@ -88,7 +94,7 @@ LIBC_INLINE constexpr bool fenv_is_round_up() {
   }
 }
 
-LIBC_INLINE constexpr bool fenv_is_round_down() {
+LIBC_INLINE LIBC_ROUNDING_MODE_CONSTEXPR bool fenv_is_round_down() {
   if (cpp::is_constant_evaluated()) {
     return false;
   } else {
@@ -96,7 +102,7 @@ LIBC_INLINE constexpr bool fenv_is_round_down() {
   }
 }
 
-LIBC_INLINE constexpr bool fenv_is_round_to_nearest() {
+LIBC_INLINE LIBC_ROUNDING_MODE_CONSTEXPR bool fenv_is_round_to_nearest() {
   if (cpp::is_constant_evaluated()) {
     return true;
   } else {
@@ -104,7 +110,7 @@ LIBC_INLINE constexpr bool fenv_is_round_to_nearest() {
   }
 }
 
-LIBC_INLINE constexpr bool fenv_is_round_to_zero() {
+LIBC_INLINE LIBC_ROUNDING_MODE_CONSTEXPR bool fenv_is_round_to_zero() {
   if (cpp::is_constant_evaluated()) {
     return false;
   } else {
@@ -113,7 +119,7 @@ LIBC_INLINE constexpr bool fenv_is_round_to_zero() {
 }
 
 // Quick free standing get rounding mode based on the above observations.
-LIBC_INLINE constexpr int quick_get_round() {
+LIBC_INLINE LIBC_ROUNDING_MODE_CONSTEXPR int quick_get_round() {
   if (cpp::is_constant_evaluated()) {
     return FE_TONEAREST;
   } else {
diff --git a/libc/src/__support/FPUtil/x86_64/FEnvImpl.h b/libc/src/__support/FPUtil/x86_64/FEnvImpl.h
index 703c305293dfd..0db0f91bf470d 100644
--- a/libc/src/__support/FPUtil/x86_64/FEnvImpl.h
+++ b/libc/src/__support/FPUtil/x86_64/FEnvImpl.h
@@ -55,7 +55,8 @@ LIBC_INLINE static int test_except(int excepts) {
   uint16_t tested_excepts = sse::test_except(x86_excepts);
 
 #ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
-  tested_excepts |= x87::test_except(x86_excepts);
+  tested_excepts =
+      static_cast<uint16_t>(tested_excepts | x87::test_except(x86_excepts));
 #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
 
   return internal::get_macro_from_exception_status(tested_excepts);
@@ -65,7 +66,7 @@ LIBC_INLINE static int get_except() {
   uint16_t excepts = sse::get_except();
 
 #ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
-  excepts |= x87::get_except();
+  excepts = static_cast<uint16_t>(excepts | x87::get_except());
 #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
 
   return internal::get_macro_from_exception_status(excepts);
@@ -96,7 +97,8 @@ LIBC_INLINE static int enable_except(int excepts) {
   uint16_t old_excepts = sse::enable_except(x86_excepts);
 
 #ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
-  old_excepts |= x87::enable_except(x86_excepts);
+  old_excepts =
+      static_cast<uint16_t>(old_excepts | x87::enable_except(x86_excepts));
 #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
 
   return internal::get_macro_from_exception_status(old_excepts);
@@ -107,7 +109,8 @@ LIBC_INLINE static int disable_except(int excepts) {
   uint16_t old_excepts = sse::disable_except(x86_excepts);
 
 #ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
-  old_excepts |= x87::disable_except(x86_excepts);
+  old_excepts =
+      static_cast<uint16_t>(old_excepts | x87::disable_except(x86_excepts));
 #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
 
   return internal::get_macro_from_exception_status(old_excepts);
diff --git a/libc/src/__support/FPUtil/x86_64/fenv_mxcsr_utils.h b/libc/src/__support/FPUtil/x86_64/fenv_mxcsr_utils.h
index e28aa3a9411e7..77954b48d7f05 100644
--- a/libc/src/__support/FPUtil/x86_64/fenv_mxcsr_utils.h
+++ b/libc/src/__support/FPUtil/x86_64/fenv_mxcsr_utils.h
@@ -152,7 +152,8 @@ LIBC_INLINE static uint16_t get_round() {
 
 LIBC_INLINE static void set_round(uint16_t rounding_mode) {
   uint32_t mxcsr = get_mxcsr();
-  rounding_mode <<= RoundingControl::MXCSR_BIT_POSITION;
+  rounding_mode = static_cast<uint16_t>(rounding_mode
+                                        << RoundingControl::MXCSR_BIT_POSITION);
   // Clear rounding bits.
   mxcsr &= (~RoundingControl::MXCSR_ROUNDING_MASK);
   write_mxcsr(mxcsr | rounding_mode);
diff --git a/libc/src/__support/FPUtil/x86_64/fenv_x86_common.h b/libc/src/__support/FPUtil/x86_64/fenv_x86_common.h
index e27c62a99dba9..a232a4db69c73 100644
--- a/libc/src/__support/FPUtil/x86_64/fenv_x86_common.h
+++ b/libc/src/__support/FPUtil/x86_64/fenv_x86_common.h
@@ -221,32 +221,35 @@ struct X87StateDescriptor {
 LIBC_INLINE static uint16_t x87_state_to_mxcsr(const X87StateDescriptor &s) {
   uint16_t mxcsr = 0;
   // Copy 6 exception flags from status word.
-  mxcsr = s.status_word & ExceptionFlags::ALL_F;
+  mxcsr = static_cast<uint16_t>(s.status_word & ExceptionFlags::ALL_F);
   // Copy 6 exception masks from control word.
-  mxcsr |= (s.control_word & ExceptionFlags::ALL_F)
-           << ExceptionFlags::MXCSR_EXCEPTION_MASK_BIT_POSITION;
+  mxcsr |= static_cast<uint16_t>(
+      (s.control_word & ExceptionFlags::ALL_F)
+      << ExceptionFlags::MXCSR_EXCEPTION_MASK_BIT_POSITION);
   // Copy 2-bit rounding control.
-  mxcsr |= (s.control_word & RoundingControl::X87_ROUNDING_MASK)
-           << (RoundingControl::MXCSR_BIT_POSITION -
-               RoundingControl::X87_BIT_POSITION);
+  mxcsr |= static_cast<uint16_t>(
+      (s.control_word & RoundingControl::X87_ROUNDING_MASK)
+      << (RoundingControl::MXCSR_BIT_POSITION -
+          RoundingControl::X87_BIT_POSITION));
   return mxcsr;
 }
 
 LIBC_INLINE static void mxcsr_to_x87_state(uint16_t mxcsr,
                                            X87StateDescriptor &s) {
   // Clear exception mask and rounding control.
-  s.control_word &=
-      ~(ExceptionFlags::ALL_F | RoundingControl::X87_ROUNDING_MASK);
+  s.control_word &= static_cast<uint16_t>(
+      ~(ExceptionFlags::ALL_F | RoundingControl::X87_ROUNDING_MASK));
   // Copy 6 exception masks.
-  s.control_word |=
+  s.control_word |= static_cast<uint16_t>(
       (mxcsr >> ExceptionFlags::MXCSR_EXCEPTION_MASK_BIT_POSITION) &
-      ExceptionFlags::ALL_F;
+      ExceptionFlags::ALL_F);
   // Copy rounding control.
   s.control_word |=
-      (mxcsr & RoundingControl::MXCSR_ROUNDING_MASK) >>
-      (RoundingControl::MXCSR_BIT_POSITION - RoundingControl::X87_BIT_POSITION);
+      static_cast<uint16_t>((mxcsr & RoundingControl::MXCSR_ROUNDING_MASK) >>
+                            (RoundingControl::MXCSR_BIT_POSITION -
+                             RoundingControl::X87_BIT_POSITION));
   // Clear exception flags
-  s.status_word &= ~ExceptionFlags::ALL_F;
+  s.status_word &= static_cast<uint16_t>(~ExceptionFlags::ALL_F);
   // Copy 6 exception status flags.
   s.status_word |= mxcsr & ExceptionFlags::ALL_F;
 }
diff --git a/libc/src/__support/FPUtil/x86_64/fenv_x87_utils.h b/libc/src/__support/FPUtil/x86_64/fenv_x87_utils.h
index a38e4c9988084..4bbf3ca215b7d 100644
--- a/libc/src/__support/FPUtil/x86_64/fenv_x87_utils.h
+++ b/libc/src/__support/FPUtil/x86_64/fenv_x87_utils.h
@@ -178,9 +178,10 @@ LIBC_INLINE static uint16_t get_round() {
 
 LIBC_INLINE static void set_round(uint16_t rounding_mode) {
   uint16_t x87_control = get_x87_control_word();
-  rounding_mode <<= RoundingControl::X87_BIT_POSITION;
-  uint16_t x87_control_new =
-      (x87_control & (~RoundingControl::X87_ROUNDING_MASK)) | rounding_mode;
+  rounding_mode =
+      static_cast<uint16_t>(rounding_mode << RoundingControl::X87_BIT_POSITION);
+  uint16_t x87_control_new = static_cast<uint16_t>(
+      (x87_control & (~RoundingControl::X87_ROUNDING_MASK)) | rounding_mode);
   // Only update if rounding mode changes.
   if (x87_control_new != x87_control)
     write_x87_control_word(x87_control_new);
diff --git a/libc/src/__support/big_int.h b/libc/src/__support/big_int.h
index a6dcff27ca167..ef2eb5bf33afe 100644
--- a/libc/src/__support/big_int.h
+++ b/libc/src/__support/big_int.h
@@ -229,12 +229,14 @@ LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst,
   word carry = 0;
   // First round of accumulation for those at N - 1 in the full product.
   for (size_t i = 0; i < N; ++i)
-    carry += mul_add_with_carry(acc, lhs[i], rhs[N - 1 - i]);
+    carry = static_cast<word>(carry +
+                              mul_add_with_carry(acc, lhs[i], rhs[N - 1 - i]));
   for (size_t i = N; i < 2 * N - 1; ++i) {
     acc.advance(carry);
     carry = 0;
     for (size_t j = i - N + 1; j < N; ++j)
-      carry += mul_add_with_carry(acc, lhs[j], rhs[i - j]);
+      carry = static_cast<word>(carry +
+                                mul_add_with_carry(acc, lhs[j], rhs[i - j]));
     dst[i - N] = acc.sum();
   }
   dst.back() = acc.carry();
@@ -260,7 +262,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
 #ifdef LIBC_TYPES_HAS_INT128
   constexpr size_t TOTAL_BITS = N * WORD_BITS;
   if constexpr (TOTAL_BITS == 128 &&
-                __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) {
+                __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ &&
+                LIBC_HAS_BUILTIN_BIT_CAST) {
     using type = cpp::conditional_t<is_signed, __int128_t, __uint128_t>;
     auto tmp = cpp::bit_cast<type>(array);
     if constexpr (direction == LEFT)
@@ -366,7 +369,7 @@ struct BigInt {
   LIBC_INLINE constexpr BigInt(
       const BigInt<OtherBits, OtherSigned, OtherWordType> &other) {
     using BigIntOther = BigInt<OtherBits, OtherSigned, OtherWordType>;
-    const bool should_sign_extend = Signed && other.is_neg();
+    [[maybe_unused]] const bool should_sign_extend = Signed && other.is_neg();
 
     static_assert(!(Bits == OtherBits && WORD_SIZE != BigIntOther::WORD_SIZE) &&
                   "This is currently untested for casting between bigints with "
@@ -524,8 +527,11 @@ struct BigInt {
       return lo;
     constexpr size_t MAX_COUNT =
         T_SIZE > Bits ? WORD_COUNT : T_SIZE / WORD_SIZE;
-    for (size_t i = 1; i < MAX_COUNT; ++i)
-      lo += static_cast<T>(static_cast<T>(val[i]) << (WORD_SIZE * i));
+    if constexpr (MAX_COUNT > 1) {
+      for (size_t i = 1; i < MAX_COUNT; ++i)
+        lo = static_cast<T>(
+            lo + static_cast<T>(static_cast<T>(val[i]) << (WORD_SIZE * i)));
+    }
     if constexpr (Signed && (T_SIZE > Bits)) {
       // Extend sign for negative numbers.
       constexpr T MASK = (~T(0) << Bits);
@@ -852,10 +858,10 @@ struct BigInt {
       result[i] = lhs[i] OP rhs[i];                                            \
     return result;                                                             \
   }                                                                            \
-  LIBC_INLINE friend constexpr BigInt operator OP##=(BigInt &lhs,              \
-                                                     const BigInt &rhs) {      \
+  LIBC_INLINE friend constexpr BigInt operator OP## =                          \
+      (BigInt & lhs, const BigInt &rhs) {                                      \
     for (size_t i = 0; i < WORD_COUNT; ++i)                                    \
-      lhs[i] OP## = rhs[i];                                                    \
+      lhs[i] = static_cast<WordType>(lhs[i] OP rhs[i]);                        \
     return lhs;                                                                \
   }
 
diff --git a/libc/src/__support/integer_to_string.h b/libc/src/__support/integer_to_string.h
index 5e7369de00962..c3f69ca832b24 100644
--- a/libc/src/__support/integer_to_string.h
+++ b/libc/src/__support/integer_to_string.h
@@ -159,7 +159,8 @@ using Bin = details::Fmt<2>;
 using Oct = details::Fmt<8>;
 using Dec = details::Fmt<10>;
 using Hex = details::Fmt<16>;
-template <size_t radix> using Custom = details::Fmt<radix>;
+template <size_t radix>
+using Custom = details::Fmt<static_cast<uint8_t>(radix)>;
 
 } // namespace radix
 
@@ -385,7 +386,8 @@ template <typename T, typename Fmt = radix::Dec> class IntegerToString {
     LIBC_INLINE static void
     write_unsigned_number(UNSIGNED_T value,
                           details::BackwardStringBufferWriter &sink) {
-      for (; sink.ok() && value != 0; value /= Fmt::BASE) {
+      for (; sink.ok() && value != 0;
+           value = static_cast<UNSIGNED_T>(value / Fmt::BASE)) {
         const uint8_t digit(static_cast<uint8_t>(value % Fmt::BASE));
         sink.push(digit_char(digit));
       }
diff --git a/libc/src/__support/macros/attributes.h b/libc/src/__support/macros/attributes.h
index b3e1e12889511..76da7f4b60bfa 100644
--- a/libc/src/__support/macros/attributes.h
+++ b/libc/src/__support/macros/attributes.h
@@ -137,10 +137,23 @@ LIBC_THREAD_MODE_EXTERNAL.
 // Disable regular and hardware-supported ASan for functions that may
 // intentionally make out-of-bounds access. Disable TSan as well, as it detects
 // out-of-bounds accesses to heap memory.
+#if defined(__clang__)
 #define LIBC_NO_SANITIZE_OOB_ACCESS                                            \
   __attribute__((no_sanitize("address", "hwaddress", "thread")))
 #else
+#define LIBC_NO_SANITIZE_OOB_ACCESS                                            \
+  __attribute__((no_sanitize("address", "thread")))
+#endif
+#else
 #define LIBC_NO_SANITIZE_OOB_ACCESS
 #endif
 
+#include "src/__support/macros/properties/compiler.h"
+#if LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED && LIBC_HAS_BUILTIN_BIT_CAST &&     \
+    (!defined(LIBC_COMPILER_IS_GCC) || (LIBC_COMPILER_GCC_VER >= 900))
+#define LIBC_MATH_CONSTEXPR constexpr
+#else
+#define LIBC_MATH_CONSTEXPR
+#endif
+
 #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
diff --git a/libc/src/__support/macros/optimization.h b/libc/src/__support/macros/optimization.h
index dbefd20a5cd16..e57c54190e58e 100644
--- a/libc/src/__support/macros/optimization.h
+++ b/libc/src/__support/macros/optimization.h
@@ -28,12 +28,18 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
 #define LIBC_UNLIKELY(x)                                                       \
   LIBC_NAMESPACE::details::expects_bool_condition(x, false)
 
+#include "src/__support/macros/properties/compiler.h"
 #if defined(LIBC_COMPILER_IS_CLANG)
 #define LIBC_LOOP_NOUNROLL _Pragma("nounroll")
 #define LIBC_LOOP_UNROLL _Pragma("unroll")
 #elif defined(LIBC_COMPILER_IS_GCC)
+#if (LIBC_COMPILER_GCC_VER >= 800)
 #define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0")
 #define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048")
+#else
+#define LIBC_LOOP_NOUNROLL
+#define LIBC_LOOP_UNROLL
+#endif
 #elif defined(LIBC_COMPILER_IS_MSVC)
 #define LIBC_LOOP_NOUNROLL
 #define LIBC_LOOP_UNROLL
diff --git a/libc/src/__support/math/acos.h b/libc/src/__support/math/acos.h
index 6b419449176fd..ed7e02ad6e7b2 100644
--- a/libc/src/__support/math/acos.h
+++ b/libc/src/__support/math/acos.h
@@ -24,7 +24,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr double acos(double x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR double acos(double x) {
   using DoubleDouble = fputil::DoubleDouble;
   using namespace asin_internal;
   using FPBits = fputil::FPBits<double>;
diff --git a/libc/src/__support/math/acosf.h b/libc/src/__support/math/acosf.h
index ae93abe7e716a..05b295e4b5298 100644
--- a/libc/src/__support/math/acosf.h
+++ b/libc/src/__support/math/acosf.h
@@ -46,7 +46,7 @@ LIBC_INLINE_VAR constexpr fputil::ExceptValues<float, N_EXCEPTS> ACOSF_EXCEPTS =
 
 } // namespace acosf_internal
 
-LIBC_INLINE constexpr float acosf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float acosf(float x) {
   using namespace acosf_internal;
   using namespace inv_trigf_utils_internal;
   using FPBits = typename fputil::FPBits<float>;
diff --git a/libc/src/__support/math/acoshf.h b/libc/src/__support/math/acoshf.h
index b111a21c07b70..41a27875c9350 100644
--- a/libc/src/__support/math/acoshf.h
+++ b/libc/src/__support/math/acoshf.h
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float acoshf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float acoshf(float x) {
   using namespace acoshf_internal;
   using FPBits_t = typename fputil::FPBits<float>;
   FPBits_t xbits(x);
diff --git a/libc/src/__support/math/asinf.h b/libc/src/__support/math/asinf.h
index 08cfb192754e4..09e10a039a2c7 100644
--- a/libc/src/__support/math/asinf.h
+++ b/libc/src/__support/math/asinf.h
@@ -23,7 +23,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float asinf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float asinf(float x) {
   using namespace inv_trigf_utils_internal;
   using FPBits = typename fputil::FPBits<float>;
 
diff --git a/libc/src/__support/math/asinhf.h b/libc/src/__support/math/asinhf.h
index e420eae221c3e..abd25cfe43ded 100644
--- a/libc/src/__support/math/asinhf.h
+++ b/libc/src/__support/math/asinhf.h
@@ -21,7 +21,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float asinhf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float asinhf(float x) {
   using namespace acoshf_internal;
   using FPBits_t = typename fputil::FPBits<float>;
   FPBits_t xbits(x);
diff --git a/libc/src/__support/math/atan.h b/libc/src/__support/math/atan.h
index db60311bd746d..853a81dada78c 100644
--- a/libc/src/__support/math/atan.h
+++ b/libc/src/__support/math/atan.h
@@ -52,7 +52,7 @@ namespace math {
 //      So we can return:
 //        atan(x) = sign(x) * (pi/2 - epsilon)
 
-LIBC_INLINE constexpr double atan(double x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR double atan(double x) {
 
   using namespace atan_internal;
   using FPBits = fputil::FPBits<double>;
diff --git a/libc/src/__support/math/atan2.h b/libc/src/__support/math/atan2.h
index f59d92b6dc19c..5e1becbe493c4 100644
--- a/libc/src/__support/math/atan2.h
+++ b/libc/src/__support/math/atan2.h
@@ -75,7 +75,7 @@ namespace math {
 // and relative errors bounded by:
 //   |(atan(u) - P(u)) / P(u)| < u^10 / 11 < 2^-73.
 
-LIBC_INLINE constexpr double atan2(double y, double x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR double atan2(double y, double x) {
   using namespace atan_internal;
   using FPBits = fputil::FPBits<double>;
 
diff --git a/libc/src/__support/math/atan2f.h b/libc/src/__support/math/atan2f.h
index 15d1fce2b707c..12e9aacef5926 100644
--- a/libc/src/__support/math/atan2f.h
+++ b/libc/src/__support/math/atan2f.h
@@ -239,7 +239,7 @@ LIBC_INLINE float atan2f_double_double(double num_d, double den_d, double q_d,
 // 0x1.aec6f...p-100
 // which is about rounding errors of double-double (2^-104).
 
-LIBC_INLINE constexpr float atan2f(float y, float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float atan2f(float y, float x) {
   using namespace atan2f_internal;
   using namespace inv_trigf_utils_internal;
   using FPBits = typename fputil::FPBits<float>;
diff --git a/libc/src/__support/math/atan2f128.h b/libc/src/__support/math/atan2f128.h
index d04cf6f49d4ea..0b0efa538a4f6 100644
--- a/libc/src/__support/math/atan2f128.h
+++ b/libc/src/__support/math/atan2f128.h
@@ -81,33 +81,31 @@ namespace math {
 // and relative errors bounded by:
 //   |(atan(u) - P(u)) / P(u)| < 2^-114.
 
-LIBC_INLINE constexpr float128 atan2f128(float128 y, float128 x) {
-  using Float128 = fputil::DyadicFloat<128>;
-
-  constexpr Float128 ZERO = {Sign::POS, 0, 0_u128};
-  constexpr Float128 MZERO = {Sign::NEG, 0, 0_u128};
-  constexpr Float128 PI = {Sign::POS, -126,
-                           0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128};
-  constexpr Float128 MPI = {Sign::NEG, -126,
-                            0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128};
-  constexpr Float128 PI_OVER_2 = {Sign::POS, -127,
-                                  0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128};
-  constexpr Float128 MPI_OVER_2 = {Sign::NEG, -127,
-                                   0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128};
-  constexpr Float128 PI_OVER_4 = {Sign::POS, -128,
-                                  0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128};
-  constexpr Float128 THREE_PI_OVER_4 = {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float128 atan2f128(float128 y, float128 x) {
+  using DF128 = fputil::DyadicFloat<128>;
+
+  constexpr DF128 ZERO = {Sign::POS, 0, 0_u128};
+  constexpr DF128 MZERO = {Sign::NEG, 0, 0_u128};
+  constexpr DF128 PI = {Sign::POS, -126,
+                        0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128};
+  constexpr DF128 MPI = {Sign::NEG, -126,
+                         0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128};
+  constexpr DF128 PI_OVER_2 = {Sign::POS, -127,
+                               0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128};
+  constexpr DF128 MPI_OVER_2 = {Sign::NEG, -127,
+                                0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128};
+  constexpr DF128 PI_OVER_4 = {Sign::POS, -128,
+                               0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128};
+  constexpr DF128 THREE_PI_OVER_4 = {
       Sign::POS, -128, 0x96cbe3f9'990e91a7'9394c9e8'a0a5159d_u128};
 
   // Adjustment for constant term:
   //   CONST_ADJ[x_sign][y_sign][recip]
-  constexpr Float128 CONST_ADJ[2][2][2] = {
-      {{ZERO, MPI_OVER_2}, {MZERO, MPI_OVER_2}},
-      {{MPI, PI_OVER_2}, {MPI, PI_OVER_2}}};
+  const DF128 CONST_ADJ[2][2][2] = {{{ZERO, MPI_OVER_2}, {MZERO, MPI_OVER_2}},
+                                    {{MPI, PI_OVER_2}, {MPI, PI_OVER_2}}};
 
   using namespace atan_internal;
   using FPBits = fputil::FPBits<float128>;
-  using Float128 = fputil::DyadicFloat<128>;
 
   FPBits x_bits(x), y_bits(y);
   bool x_sign = x_bits.sign().is_neg();
@@ -139,7 +137,7 @@ LIBC_INLINE constexpr float128 atan2f128(float128 y, float128 x) {
     //   0: zero
     //   1: finite, non-zero
     //   2: infinity
-    constexpr Float128 EXCEPTS[3][3][2] = {
+    const DF128 EXCEPTS[3][3][2] = {
         {{ZERO, PI}, {ZERO, PI}, {ZERO, PI}},
         {{PI_OVER_2, PI_OVER_2}, {ZERO, ZERO}, {ZERO, PI}},
         {{PI_OVER_2, PI_OVER_2},
@@ -148,7 +146,7 @@ LIBC_INLINE constexpr float128 atan2f128(float128 y, float128 x) {
     };
 
     if ((x_except != 1) || (y_except != 1)) {
-      Float128 r = EXCEPTS[y_except][x_except][x_sign];
+      DF128 r = EXCEPTS[y_except][x_except][x_sign];
       if (y_sign)
         r.sign = r.sign.negate();
       return static_cast<float128>(r);
@@ -156,13 +154,13 @@ LIBC_INLINE constexpr float128 atan2f128(float128 y, float128 x) {
   }
 
   bool final_sign = ((x_sign != y_sign) != recip);
-  Float128 const_term = CONST_ADJ[x_sign][y_sign][recip];
+  DF128 const_term = CONST_ADJ[x_sign][y_sign][recip];
   int exp_diff = den.exponent - num.exponent;
   // We have the following bound for normalized n and d:
   //   2^(-exp_diff - 1) < n/d < 2^(-exp_diff + 1).
   if (LIBC_UNLIKELY(exp_diff > FPBits::FRACTION_LEN + 2)) {
-    Float128 quotient = rounded_div(num, den);
-    Float128 result = quick_add(const_term, quotient);
+    DF128 quotient = rounded_div(num, den);
+    DF128 result = quick_add(const_term, quotient);
     if (final_sign)
       result.sign = result.sign.negate();
     return static_cast<float128>(result);
@@ -182,22 +180,22 @@ LIBC_INLINE constexpr float128 atan2f128(float128 y, float128 x) {
   unsigned idx = static_cast<unsigned>(k);
 
   // k_f128 = idx / 64
-  Float128 k_f128(Sign::POS, -6, Float128::MantissaType(idx));
+  DF128 k_f128(Sign::POS, -6, DF128::MantissaType(idx));
 
   // Range reduction:
   // atan(n/d) - atan(k) = atan((n/d - k/64) / (1 + (n/d) * (k/64)))
   //                     = atan((n - d * k/64)) / (d + n * k/64))
   // num_f128 = n - d * k/64
-  Float128 num_f128 = fputil::multiply_add(den, -k_f128, num);
+  DF128 num_f128 = fputil::multiply_add(den, -k_f128, num);
   // den_f128 = d + n * k/64
-  Float128 den_f128 = fputil::multiply_add(num, k_f128, den);
+  DF128 den_f128 = fputil::multiply_add(num, k_f128, den);
 
   // q = (n - d * k) / (d + n * k)
-  Float128 q = fputil::quick_mul(num_f128, fputil::approx_reciprocal(den_f128));
+  DF128 q = fputil::quick_mul(num_f128, fputil::approx_reciprocal(den_f128));
   // p ~ atan(q)
-  Float128 p = atan_eval(q);
+  DF128 p = atan_eval(q);
 
-  Float128 r =
+  DF128 r =
       fputil::quick_add(const_term, fputil::quick_add(ATAN_I_F128[idx], p));
   if (final_sign)
     r.sign = r.sign.negate();
diff --git a/libc/src/__support/math/atanf.h b/libc/src/__support/math/atanf.h
index d583572ea4727..60a38cfe6d7b8 100644
--- a/libc/src/__support/math/atanf.h
+++ b/libc/src/__support/math/atanf.h
@@ -30,7 +30,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float atanf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float atanf(float x) {
   using namespace inv_trigf_utils_internal;
   using FPBits = typename fputil::FPBits<float>;
 
@@ -96,7 +96,7 @@ LIBC_INLINE constexpr float atanf(float x) {
   double x_d = 0, const_term = 0, final_sign = 0;
   int idx = 0;
 
-  if (x_abs > 0x3f80'0000U) {
+  if (x_abs > 1065353216U) { // 0x3f80'0000U
     // |x| > 1, we need to invert x, so we will perform range reduction in
     // double precision.
     x_d = 1.0 / static_cast<double>(x_bits.get_val());
diff --git a/libc/src/__support/math/atanhf.h b/libc/src/__support/math/atanhf.h
index 16d46994e2705..d86b5bcc951cf 100644
--- a/libc/src/__support/math/atanhf.h
+++ b/libc/src/__support/math/atanhf.h
@@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float atanhf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float atanhf(float x) {
   using namespace acoshf_internal;
   using FPBits = typename fputil::FPBits<float>;
 
diff --git a/libc/src/__support/math/cbrt.h b/libc/src/__support/math/cbrt.h
index a781ed36238b8..3f5f19395f676 100644
--- a/libc/src/__support/math/cbrt.h
+++ b/libc/src/__support/math/cbrt.h
@@ -144,7 +144,7 @@ LIBC_INLINE constexpr double get_error(const DoubleDouble &x_3,
 // exceptional handling, similar to what was done in the CORE-MATH project:
 // https://gitlab.inria.fr/core-math/core-math/-/blob/master/src/binary64/cbrt/cbrt.c
 
-LIBC_INLINE constexpr double cbrt(double x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR double cbrt(double x) {
   using DoubleDouble = fputil::DoubleDouble;
   using namespace cbrt_internal;
   using FPBits = fputil::FPBits<double>;
diff --git a/libc/src/__support/math/cbrtf.h b/libc/src/__support/math/cbrtf.h
index 35e60562a39c0..c012d97012cb2 100644
--- a/libc/src/__support/math/cbrtf.h
+++ b/libc/src/__support/math/cbrtf.h
@@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float cbrtf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float cbrtf(float x) {
   // Look up table for 2^(i/3) for i = 0, 1, 2.
   constexpr double CBRT2[3] = {1.0, 0x1.428a2f98d728bp0, 0x1.965fea53d6e3dp0};
 
diff --git a/libc/src/__support/math/cos.h b/libc/src/__support/math/cos.h
index e6a37c132cd80..29f70c0c1fc40 100644
--- a/libc/src/__support/math/cos.h
+++ b/libc/src/__support/math/cos.h
@@ -30,7 +30,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr double cos(double x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR double cos(double x) {
   using namespace range_reduction_double_internal;
   using FPBits = typename fputil::FPBits<double>;
   FPBits xbits(x);
diff --git a/libc/src/__support/math/cosf.h b/libc/src/__support/math/cosf.h
index f6ead968ac26e..769f30c79bb8a 100644
--- a/libc/src/__support/math/cosf.h
+++ b/libc/src/__support/math/cosf.h
@@ -26,7 +26,7 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
-LIBC_INLINE constexpr float cosf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float cosf(float x) {
   return sincosf_float_eval::sincosf_eval</*IS_SIN*/ false>(x);
 }
 
@@ -41,7 +41,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float cosf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float cosf(float x) {
   using namespace sincosf_utils_internal;
 
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
diff --git a/libc/src/__support/math/coshf.h b/libc/src/__support/math/coshf.h
index aa0988f9711f1..8b52b1a31a081 100644
--- a/libc/src/__support/math/coshf.h
+++ b/libc/src/__support/math/coshf.h
@@ -20,7 +20,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float coshf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float coshf(float x) {
   using namespace sinhfcoshf_internal;
   using FPBits = typename fputil::FPBits<float>;
 
diff --git a/libc/src/__support/math/cospif.h b/libc/src/__support/math/cospif.h
index 3d0a335408722..7a7a290787c3b 100644
--- a/libc/src/__support/math/cospif.h
+++ b/libc/src/__support/math/cospif.h
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float cospif(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float cospif(float x) {
   using namespace sincosf_utils_internal;
   using FPBits = typename fputil::FPBits<float>;
 
diff --git a/libc/src/__support/math/erff.h b/libc/src/__support/math/erff.h
index a40b927c60a26..66239aa16ecda 100644
--- a/libc/src/__support/math/erff.h
+++ b/libc/src/__support/math/erff.h
@@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float erff(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float erff(float x) {
 
   // Polynomials approximating erf(x)/x on ( k/8, (k + 1)/8 ) generated by
   // Sollya with: > P = fpminimax(erf(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|],
diff --git a/libc/src/__support/math/exp10.h b/libc/src/__support/math/exp10.h
index c2ca627d20db9..54adbef29aa00 100644
--- a/libc/src/__support/math/exp10.h
+++ b/libc/src/__support/math/exp10.h
@@ -286,7 +286,7 @@ LIBC_INLINE constexpr double exp10_set_exceptional(double x) {
 
 namespace math {
 
-LIBC_INLINE constexpr double exp10(double x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR double exp10(double x) {
   using FPBits = typename fputil::FPBits<double>;
   FPBits xbits(x);
 
diff --git a/libc/src/__support/math/exp10f.h b/libc/src/__support/math/exp10f.h
index 31d3492d56a5e..6fd386fe27173 100644
--- a/libc/src/__support/math/exp10f.h
+++ b/libc/src/__support/math/exp10f.h
@@ -20,7 +20,7 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
-LIBC_INLINE constexpr float exp10f(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float exp10f(float x) {
   using FPBits = typename fputil::FPBits<float>;
   FPBits xbits(x);
 
diff --git a/libc/src/__support/math/exp10m1f.h b/libc/src/__support/math/exp10m1f.h
index 25cfa13789ebd..f610e9b2d4f70 100644
--- a/libc/src/__support/math/exp10m1f.h
+++ b/libc/src/__support/math/exp10m1f.h
@@ -104,7 +104,7 @@ LIBC_INLINE_VAR constexpr fputil::ExceptValues<float, N_EXCEPTS_HI>
 
 } // namespace exp10m1f_internal
 
-LIBC_INLINE constexpr float exp10m1f(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float exp10m1f(float x) {
   using namespace exp10m1f_internal;
   using FPBits = fputil::FPBits<float>;
   FPBits xbits(x);
diff --git a/libc/src/__support/math/exp2.h b/libc/src/__support/math/exp2.h
index 9a3e9c6f19dec..7f6e17cdbeb09 100644
--- a/libc/src/__support/math/exp2.h
+++ b/libc/src/__support/math/exp2.h
@@ -264,7 +264,7 @@ LIBC_INLINE constexpr double set_exceptional(double x) {
 
 } // namespace exp2_internal
 
-LIBC_INLINE constexpr double exp2(double x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR double exp2(double x) {
   using namespace exp2_internal;
   using FPBits = typename fputil::FPBits<double>;
   FPBits xbits(x);
diff --git a/libc/src/__support/math/exp2f.h b/libc/src/__support/math/exp2f.h
index a231fcedda034..940c80f7113bd 100644
--- a/libc/src/__support/math/exp2f.h
+++ b/libc/src/__support/math/exp2f.h
@@ -26,7 +26,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float exp2f(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float exp2f(float x) {
   using FPBits = typename fputil::FPBits<float>;
   FPBits xbits(x);
 
diff --git a/libc/src/__support/math/exp2m1f.h b/libc/src/__support/math/exp2m1f.h
index f1acde27ac0e1..8699378492df3 100644
--- a/libc/src/__support/math/exp2m1f.h
+++ b/libc/src/__support/math/exp2m1f.h
@@ -26,7 +26,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float exp2m1f(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float exp2m1f(float x) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
   constexpr size_t N_EXCEPTS_LO = 8;
 
diff --git a/libc/src/__support/math/expf.h b/libc/src/__support/math/expf.h
index 5fcf0ffa97d5c..d40230cadafe4 100644
--- a/libc/src/__support/math/expf.h
+++ b/libc/src/__support/math/expf.h
@@ -24,7 +24,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float expf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float expf(float x) {
   using FPBits = typename fputil::FPBits<float>;
   FPBits xbits(x);
 
diff --git a/libc/src/__support/math/expm1.h b/libc/src/__support/math/expm1.h
index 2e07e10883547..9deeac1bf2c5f 100644
--- a/libc/src/__support/math/expm1.h
+++ b/libc/src/__support/math/expm1.h
@@ -279,7 +279,7 @@ LIBC_INLINE constexpr double set_exceptional(double x) {
 
 } // namespace expm1_internal
 
-LIBC_INLINE constexpr double expm1(double x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR double expm1(double x) {
   using namespace expm1_internal;
 
   using FPBits = typename fputil::FPBits<double>;
diff --git a/libc/src/__support/math/expm1f.h b/libc/src/__support/math/expm1f.h
index f581635f77c7b..993c9eeb4a476 100644
--- a/libc/src/__support/math/expm1f.h
+++ b/libc/src/__support/math/expm1f.h
@@ -27,7 +27,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float expm1f(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float expm1f(float x) {
   using namespace common_constants_internal;
   using FPBits = typename fputil::FPBits<float>;
   FPBits xbits(x);
diff --git a/libc/src/__support/math/rsqrtf.h b/libc/src/__support/math/rsqrtf.h
index 1e98a5dbb428f..89707dd228131 100644
--- a/libc/src/__support/math/rsqrtf.h
+++ b/libc/src/__support/math/rsqrtf.h
@@ -20,7 +20,7 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
-LIBC_INLINE constexpr float rsqrtf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float rsqrtf(float x) {
   using FPBits = fputil::FPBits<float>;
   FPBits xbits(x);
 
diff --git a/libc/src/__support/math/sin.h b/libc/src/__support/math/sin.h
index 124df61b1dc80..6d579b33bea0f 100644
--- a/libc/src/__support/math/sin.h
+++ b/libc/src/__support/math/sin.h
@@ -29,7 +29,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr double sin(double x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR double sin(double x) {
   using namespace math::range_reduction_double_internal;
   using FPBits = typename fputil::FPBits<double>;
   FPBits xbits(x);
diff --git a/libc/src/__support/math/sinhf.h b/libc/src/__support/math/sinhf.h
index 6af34412129fc..4972957bb4aae 100644
--- a/libc/src/__support/math/sinhf.h
+++ b/libc/src/__support/math/sinhf.h
@@ -20,7 +20,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr float sinhf(float x) {
+LIBC_INLINE LIBC_MATH_CONSTEXPR float sinhf(float x) {
   using FPBits = typename fputil::FPBits<float>;
   FPBits xbits(x);
   uint32_t x_abs = xbits.abs().uintval();
diff --git a/libc/src/__support/math/tan.h b/libc/src/__support/math/tan.h
index 27cd4b7a044ab..7e01dbed4d590 100644
--- a/libc/src/__support/math/tan.h
+++ b/libc/src/__support/math/tan.h
@@ -83,7 +83,7 @@ LIBC_INLINE double tan_eval(const DoubleDouble &u, DoubleDouble &result) {
   //          + x^11 * 1382/155925 + x^13 * 21844/6081075 +
   //          + x^15 * 929569/638512875 + x^17 * 6404582/10854718875
   // Relative errors < 2^-127 for |u| < pi/256.
-  constexpr Float128 TAN_COEFFS[] = {
+  const Float128 TAN_COEFFS[] = {
       {Sign::POS, -127, 0x80000000'00000000'00000000'00000000_u128}, // 1
       {Sign::POS, -129, 0xaaaaaaaa'aaaaaaaa'aaaaaaaa'aaaaaaab_u128}, // 1
       {Sign::POS, -130, 0x88888888'88888888'88888888'88888889_u128}, // 2/15
@@ -111,7 +111,7 @@ LIBC_INLINE double tan_eval(const DoubleDouble &u, DoubleDouble &result) {
 [[maybe_unused]] Float128 newton_raphson_div(const Float128 &a, Float128 b,
                                              double q) {
   Float128 q0(q);
-  constexpr Float128 TWO(2.0);
+  const Float128 TWO(2.0);
   b.sign = (b.sign == Sign::POS) ? Sign::NEG : Sign::POS;
   Float128 q1 =
       fputil::quick_mul(q0, fputil::quick_add(TWO, fputil::quick_mul(b, q0)));
diff --git a/libc/src/__support/math_extras.h b/libc/src/__support/math_extras.h
index b8abf8041c8e7..928408aae4c36 100644
--- a/libc/src/__support/math_extras.h
+++ b/libc/src/__support/math_extras.h
@@ -64,7 +64,7 @@ template <typename T>
 #if __has_builtin(__builtin_add_overflow)
   return __builtin_add_overflow(a, b, &res);
 #else
-  res = a + b;
+  res = static_cast<T>(a + b);
   return (res < a) || (res < b);
 #endif // __builtin_add_overflow
 }
@@ -75,7 +75,7 @@ template <typename T>
 #if __has_builtin(__builtin_sub_overflow)
   return __builtin_sub_overflow(a, b, &res);
 #else
-  res = a - b;
+  res = static_cast<T>(a - b);
   return (res > a);
 #endif // __builtin_sub_overflow
 }
diff --git a/libc/src/__support/str_to_integer.h b/libc/src/__support/str_to_integer.h
index 36f1d05eb2844..22026157d108b 100644
--- a/libc/src/__support/str_to_integer.h
+++ b/libc/src/__support/str_to_integer.h
@@ -152,13 +152,14 @@ strtointeger(const CharType *__restrict src, int base,
       result = abs_max;
       error_val = ERANGE;
     } else {
-      result = result * static_cast<ResultType>(base);
+      result = static_cast<ResultType>(result * static_cast<ResultType>(base));
     }
     if (result > abs_max - static_cast<ResultType>(cur_digit)) {
       result = abs_max;
       error_val = ERANGE;
     } else {
-      result = result + static_cast<ResultType>(cur_digit);
+      result =
+          static_cast<ResultType>(result + static_cast<ResultType>(cur_digit));
     }
   }
 
diff --git a/libc/src/string/memory_utils/op_generic.h b/libc/src/string/memory_utils/op_generic.h
index a86cbd8bcfc72..e9a18c5c9c93c 100644
--- a/libc/src/string/memory_utils/op_generic.h
+++ b/libc/src/string/memory_utils/op_generic.h
@@ -149,7 +149,8 @@ template <typename T> void store(Ptr dst, T value) {
 template <typename T> T splat(uint8_t value) {
   static_assert(is_scalar_v<T> || is_vector_v<T>);
   if constexpr (is_scalar_v<T>)
-    return T(~0) / T(0xFF) * T(value);
+    return static_cast<T>(static_cast<T>(~0) / static_cast<T>(0xFF) *
+                          static_cast<T>(value));
   else if constexpr (is_vector_v<T>) {
     T out;
     // This for loop is optimized out for vector types.
diff --git a/libc/src/string/memory_utils/utils.h b/libc/src/string/memory_utils/utils.h
index 6f6882b49223b..0458c4d6c55a6 100644
--- a/libc/src/string/memory_utils/utils.h
+++ b/libc/src/string/memory_utils/utils.h
@@ -94,8 +94,12 @@ LIBC_INLINE void memcpy_inline(void *__restrict dst,
 #ifndef LIBC_COMPILER_IS_MSVC
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Warray-bounds"
+#if defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 1100)
 #pragma GCC diagnostic ignored "-Wstringop-overread"
+#endif
+#if defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 700)
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #endif // !LIBC_COMPILER_IS_MSVC
   for (size_t i = 0; i < Size; ++i)
     static_cast<char *>(dst)[i] = static_cast<const char *>(src)[i];
diff --git a/libc/src/string/memory_utils/x86_64/inline_memcpy.h b/libc/src/string/memory_utils/x86_64/inline_memcpy.h
index e569ecceb80cc..36e4da476bc96 100644
--- a/libc/src/string/memory_utils/x86_64/inline_memcpy.h
+++ b/libc/src/string/memory_utils/x86_64/inline_memcpy.h
@@ -156,7 +156,7 @@ inline_memcpy_x86_avx_ge64_sw_prefetching(Ptr __restrict dst,
   // If we are using the Non-temporal stores, we don't need prefetching
   bool need_prefetch_run = true;
   if constexpr (x86::K_NTA_THRESHOLD != 0) {
-    if (count >= x86::K_NTA_THRESHOLD) {
+    if (count >= (x86::K_NTA_THRESHOLD ? x86::K_NTA_THRESHOLD : 1)) {
       while (offset + K_THREE_CACHELINES + 64 <= count) {
         for (size_t i = 0; i < 3; ++i, offset += K_ONE_CACHELINE) {
           generic::stream(dst + offset, generic::load<__m256i>(src + offset));
diff --git a/libc/src/string/memory_utils/x86_64/inline_strlen.h b/libc/src/string/memory_utils/x86_64/inline_strlen.h
index 74b6820a50ff1..2def8d3b3c9ef 100644
--- a/libc/src/string/memory_utils/x86_64/inline_strlen.h
+++ b/libc/src/string/memory_utils/x86_64/inline_strlen.h
@@ -23,8 +23,7 @@ template <typename Vector, typename Mask>
 LIBC_NO_SANITIZE_OOB_ACCESS LIBC_INLINE static Mask
 compare_and_mask(const Vector *block_ptr, char c);
 
-template <typename Vector, typename Mask,
-          decltype(compare_and_mask<Vector, Mask>)>
+template <typename Vector, typename Mask, Mask (*)(const Vector *, char)>
 LIBC_NO_SANITIZE_OOB_ACCESS LIBC_INLINE static size_t
 string_length_vector(const char *src) {
   uintptr_t misalign_bytes = reinterpret_cast<uintptr_t>(src) % sizeof(Vector);
@@ -55,8 +54,7 @@ calculate_find_first_character_return(const unsigned char *src, Mask c_mask,
   return const_cast<unsigned char *>(src) + c_offset;
 }
 
-template <typename Vector, typename Mask,
-          decltype(compare_and_mask<Vector, Mask>)>
+template <typename Vector, typename Mask, Mask (*)(const Vector *, char)>
 LIBC_NO_SANITIZE_OOB_ACCESS LIBC_INLINE static void *
 find_first_character_vector(const unsigned char *s, unsigned char c, size_t n) {
   uintptr_t misalign_bytes = reinterpret_cast<uintptr_t>(s) % sizeof(Vector);

>From 0be78466535ba467a7bc47d87a2f334b238a19a0 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 15 May 2026 15:43:13 +0000
Subject: [PATCH 2/2] Fix aarch64.

---
 libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake | 8 ++++++++
 libc/src/__support/FPUtil/generic/sqrt.h          | 3 ++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake b/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake
index 4b8f1c3399ff5..5bf9c0d318ff0 100644
--- a/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake
+++ b/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake
@@ -30,6 +30,14 @@ endif()
 set(LIBC_COMPILE_OPTIONS_NATIVE "${_libc_native_default}" CACHE STRING
     "Compile options for host-native builds.  Set to empty to disable -march=native.")
 
+if(LIBC_COMPILE_OPTIONS_NATIVE)
+  check_cxx_compiler_flag("${LIBC_COMPILE_OPTIONS_NATIVE}" LIBC_COMPILER_HAS_NATIVE)
+  if(NOT LIBC_COMPILER_HAS_NATIVE)
+    set(LIBC_COMPILE_OPTIONS_NATIVE "" CACHE STRING
+        "Compile options for host-native builds.  Set to empty to disable -march=native." FORCE)
+  endif()
+endif()
+
 # Making sure ALL_CPU_FEATURES is sorted.
 list(SORT ALL_CPU_FEATURES)
 
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index e37c318d815dc..1ae84c41599ae 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -63,7 +63,8 @@ LIBC_INLINE void normalize<long double>(int &exponent, UInt128 &mantissa) {
       hi_bits ? (cpp::countl_zero(hi_bits) - 15)
               : (cpp::countl_zero(static_cast<uint64_t>(mantissa)) + 49);
   exponent -= shift;
-  mantissa = static_cast<typename FPBits<T>::StorageType>(mantissa << shift);
+  mantissa =
+      static_cast<typename FPBits<long double>::StorageType>(mantissa << shift);
 }
 #endif
 



More information about the libc-commits mailing list