[libc-commits] [libc] [libc] Fix various MSVC compatibility issues. (PR #233984)
via libc-commits
libc-commits at lists.llvm.org
Tue Oct 20 13:47:24 PDT 2026
https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/233984
>From a47b0014e1440c19b668007956045a45c4a1db8d Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Tue, 20 Oct 2026 20:26:25 +0000
Subject: [PATCH 1/2] [libc] Fix various MSVC compatibility issues.
---
libc/src/__support/CPP/cstddef.h | 2 +-
libc/src/__support/CPP/new.h | 3 ++-
libc/src/__support/FPUtil/FMA.h | 23 +++++++++++++++++++
libc/src/__support/FPUtil/FPBits.h | 2 +-
.../FPUtil/aarch64/nearest_integer.h | 13 +++++++++++
libc/src/__support/FPUtil/aarch64/sqrt.h | 13 +++++++++++
libc/src/__support/FPUtil/cast.h | 8 ++++---
libc/src/__support/FPUtil/float80.h | 2 +-
libc/src/__support/FPUtil/fp_bitwise.h | 23 ++++++++++++++-----
libc/src/__support/FPUtil/multiply_add.h | 21 +++++++++++++++++
libc/src/__support/FPUtil/nearest_integer.h | 4 +++-
libc/src/__support/FPUtil/sqrt.h | 2 +-
.../__support/FPUtil/x86_64/nearest_integer.h | 12 ++++++----
libc/src/__support/FPUtil/x86_64/sqrt.h | 19 +++++++++++++++
libc/src/__support/macros/attributes.h | 14 ++++++++++-
.../__support/macros/properties/compiler.h | 2 +-
.../macros/properties/cpu_features.h | 17 ++++++++++----
libc/src/__support/math/exp10f_double_eval.h | 3 ++-
libc/src/__support/str_to_integer.h | 4 ++--
19 files changed, 158 insertions(+), 29 deletions(-)
diff --git a/libc/src/__support/CPP/cstddef.h b/libc/src/__support/CPP/cstddef.h
index 559a2c2494b3b..1507789cb1b10 100644
--- a/libc/src/__support/CPP/cstddef.h
+++ b/libc/src/__support/CPP/cstddef.h
@@ -20,7 +20,7 @@ namespace cpp {
// `::std::byte` type (see `Type::isStdByteType()`), so `cpp::byte` would
// otherwise get its own TBAA node. `may_alias` makes accesses through
// `cpp::byte *` char-aliasing as callers expect.
-enum class [[gnu::may_alias]] byte : unsigned char {};
+enum class LIBC_MAY_ALIAS byte : unsigned char {};
template <class IntegerType>
LIBC_INLINE constexpr enable_if_t<is_integral_v<IntegerType>, byte>
diff --git a/libc/src/__support/CPP/new.h b/libc/src/__support/CPP/new.h
index 47a8f1b9b8302..8f9bf5344d8d7 100644
--- a/libc/src/__support/CPP/new.h
+++ b/libc/src/__support/CPP/new.h
@@ -30,7 +30,8 @@ namespace LIBC_NAMESPACE_DECL {
namespace cpp {
template <class T> [[nodiscard]] constexpr T *launder(T *p) {
- static_assert(__has_builtin(__builtin_launder),
+ static_assert(__has_builtin(__builtin_launder) ||
+ defined(LIBC_COMPILER_IS_MSVC),
"cpp::launder requires __builtin_launder");
return __builtin_launder(p);
}
diff --git a/libc/src/__support/FPUtil/FMA.h b/libc/src/__support/FPUtil/FMA.h
index 2cafb4c0974e3..a5201f321b775 100644
--- a/libc/src/__support/FPUtil/FMA.h
+++ b/libc/src/__support/FPUtil/FMA.h
@@ -13,8 +13,19 @@
#include "src/__support/FPUtil/generic/FMA.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/macros/properties/compiler.h"
#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
+#if defined(LIBC_TARGET_CPU_HAS_FMA) && \
+ !__has_builtin(__builtin_elementwise_fma) && \
+ defined(LIBC_COMPILER_IS_MSVC)
+#if defined(LIBC_TARGET_ARCH_IS_X86)
+#include <immintrin.h>
+#elif defined(LIBC_TARGET_ARCH_IS_AARCH64)
+#include <arm64_neon.h>
+#endif
+#endif
+
namespace LIBC_NAMESPACE_DECL {
namespace fputil {
@@ -29,6 +40,12 @@ LIBC_INLINE OutType fma(InType x, InType y, InType z) {
template <> LIBC_INLINE float fma(float x, float y, float z) {
#if __has_builtin(__builtin_elementwise_fma)
return __builtin_elementwise_fma(x, y, z);
+#elif defined(LIBC_COMPILER_IS_MSVC) && defined(LIBC_TARGET_ARCH_IS_X86)
+ return _mm_cvtss_f32(
+ _mm_fmadd_ss(_mm_set_ss(x), _mm_set_ss(y), _mm_set_ss(z)));
+#elif defined(LIBC_COMPILER_IS_MSVC) && defined(LIBC_TARGET_ARCH_IS_AARCH64)
+ return vget_lane_f32(vfma_f32(vdup_n_f32(z), vdup_n_f32(x), vdup_n_f32(y)),
+ 0);
#else
return __builtin_fmaf(x, y, z);
#endif
@@ -39,6 +56,12 @@ template <> LIBC_INLINE float fma(float x, float y, float z) {
template <> LIBC_INLINE double fma(double x, double y, double z) {
#if __has_builtin(__builtin_elementwise_fma)
return __builtin_elementwise_fma(x, y, z);
+#elif defined(LIBC_COMPILER_IS_MSVC) && defined(LIBC_TARGET_ARCH_IS_X86)
+ return _mm_cvtsd_f64(
+ _mm_fmadd_sd(_mm_set_sd(x), _mm_set_sd(y), _mm_set_sd(z)));
+#elif defined(LIBC_COMPILER_IS_MSVC) && defined(LIBC_TARGET_ARCH_IS_AARCH64)
+ return vget_lane_f64(vfma_f64(vdup_n_f64(z), vdup_n_f64(x), vdup_n_f64(y)),
+ 0);
#else
return __builtin_fma(x, y, z);
#endif
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 6127dede03f4a..5b92fbaa82ecc 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -127,7 +127,7 @@ template <> struct FPLayout<FPType::IEEE754_Binary128> {
};
template <> struct FPLayout<FPType::X86_Binary80> {
-#if __SIZEOF_LONG_DOUBLE__ == 12
+#if defined(__SIZEOF_LONG_DOUBLE__) && (__SIZEOF_LONG_DOUBLE__ == 12)
using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
#else
using StorageType = UInt128;
diff --git a/libc/src/__support/FPUtil/aarch64/nearest_integer.h b/libc/src/__support/FPUtil/aarch64/nearest_integer.h
index d5ea0678825fd..9f6a5b97d64e4 100644
--- a/libc/src/__support/FPUtil/aarch64/nearest_integer.h
+++ b/libc/src/__support/FPUtil/aarch64/nearest_integer.h
@@ -12,24 +12,37 @@
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/macros/properties/compiler.h"
#if !defined(LIBC_TARGET_ARCH_IS_AARCH64)
#error "Invalid include"
#endif
+#ifdef LIBC_COMPILER_IS_MSVC
+#include <arm64_neon.h>
+#endif
+
namespace LIBC_NAMESPACE_DECL {
namespace fputil {
LIBC_INLINE float nearest_integer(float x) {
+#ifdef LIBC_COMPILER_IS_MSVC
+ return vget_lane_f32(vrndn_f32(vdup_n_f32(x)), 0);
+#else
float result;
__asm__ __volatile__("frintn %s0, %s1\n\t" : "=w"(result) : "w"(x));
return result;
+#endif
}
LIBC_INLINE double nearest_integer(double x) {
+#ifdef LIBC_COMPILER_IS_MSVC
+ return vget_lane_f64(vrndn_f64(vdup_n_f64(x)), 0);
+#else
double result;
__asm__ __volatile__("frintn %d0, %d1\n\t" : "=w"(result) : "w"(x));
return result;
+#endif
}
} // namespace fputil
diff --git a/libc/src/__support/FPUtil/aarch64/sqrt.h b/libc/src/__support/FPUtil/aarch64/sqrt.h
index 4eb576bf2244c..be9cb1f1cea43 100644
--- a/libc/src/__support/FPUtil/aarch64/sqrt.h
+++ b/libc/src/__support/FPUtil/aarch64/sqrt.h
@@ -12,6 +12,7 @@
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/macros/properties/compiler.h"
#include "src/__support/macros/properties/cpu_features.h"
#if !defined(LIBC_TARGET_ARCH_IS_AARCH64)
@@ -20,22 +21,34 @@
#include "src/__support/FPUtil/generic/sqrt.h"
+#ifdef LIBC_COMPILER_IS_MSVC
+#include <arm64_neon.h>
+#endif
+
namespace LIBC_NAMESPACE_DECL {
namespace fputil {
#ifdef LIBC_TARGET_CPU_HAS_FPU_FLOAT
template <> LIBC_INLINE float sqrt<float>(float x) {
+#ifdef LIBC_COMPILER_IS_MSVC
+ return vget_lane_f32(vsqrt_f32(vdup_n_f32(x)), 0);
+#else
float y;
asm("fsqrt %s0, %s1\n\t" : "=w"(y) : "w"(x));
return y;
+#endif
}
#endif // LIBC_TARGET_CPU_HAS_FPU_FLOAT
#ifdef LIBC_TARGET_CPU_HAS_FPU_DOUBLE
template <> LIBC_INLINE double sqrt<double>(double x) {
+#ifdef LIBC_COMPILER_IS_MSVC
+ return vget_lane_f64(vsqrt_f64(vdup_n_f64(x)), 0);
+#else
double y;
asm("fsqrt %d0, %d1\n\t" : "=w"(y) : "w"(x));
return y;
+#endif
}
#endif // LIBC_TARGET_CPU_HAS_FPU_DOUBLE
diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
index 2a9bfd5a9f62e..7c1c3114f70bf 100644
--- a/libc/src/__support/FPUtil/cast.h
+++ b/libc/src/__support/FPUtil/cast.h
@@ -16,7 +16,8 @@
#include "src/__support/CPP/type_traits.h"
#include "src/__support/macros/properties/types.h"
-namespace LIBC_NAMESPACE::fputil {
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil {
// TODO: Add optimization for known good targets with fast
// float to float16 conversion:
@@ -55,7 +56,7 @@ cast(InType x) {
}
InStorageType x_mant = x_bits.get_mantissa();
- if (InFPBits::FRACTION_LEN > OutFPBits::FRACTION_LEN)
+ if constexpr (InFPBits::FRACTION_LEN > OutFPBits::FRACTION_LEN)
x_mant >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
return OutFPBits::quiet_nan(x_bits.sign(),
static_cast<OutStorageType>(x_mant))
@@ -75,6 +76,7 @@ cast(InType x) {
}
}
-} // namespace LIBC_NAMESPACE::fputil
+} // namespace fputil
+} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H
diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index c0bc40cd6c1aa..56f3434122bac 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -26,7 +26,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace fputil {
struct Float80 {
-#if __SIZEOF_LONG_DOUBLE__ == 12
+#if defined(__SIZEOF_LONG_DOUBLE__) && (__SIZEOF_LONG_DOUBLE__ == 12)
UInt<96> bits;
#else
UInt128 bits;
diff --git a/libc/src/__support/FPUtil/fp_bitwise.h b/libc/src/__support/FPUtil/fp_bitwise.h
index 5902b8e30aac5..fad64bf398402 100644
--- a/libc/src/__support/FPUtil/fp_bitwise.h
+++ b/libc/src/__support/FPUtil/fp_bitwise.h
@@ -19,12 +19,18 @@
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/macros/properties/compiler.h"
#include "src/__support/macros/properties/cpu_features.h"
#ifdef LIBC_TARGET_CPU_HAS_SSE2
#include <immintrin.h>
-#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_NEON)
+#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && \
+ defined(LIBC_TARGET_CPU_HAS_ARM_NEON)
+#ifdef LIBC_COMPILER_IS_MSVC
+#include <arm64_neon.h>
+#else
#include <arm_neon.h>
+#endif
#endif // LIBC_TARGET_CPU_HAS_SSE2
namespace LIBC_NAMESPACE_DECL {
@@ -42,7 +48,8 @@ fp_and(T a, T b) {
return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(a), _mm_set_ss(b)));
if constexpr (cpp::is_same_v<T, double>)
return _mm_cvtsd_f64(_mm_and_pd(_mm_set_sd(a), _mm_set_sd(b)));
-#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_NEON)
+#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && \
+ defined(LIBC_TARGET_CPU_HAS_ARM_NEON)
if constexpr (cpp::is_same_v<T, float>)
return vget_lane_f32(
vreinterpret_f32_u32(vand_u32(vreinterpret_u32_f32(vdup_n_f32(a)),
@@ -73,7 +80,8 @@ fp_or(T a, T b) {
return _mm_cvtss_f32(_mm_or_ps(_mm_set_ss(a), _mm_set_ss(b)));
if constexpr (cpp::is_same_v<T, double>)
return _mm_cvtsd_f64(_mm_or_pd(_mm_set_sd(a), _mm_set_sd(b)));
-#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_NEON)
+#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && \
+ defined(LIBC_TARGET_CPU_HAS_ARM_NEON)
if constexpr (cpp::is_same_v<T, float>)
return vget_lane_f32(
vreinterpret_f32_u32(vorr_u32(vreinterpret_u32_f32(vdup_n_f32(a)),
@@ -104,7 +112,8 @@ fp_xor(T a, T b) {
return _mm_cvtss_f32(_mm_xor_ps(_mm_set_ss(a), _mm_set_ss(b)));
if constexpr (cpp::is_same_v<T, double>)
return _mm_cvtsd_f64(_mm_xor_pd(_mm_set_sd(a), _mm_set_sd(b)));
-#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_NEON)
+#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && \
+ defined(LIBC_TARGET_CPU_HAS_ARM_NEON)
if constexpr (cpp::is_same_v<T, float>)
return vget_lane_f32(
vreinterpret_f32_u32(veor_u32(vreinterpret_u32_f32(vdup_n_f32(a)),
@@ -135,7 +144,8 @@ fp_andnot(T a, T b) {
return _mm_cvtss_f32(_mm_andnot_ps(_mm_set_ss(b), _mm_set_ss(a)));
if constexpr (cpp::is_same_v<T, double>)
return _mm_cvtsd_f64(_mm_andnot_pd(_mm_set_sd(b), _mm_set_sd(a)));
-#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_NEON)
+#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && \
+ defined(LIBC_TARGET_CPU_HAS_ARM_NEON)
if constexpr (cpp::is_same_v<T, float>)
return vget_lane_f32(
vreinterpret_f32_u32(vbic_u32(vreinterpret_u32_f32(vdup_n_f32(a)),
@@ -167,7 +177,8 @@ fp_not(T a) {
if constexpr (cpp::is_same_v<T, double>)
return _mm_cvtsd_f64(
_mm_xor_pd(_mm_set_sd(a), _mm_castsi128_pd(_mm_set1_epi64x(-1))));
-#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_NEON)
+#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && \
+ defined(LIBC_TARGET_CPU_HAS_ARM_NEON)
if constexpr (cpp::is_same_v<T, float>)
return vget_lane_f32(
vreinterpret_f32_u32(vmvn_u32(vreinterpret_u32_f32(vdup_n_f32(a)))),
diff --git a/libc/src/__support/FPUtil/multiply_add.h b/libc/src/__support/FPUtil/multiply_add.h
index fe87877d2443d..f7f30035c7739 100644
--- a/libc/src/__support/FPUtil/multiply_add.h
+++ b/libc/src/__support/FPUtil/multiply_add.h
@@ -18,6 +18,7 @@
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/macros/properties/compiler.h"
#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
namespace LIBC_NAMESPACE_DECL {
@@ -46,6 +47,14 @@ multiply_add(T x, T y, T z) {
#if defined(LIBC_TARGET_CPU_HAS_FMA) && !defined(LIBC_USE_CONSTEXPR)
+#if !__has_builtin(__builtin_elementwise_fma) && defined(LIBC_COMPILER_IS_MSVC)
+#if defined(LIBC_TARGET_ARCH_IS_X86)
+#include <immintrin.h>
+#elif defined(LIBC_TARGET_ARCH_IS_AARCH64)
+#include <arm64_neon.h>
+#endif
+#endif
+
// FMA instructions are available.
// We use builtins directly instead of including FMA.h to avoid a circular
// dependency: multiply_add.h -> FMA.h -> generic/FMA.h -> dyadic_float.h.
@@ -63,6 +72,12 @@ namespace fputil {
LIBC_INLINE float multiply_add(float x, float y, float z) {
#if __has_builtin(__builtin_elementwise_fma)
return __builtin_elementwise_fma(x, y, z);
+#elif defined(LIBC_COMPILER_IS_MSVC) && defined(LIBC_TARGET_ARCH_IS_X86)
+ return _mm_cvtss_f32(
+ _mm_fmadd_ss(_mm_set_ss(x), _mm_set_ss(y), _mm_set_ss(z)));
+#elif defined(LIBC_COMPILER_IS_MSVC) && defined(LIBC_TARGET_ARCH_IS_AARCH64)
+ return vget_lane_f32(vfma_f32(vdup_n_f32(z), vdup_n_f32(x), vdup_n_f32(y)),
+ 0);
#else
return __builtin_fmaf(x, y, z);
#endif
@@ -73,6 +88,12 @@ LIBC_INLINE float multiply_add(float x, float y, float z) {
LIBC_INLINE double multiply_add(double x, double y, double z) {
#if __has_builtin(__builtin_elementwise_fma)
return __builtin_elementwise_fma(x, y, z);
+#elif defined(LIBC_COMPILER_IS_MSVC) && defined(LIBC_TARGET_ARCH_IS_X86)
+ return _mm_cvtsd_f64(
+ _mm_fmadd_sd(_mm_set_sd(x), _mm_set_sd(y), _mm_set_sd(z)));
+#elif defined(LIBC_COMPILER_IS_MSVC) && defined(LIBC_TARGET_ARCH_IS_AARCH64)
+ return vget_lane_f64(vfma_f64(vdup_n_f64(z), vdup_n_f64(x), vdup_n_f64(y)),
+ 0);
#else
return __builtin_fma(x, y, z);
#endif
diff --git a/libc/src/__support/FPUtil/nearest_integer.h b/libc/src/__support/FPUtil/nearest_integer.h
index f131181fd2c61..c9d55a2e61af0 100644
--- a/libc/src/__support/FPUtil/nearest_integer.h
+++ b/libc/src/__support/FPUtil/nearest_integer.h
@@ -17,7 +17,9 @@
#if (defined(LIBC_TARGET_ARCH_IS_X86_64) && defined(LIBC_TARGET_CPU_HAS_SSE4_2))
#include "x86_64/nearest_integer.h"
-#elif (defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_FP))
+#elif (defined(LIBC_TARGET_ARCH_IS_AARCH64) && \
+ defined(LIBC_TARGET_CPU_HAS_FPU_FLOAT) && \
+ defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE))
#include "aarch64/nearest_integer.h"
#elif defined(LIBC_TARGET_ARCH_IS_GPU)
diff --git a/libc/src/__support/FPUtil/sqrt.h b/libc/src/__support/FPUtil/sqrt.h
index fbc279a128ff7..e8540adc753b7 100644
--- a/libc/src/__support/FPUtil/sqrt.h
+++ b/libc/src/__support/FPUtil/sqrt.h
@@ -50,7 +50,7 @@ template <> LIBC_INLINE long double sqrt<long double>(long double x) {
// Use inline assembly when __builtin_elementwise_sqrt is not available.
#if defined(LIBC_TARGET_CPU_HAS_SSE2) && defined(LIBC_TARGET_ARCH_IS_X86_64)
#include "x86_64/sqrt.h"
-#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_FP)
+#elif defined(LIBC_TARGET_ARCH_IS_AARCH64)
#include "aarch64/sqrt.h"
#elif defined(LIBC_TARGET_ARCH_IS_ARM)
#include "arm/sqrt.h"
diff --git a/libc/src/__support/FPUtil/x86_64/nearest_integer.h b/libc/src/__support/FPUtil/x86_64/nearest_integer.h
index d57db0dacf013..a011e7321e43d 100644
--- a/libc/src/__support/FPUtil/x86_64/nearest_integer.h
+++ b/libc/src/__support/FPUtil/x86_64/nearest_integer.h
@@ -12,12 +12,14 @@
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/macros/properties/compiler.h"
+#include "src/__support/macros/properties/cpu_features.h"
#if !defined(LIBC_TARGET_ARCH_IS_X86_64)
#error "Invalid include"
#endif
-#if !defined(__SSE4_2__)
+#if !defined(LIBC_TARGET_CPU_HAS_SSE4_2)
#error "SSE4.2 instruction set is not supported"
#endif
@@ -38,11 +40,11 @@ namespace fputil {
// without the extra lane-zeroing instructions required by `_mm_round_ps` /
// `_mm_round_pd`.
LIBC_INLINE float nearest_integer(float x) {
-#ifdef __AVX__
+#if defined(__AVX__) || defined(LIBC_COMPILER_IS_MSVC)
__m128 xmm = _mm_set_ss(x); // NOLINT
__m128 ymm =
_mm_round_ss(xmm, xmm, _MM_ROUND_NEAREST | _MM_FROUND_NO_EXC); // NOLINT
- return ymm[0];
+ return _mm_cvtss_f32(ymm);
#else
LIBC_INLINE_ASM("roundss %1, %0, %0" : "+x"(x) : "i"(_MM_ROUND_NEAREST |
_MM_FROUND_NO_EXC));
@@ -51,11 +53,11 @@ LIBC_INLINE float nearest_integer(float x) {
}
LIBC_INLINE double nearest_integer(double x) {
-#ifdef __AVX__
+#if defined(__AVX__) || defined(LIBC_COMPILER_IS_MSVC)
__m128d xmm = _mm_set_sd(x); // NOLINT
__m128d ymm =
_mm_round_sd(xmm, xmm, _MM_ROUND_NEAREST | _MM_FROUND_NO_EXC); // NOLINT
- return ymm[0];
+ return _mm_cvtsd_f64(ymm);
#else
LIBC_INLINE_ASM("roundsd %1, %0, %0" : "+x"(x) : "i"(_MM_ROUND_NEAREST |
_MM_FROUND_NO_EXC));
diff --git a/libc/src/__support/FPUtil/x86_64/sqrt.h b/libc/src/__support/FPUtil/x86_64/sqrt.h
index 68ce627a57025..9c8545c1b8fd7 100644
--- a/libc/src/__support/FPUtil/x86_64/sqrt.h
+++ b/libc/src/__support/FPUtil/x86_64/sqrt.h
@@ -12,6 +12,7 @@
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/macros/properties/compiler.h"
#include "src/__support/macros/properties/cpu_features.h"
#if !defined(LIBC_TARGET_CPU_HAS_SSE2)
@@ -20,26 +21,44 @@
#include "src/__support/FPUtil/generic/sqrt.h"
+#ifdef LIBC_COMPILER_IS_MSVC
+#include <immintrin.h>
+#endif
+
namespace LIBC_NAMESPACE_DECL {
namespace fputil {
template <> LIBC_INLINE float sqrt<float>(float x) {
+#ifdef LIBC_COMPILER_IS_MSVC
+ return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(x)));
+#else
float result;
__asm__ __volatile__("sqrtss %x1, %x0" : "=x"(result) : "x"(x));
return result;
+#endif
}
template <> LIBC_INLINE double sqrt<double>(double x) {
+#ifdef LIBC_COMPILER_IS_MSVC
+ __m128d xmm = _mm_set_sd(x);
+ return _mm_cvtsd_f64(_mm_sqrt_sd(xmm, xmm));
+#else
double result;
__asm__ __volatile__("sqrtsd %x1, %x0" : "=x"(result) : "x"(x));
return result;
+#endif
}
#ifdef LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64
template <> LIBC_INLINE long double sqrt<long double>(long double x) {
+#ifdef LIBC_COMPILER_IS_MSVC
+ __m128d xmm = _mm_set_sd(static_cast<double>(x));
+ return _mm_cvtsd_f64(_mm_sqrt_sd(xmm, xmm));
+#else
long double result;
__asm__ __volatile__("sqrtsd %x1, %x0" : "=x"(result) : "x"(x));
return result;
+#endif
}
#else
template <> LIBC_INLINE long double sqrt<long double>(long double x) {
diff --git a/libc/src/__support/macros/attributes.h b/libc/src/__support/macros/attributes.h
index e251f917d9850..8a5851e30ef15 100644
--- a/libc/src/__support/macros/attributes.h
+++ b/libc/src/__support/macros/attributes.h
@@ -27,7 +27,7 @@
#define LIBC_INLINE inline
#define LIBC_INLINE_VAR inline
#define LIBC_INLINE_ASM __asm__ __volatile__
-#define LIBC_UNUSED __attribute__((unused))
+#define LIBC_UNUSED [[maybe_unused]]
#if __has_attribute(always_inline)
#define LIBC_ALWAYS_INLINE LIBC_INLINE __attribute__((always_inline))
@@ -45,6 +45,18 @@
#define LIBC_NOINLINE
#endif // __has_attribute(noinline)
+#if __has_attribute(cold)
+#define LIBC_COLD __attribute__((cold))
+#else
+#define LIBC_COLD
+#endif // __has_attribute(cold)
+
+#if __has_attribute(may_alias)
+#define LIBC_MAY_ALIAS __attribute__((may_alias))
+#else
+#define LIBC_MAY_ALIAS
+#endif // __has_attribute(may_alias)
+
#ifndef LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
#if (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 900)) || \
(defined(LIBC_COMPILER_IS_CLANG) && LIBC_COMPILER_CLANG_VER >= 900)
diff --git a/libc/src/__support/macros/properties/compiler.h b/libc/src/__support/macros/properties/compiler.h
index 592f6c2ba1c95..ddea49ebbaa5f 100644
--- a/libc/src/__support/macros/properties/compiler.h
+++ b/libc/src/__support/macros/properties/compiler.h
@@ -40,7 +40,7 @@
#define LIBC_COMPILER_MSVC_VER (_MSC_VER)
#ifdef _M_X64
#define LIBC_COMPILER_IS_MSVC_X64
-#else
+#elif defined(_M_IX86)
#define LIBC_COMPILER_IS_MSVC_X86
#endif
#endif
diff --git a/libc/src/__support/macros/properties/cpu_features.h b/libc/src/__support/macros/properties/cpu_features.h
index 77daeb7c1fcc2..6071319008da1 100644
--- a/libc/src/__support/macros/properties/cpu_features.h
+++ b/libc/src/__support/macros/properties/cpu_features.h
@@ -13,6 +13,7 @@
#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CPU_FEATURES_H
#include "architectures.h"
+#include "compiler.h"
#if defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC)
#define LIBC_TARGET_CPU_HAS_FULLFP16
@@ -40,14 +41,15 @@
#define LIBC_TARGET_CPU_HAS_MOPS
#endif
-#if defined(__SSE2__)
+#if defined(__SSE2__) || defined(_M_X64) || \
+ (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
#define LIBC_TARGET_CPU_HAS_SSE2
#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
#define LIBC_TARGET_CPU_GENERIC_VECTOR_SIZE_MAX 128
#endif
-#if defined(__SSE4_2__)
+#if defined(__SSE4_2__) || defined(__AVX__)
#define LIBC_TARGET_CPU_HAS_SSE4_2
#endif
@@ -88,9 +90,14 @@
#define LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE
#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
#endif // LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE
+#elif defined(_M_ARM64) || defined(_M_ARM64EC)
+#define LIBC_TARGET_CPU_HAS_ARM_FPU_FLOAT
+#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
+#define LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE
+#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
#endif // __ARM_FP
-#if defined(__ARM_NEON)
+#if defined(__ARM_NEON) || defined(_M_ARM64) || defined(_M_ARM64EC)
#define LIBC_TARGET_CPU_HAS_ARM_NEON
#define LIBC_TARGET_CPU_GENERIC_VECTOR_SIZE_MAX 512
#endif
@@ -120,7 +127,9 @@
#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
#endif
-#if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \
+#if defined(__ARM_FEATURE_FMA) || defined(_M_ARM64) || defined(_M_ARM64EC) || \
+ (defined(__AVX2__) && defined(__FMA__)) || \
+ (defined(LIBC_COMPILER_IS_MSVC) && defined(__AVX2__)) || \
defined(__NVPTX__) || defined(__AMDGPU__) || defined(__riscv_flen) || \
defined(__SPIRV__)
#define LIBC_TARGET_CPU_HAS_FMA
diff --git a/libc/src/__support/math/exp10f_double_eval.h b/libc/src/__support/math/exp10f_double_eval.h
index 75daf79bf6769..a2d55f9b98b87 100644
--- a/libc/src/__support/math/exp10f_double_eval.h
+++ b/libc/src/__support/math/exp10f_double_eval.h
@@ -19,6 +19,7 @@
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/nearest_integer.h"
#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h"
#include "src/__support/math/exp10f_utils.h"
@@ -43,7 +44,7 @@ LIBC_INLINE float exp10f_mid(float x) {
return static_cast<float>(multiply_add(p, lo2 * rr.mh, c0 * rr.mh));
}
-[[gnu::cold, gnu::noinline]] LIBC_INLINE float exp10f_slow(float x) {
+LIBC_COLD LIBC_NOINLINE LIBC_INLINE float exp10f_slow(float x) {
using FPBits = fputil::FPBits<float>;
FPBits xbits(x);
diff --git a/libc/src/__support/str_to_integer.h b/libc/src/__support/str_to_integer.h
index e6e599738bf44..282d26dee2de2 100644
--- a/libc/src/__support/str_to_integer.h
+++ b/libc/src/__support/str_to_integer.h
@@ -141,8 +141,8 @@ strtointeger(const CharType *__restrict src, int base,
constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>;
ResultType constexpr NEGATIVE_MAX =
- !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1
- : cpp::numeric_limits<T>::max();
+ static_cast<ResultType>(cpp::numeric_limits<T>::max()) +
+ (!IS_UNSIGNED ? 1 : 0);
ResultType const abs_max =
(is_positive ? cpp::numeric_limits<T>::max() : NEGATIVE_MAX);
ResultType const abs_max_div_by_base =
>From 68dadd3aeefe74e2567f49984523381b2076f636 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Tue, 20 Oct 2026 20:46:59 +0000
Subject: [PATCH 2/2] Fix build bots failures.
---
libc/src/__support/CPP/new.h | 5 +++--
libc/src/__support/macros/attributes.h | 6 ++++++
libc/src/__support/macros/properties/cpu_features.h | 8 ++++++++
libc/src/string/memory_utils/aarch64/inline_bcmp.h | 2 +-
libc/src/string/memory_utils/aarch64/inline_memcmp.h | 2 +-
libc/src/string/memory_utils/aarch64/inline_memset.h | 2 +-
libc/src/string/memory_utils/inline_bcmp.h | 4 ++--
libc/src/string/memory_utils/inline_bzero.h | 4 ++--
libc/src/string/memory_utils/inline_memcmp.h | 4 ++--
libc/src/string/memory_utils/inline_memcpy.h | 2 +-
libc/src/string/memory_utils/inline_memmove.h | 4 ++--
libc/src/string/memory_utils/inline_memset.h | 4 ++--
12 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/libc/src/__support/CPP/new.h b/libc/src/__support/CPP/new.h
index 8f9bf5344d8d7..44ec105b58870 100644
--- a/libc/src/__support/CPP/new.h
+++ b/libc/src/__support/CPP/new.h
@@ -30,9 +30,10 @@ namespace LIBC_NAMESPACE_DECL {
namespace cpp {
template <class T> [[nodiscard]] constexpr T *launder(T *p) {
- static_assert(__has_builtin(__builtin_launder) ||
- defined(LIBC_COMPILER_IS_MSVC),
+#ifndef LIBC_COMPILER_IS_MSVC
+ static_assert(__has_builtin(__builtin_launder),
"cpp::launder requires __builtin_launder");
+#endif // !LIBC_COMPILER_IS_MSVC
return __builtin_launder(p);
}
diff --git a/libc/src/__support/macros/attributes.h b/libc/src/__support/macros/attributes.h
index 8a5851e30ef15..2bf46c2a18225 100644
--- a/libc/src/__support/macros/attributes.h
+++ b/libc/src/__support/macros/attributes.h
@@ -51,6 +51,12 @@
#define LIBC_COLD
#endif // __has_attribute(cold)
+#if __has_attribute(flatten)
+#define LIBC_FLATTEN __attribute__((flatten))
+#else
+#define LIBC_FLATTEN
+#endif // __has_attribute(flatten)
+
#if __has_attribute(may_alias)
#define LIBC_MAY_ALIAS __attribute__((may_alias))
#else
diff --git a/libc/src/__support/macros/properties/cpu_features.h b/libc/src/__support/macros/properties/cpu_features.h
index 6071319008da1..f22a61ec70c95 100644
--- a/libc/src/__support/macros/properties/cpu_features.h
+++ b/libc/src/__support/macros/properties/cpu_features.h
@@ -46,8 +46,10 @@
#define LIBC_TARGET_CPU_HAS_SSE2
#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
+#if defined(__SSE2__)
#define LIBC_TARGET_CPU_GENERIC_VECTOR_SIZE_MAX 128
#endif
+#endif
#if defined(__SSE4_2__) || defined(__AVX__)
#define LIBC_TARGET_CPU_HAS_SSE4_2
@@ -55,9 +57,11 @@
#if defined(__AVX__)
#define LIBC_TARGET_CPU_HAS_AVX
+#ifndef LIBC_COMPILER_IS_MSVC
#undef LIBC_TARGET_CPU_GENERIC_VECTOR_SIZE_MAX
#define LIBC_TARGET_CPU_GENERIC_VECTOR_SIZE_MAX 256
#endif
+#endif
#if defined(__AVX2__)
#define LIBC_TARGET_CPU_HAS_AVX2
@@ -65,9 +69,11 @@
#if defined(__AVX512F__)
#define LIBC_TARGET_CPU_HAS_AVX512F
+#ifndef LIBC_COMPILER_IS_MSVC
#undef LIBC_TARGET_CPU_GENERIC_VECTOR_SIZE_MAX
#define LIBC_TARGET_CPU_GENERIC_VECTOR_SIZE_MAX 512
#endif
+#endif
#if defined(__AVX512BW__)
#define LIBC_TARGET_CPU_HAS_AVX512BW
@@ -99,8 +105,10 @@
#if defined(__ARM_NEON) || defined(_M_ARM64) || defined(_M_ARM64EC)
#define LIBC_TARGET_CPU_HAS_ARM_NEON
+#if defined(__ARM_NEON)
#define LIBC_TARGET_CPU_GENERIC_VECTOR_SIZE_MAX 512
#endif
+#endif
#if defined(__riscv_flen)
// https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc
diff --git a/libc/src/string/memory_utils/aarch64/inline_bcmp.h b/libc/src/string/memory_utils/aarch64/inline_bcmp.h
index 66d24378095b9..9c6821037ff1a 100644
--- a/libc/src/string/memory_utils/aarch64/inline_bcmp.h
+++ b/libc/src/string/memory_utils/aarch64/inline_bcmp.h
@@ -101,7 +101,7 @@ inline_bcmp_aarch64_with_fp(CPtr p1, CPtr p2, size_t count) {
}
#endif
-[[gnu::flatten]] LIBC_INLINE BcmpReturnType
+LIBC_FLATTEN LIBC_INLINE BcmpReturnType
inline_bcmp_aarch64_dispatch(CPtr p1, CPtr p2, size_t count) {
#if defined(__ARM_NEON)
return inline_bcmp_aarch64_with_fp(p1, p2, count);
diff --git a/libc/src/string/memory_utils/aarch64/inline_memcmp.h b/libc/src/string/memory_utils/aarch64/inline_memcmp.h
index 380ebb410efb5..c54cb457bbdaa 100644
--- a/libc/src/string/memory_utils/aarch64/inline_memcmp.h
+++ b/libc/src/string/memory_utils/aarch64/inline_memcmp.h
@@ -71,7 +71,7 @@ inline_memcmp_aarch64_with_fp(CPtr p1, CPtr p2, size_t count) {
}
#endif
-[[gnu::flatten]] LIBC_INLINE MemcmpReturnType
+LIBC_FLATTEN LIBC_INLINE MemcmpReturnType
inline_memcmp_aarch64_dispatch(CPtr p1, CPtr p2, size_t count) {
#if defined(__ARM_NEON)
return inline_memcmp_aarch64_with_fp(p1, p2, count);
diff --git a/libc/src/string/memory_utils/aarch64/inline_memset.h b/libc/src/string/memory_utils/aarch64/inline_memset.h
index 1b4b871792c69..d69c70842bd45 100644
--- a/libc/src/string/memory_utils/aarch64/inline_memset.h
+++ b/libc/src/string/memory_utils/aarch64/inline_memset.h
@@ -90,7 +90,7 @@ inline_memset_aarch64_with_fp(Ptr dst, uint8_t value, size_t count) {
}
#endif
-[[gnu::flatten]] [[maybe_unused]] LIBC_INLINE static void
+[[maybe_unused]] LIBC_FLATTEN LIBC_INLINE static void
inline_memset_aarch64_dispatch(Ptr dst, uint8_t value, size_t count) {
#if defined(__ARM_NEON)
return inline_memset_aarch64_with_fp(dst, value, count);
diff --git a/libc/src/string/memory_utils/inline_bcmp.h b/libc/src/string/memory_utils/inline_bcmp.h
index d6d3c9c1a3ad8..b241e999a6aae 100644
--- a/libc/src/string/memory_utils/inline_bcmp.h
+++ b/libc/src/string/memory_utils/inline_bcmp.h
@@ -35,8 +35,8 @@
namespace LIBC_NAMESPACE_DECL {
-[[gnu::flatten]] LIBC_INLINE int inline_bcmp(const void *p1, const void *p2,
- size_t count) {
+LIBC_FLATTEN LIBC_INLINE int inline_bcmp(const void *p1, const void *p2,
+ size_t count) {
return static_cast<int>(LIBC_SRC_STRING_MEMORY_UTILS_BCMP(
reinterpret_cast<CPtr>(p1), reinterpret_cast<CPtr>(p2), count));
}
diff --git a/libc/src/string/memory_utils/inline_bzero.h b/libc/src/string/memory_utils/inline_bzero.h
index a131b68725de7..4c19905f3fd52 100644
--- a/libc/src/string/memory_utils/inline_bzero.h
+++ b/libc/src/string/memory_utils/inline_bzero.h
@@ -18,11 +18,11 @@
namespace LIBC_NAMESPACE_DECL {
-[[gnu::flatten]] LIBC_INLINE static void inline_bzero(Ptr dst, size_t count) {
+LIBC_FLATTEN LIBC_INLINE static void inline_bzero(Ptr dst, size_t count) {
inline_memset(dst, 0, count);
}
-[[gnu::flatten]] LIBC_INLINE static void inline_bzero(void *dst, size_t count) {
+LIBC_FLATTEN LIBC_INLINE static void inline_bzero(void *dst, size_t count) {
inline_bzero(reinterpret_cast<Ptr>(dst), count);
}
diff --git a/libc/src/string/memory_utils/inline_memcmp.h b/libc/src/string/memory_utils/inline_memcmp.h
index a98f7ac51648e..7cfae049a822d 100644
--- a/libc/src/string/memory_utils/inline_memcmp.h
+++ b/libc/src/string/memory_utils/inline_memcmp.h
@@ -34,8 +34,8 @@
namespace LIBC_NAMESPACE_DECL {
-[[gnu::flatten]] LIBC_INLINE int inline_memcmp(const void *p1, const void *p2,
- size_t count) {
+LIBC_FLATTEN LIBC_INLINE int inline_memcmp(const void *p1, const void *p2,
+ size_t count) {
return static_cast<int>(LIBC_SRC_STRING_MEMORY_UTILS_MEMCMP(
reinterpret_cast<CPtr>(p1), reinterpret_cast<CPtr>(p2), count));
}
diff --git a/libc/src/string/memory_utils/inline_memcpy.h b/libc/src/string/memory_utils/inline_memcpy.h
index 6924339927a35..6f44da96afd79 100644
--- a/libc/src/string/memory_utils/inline_memcpy.h
+++ b/libc/src/string/memory_utils/inline_memcpy.h
@@ -44,7 +44,7 @@
namespace LIBC_NAMESPACE_DECL {
-[[gnu::flatten]] LIBC_INLINE void
+LIBC_FLATTEN LIBC_INLINE void
inline_memcpy(void *__restrict dst, const void *__restrict src, size_t count) {
LIBC_SRC_STRING_MEMORY_UTILS_MEMCPY(reinterpret_cast<Ptr>(dst),
reinterpret_cast<CPtr>(src), count);
diff --git a/libc/src/string/memory_utils/inline_memmove.h b/libc/src/string/memory_utils/inline_memmove.h
index c75100b48cc95..d63ec77548402 100644
--- a/libc/src/string/memory_utils/inline_memmove.h
+++ b/libc/src/string/memory_utils/inline_memmove.h
@@ -54,13 +54,13 @@ LIBC_INLINE constexpr bool inline_memmove_no_small_size(void *, const void *,
return false;
}
-[[gnu::flatten]] LIBC_INLINE bool
+LIBC_FLATTEN LIBC_INLINE bool
inline_memmove_small_size(void *dst, const void *src, size_t count) {
return LIBC_SRC_STRING_MEMORY_UTILS_MEMMOVE_SMALL_SIZE(
reinterpret_cast<Ptr>(dst), reinterpret_cast<CPtr>(src), count);
}
-[[gnu::flatten]] LIBC_INLINE void
+LIBC_FLATTEN LIBC_INLINE void
inline_memmove_follow_up(void *dst, const void *src, size_t count) {
LIBC_SRC_STRING_MEMORY_UTILS_MEMMOVE_FOLLOW_UP(
reinterpret_cast<Ptr>(dst), reinterpret_cast<CPtr>(src), count);
diff --git a/libc/src/string/memory_utils/inline_memset.h b/libc/src/string/memory_utils/inline_memset.h
index 1043077817fcc..0a6a7fd5e37c8 100644
--- a/libc/src/string/memory_utils/inline_memset.h
+++ b/libc/src/string/memory_utils/inline_memset.h
@@ -40,8 +40,8 @@
namespace LIBC_NAMESPACE_DECL {
-[[gnu::flatten]] LIBC_INLINE void inline_memset(void *dst, uint8_t value,
- size_t count) {
+LIBC_FLATTEN LIBC_INLINE void inline_memset(void *dst, uint8_t value,
+ size_t count) {
LIBC_SRC_STRING_MEMORY_UTILS_MEMSET(reinterpret_cast<Ptr>(dst), value, count);
}
More information about the libc-commits
mailing list