[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