Skip to content

Conversation

jhuber6
Copy link
Contributor

@jhuber6 jhuber6 commented Sep 8, 2025

Summary:
It's important that these functions all be local to a TU as to not incur
ABI restrictions. Otherwise, we end up with lots of warnings if we
change or use different vector sizes.

@llvmbot
Copy link
Member

llvmbot commented Sep 8, 2025

@llvm/pr-subscribers-libc

Author: Joseph Huber (jhuber6)

Changes

Summary:
It's important that these functions all be local to a TU as to not incur
ABI restrictions. Otherwise, we end up with lots of warnings if we
change or use different vector sizes.


Full diff: https://github.com/llvm/llvm-project/pull/157551.diff

1 Files Affected:

  • (modified) libc/src/__support/CPP/simd.h (+46-40)
diff --git a/libc/src/__support/CPP/simd.h b/libc/src/__support/CPP/simd.h
index 449455c5c0390..1ec874c0d1d4f 100644
--- a/libc/src/__support/CPP/simd.h
+++ b/libc/src/__support/CPP/simd.h
@@ -37,15 +37,15 @@ using get_as_integer_type_t = unsigned _BitInt(sizeof(T) * CHAR_BIT);
 
 #if defined(LIBC_TARGET_CPU_HAS_AVX512F)
 template <typename T>
-inline constexpr size_t native_vector_size = 64 / sizeof(T);
+LIBC_INLINE constexpr size_t native_vector_size = 64 / sizeof(T);
 #elif defined(LIBC_TARGET_CPU_HAS_AVX2)
 template <typename T>
-inline constexpr size_t native_vector_size = 32 / sizeof(T);
+LIBC_INLINE constexpr size_t native_vector_size = 32 / sizeof(T);
 #elif defined(LIBC_TARGET_CPU_HAS_SSE2) || defined(LIBC_TARGET_CPU_HAS_ARM_NEON)
 template <typename T>
-inline constexpr size_t native_vector_size = 16 / sizeof(T);
+LIBC_INLINE constexpr size_t native_vector_size = 16 / sizeof(T);
 #else
-template <typename T> inline constexpr size_t native_vector_size = 1;
+template <typename T> LIBC_INLINE constexpr size_t native_vector_size = 1;
 #endif
 
 template <typename T> LIBC_INLINE constexpr T poison() {
@@ -90,122 +90,127 @@ using enable_if_simd_t = cpp::enable_if_t<is_simd_v<T>, T>;
 
 // Casting.
 template <typename To, typename From, size_t N>
-LIBC_INLINE constexpr simd<To, N> simd_cast(simd<From, N> v) {
+LIBC_INLINE constexpr static simd<To, N> simd_cast(simd<From, N> v) {
   return __builtin_convertvector(v, simd<To, N>);
 }
 
 // SIMD mask operations.
-template <size_t N> LIBC_INLINE constexpr bool all_of(simd<bool, N> m) {
+template <size_t N> LIBC_INLINE constexpr static bool all_of(simd<bool, N> m) {
   return __builtin_reduce_and(m);
 }
-template <size_t N> LIBC_INLINE constexpr bool any_of(simd<bool, N> m) {
+template <size_t N> LIBC_INLINE constexpr static bool any_of(simd<bool, N> m) {
   return __builtin_reduce_or(m);
 }
-template <size_t N> LIBC_INLINE constexpr bool none_of(simd<bool, N> m) {
+template <size_t N> LIBC_INLINE constexpr static bool none_of(simd<bool, N> m) {
   return !any_of(m);
 }
-template <size_t N> LIBC_INLINE constexpr bool some_of(simd<bool, N> m) {
+template <size_t N> LIBC_INLINE constexpr static bool some_of(simd<bool, N> m) {
   return any_of(m) && !all_of(m);
 }
-template <size_t N> LIBC_INLINE constexpr int popcount(simd<bool, N> m) {
+template <size_t N> LIBC_INLINE constexpr static int popcount(simd<bool, N> m) {
   return __builtin_popcountg(m);
 }
-template <size_t N> LIBC_INLINE constexpr int find_first_set(simd<bool, N> m) {
+template <size_t N>
+LIBC_INLINE constexpr static int find_first_set(simd<bool, N> m) {
   return __builtin_ctzg(m);
 }
-template <size_t N> LIBC_INLINE constexpr int find_last_set(simd<bool, N> m) {
+template <size_t N>
+LIBC_INLINE constexpr static int find_last_set(simd<bool, N> m) {
   constexpr size_t size = simd_size_v<simd<bool, N>>;
   return size - __builtin_clzg(m);
 }
 
 // Elementwise operations.
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> min(simd<T, N> x, simd<T, N> y) {
+LIBC_INLINE constexpr static simd<T, N> min(simd<T, N> x, simd<T, N> y) {
   return __builtin_elementwise_min(x, y);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> max(simd<T, N> x, simd<T, N> y) {
+LIBC_INLINE constexpr static simd<T, N> max(simd<T, N> x, simd<T, N> y) {
   return __builtin_elementwise_max(x, y);
 }
 
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> abs(simd<T, N> x) {
+LIBC_INLINE constexpr static simd<T, N> abs(simd<T, N> x) {
   return __builtin_elementwise_abs(x);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> fma(simd<T, N> x, simd<T, N> y, simd<T, N> z) {
+LIBC_INLINE constexpr static simd<T, N> fma(simd<T, N> x, simd<T, N> y,
+                                            simd<T, N> z) {
   return __builtin_elementwise_fma(x, y, z);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> ceil(simd<T, N> x) {
+LIBC_INLINE constexpr static simd<T, N> ceil(simd<T, N> x) {
   return __builtin_elementwise_ceil(x);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> floor(simd<T, N> x) {
+LIBC_INLINE constexpr static simd<T, N> floor(simd<T, N> x) {
   return __builtin_elementwise_floor(x);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> roundeven(simd<T, N> x) {
+LIBC_INLINE constexpr static simd<T, N> roundeven(simd<T, N> x) {
   return __builtin_elementwise_roundeven(x);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> round(simd<T, N> x) {
+LIBC_INLINE constexpr static simd<T, N> round(simd<T, N> x) {
   return __builtin_elementwise_round(x);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> trunc(simd<T, N> x) {
+LIBC_INLINE constexpr static simd<T, N> trunc(simd<T, N> x) {
   return __builtin_elementwise_trunc(x);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> nearbyint(simd<T, N> x) {
+LIBC_INLINE constexpr static simd<T, N> nearbyint(simd<T, N> x) {
   return __builtin_elementwise_nearbyint(x);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> rint(simd<T, N> x) {
+LIBC_INLINE constexpr static simd<T, N> rint(simd<T, N> x) {
   return __builtin_elementwise_rint(x);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> canonicalize(simd<T, N> x) {
+LIBC_INLINE constexpr static simd<T, N> canonicalize(simd<T, N> x) {
   return __builtin_elementwise_canonicalize(x);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> copysign(simd<T, N> x, simd<T, N> y) {
+LIBC_INLINE constexpr static simd<T, N> copysign(simd<T, N> x, simd<T, N> y) {
   return __builtin_elementwise_copysign(x, y);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> fmod(simd<T, N> x, simd<T, N> y) {
+LIBC_INLINE constexpr static simd<T, N> fmod(simd<T, N> x, simd<T, N> y) {
   return __builtin_elementwise_fmod(x, y);
 }
 
 // Reduction operations.
 template <typename T, size_t N, typename Op = cpp::plus<>>
-LIBC_INLINE constexpr T reduce(simd<T, N> v, Op op = {}) {
+LIBC_INLINE constexpr static T reduce(simd<T, N> v, Op op = {}) {
   return reduce(v, op);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr T reduce(simd<T, N> v, cpp::plus<>) {
+LIBC_INLINE constexpr static T reduce(simd<T, N> v, cpp::plus<>) {
   return __builtin_reduce_add(v);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr T reduce(simd<T, N> v, cpp::multiplies<>) {
+LIBC_INLINE constexpr static T reduce(simd<T, N> v, cpp::multiplies<>) {
   return __builtin_reduce_mul(v);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr T reduce(simd<T, N> v, cpp::bit_and<>) {
+LIBC_INLINE constexpr static T reduce(simd<T, N> v, cpp::bit_and<>) {
   return __builtin_reduce_and(v);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr T reduce(simd<T, N> v, cpp::bit_or<>) {
+LIBC_INLINE constexpr static T reduce(simd<T, N> v, cpp::bit_or<>) {
   return __builtin_reduce_or(v);
 }
 template <typename T, size_t N>
-LIBC_INLINE constexpr T reduce(simd<T, N> v, cpp::bit_xor<>) {
+LIBC_INLINE constexpr static T reduce(simd<T, N> v, cpp::bit_xor<>) {
   return __builtin_reduce_xor(v);
 }
-template <typename T, size_t N> LIBC_INLINE constexpr T hmin(simd<T, N> v) {
+template <typename T, size_t N>
+LIBC_INLINE constexpr static T hmin(simd<T, N> v) {
   return __builtin_reduce_min(v);
 }
-template <typename T, size_t N> LIBC_INLINE constexpr T hmax(simd<T, N> v) {
+template <typename T, size_t N>
+LIBC_INLINE constexpr static T hmax(simd<T, N> v) {
   return __builtin_reduce_max(v);
 }
 
@@ -242,28 +247,29 @@ LIBC_INLINE enable_if_simd_t<T> masked_store(simd<bool, simd_size_v<T>> m, T v,
 }
 
 // Construction helpers.
-template <typename T, size_t N> LIBC_INLINE constexpr simd<T, N> splat(T v) {
+template <typename T, size_t N>
+LIBC_INLINE constexpr static simd<T, N> splat(T v) {
   return simd<T, N>(v);
 }
-template <typename T> LIBC_INLINE constexpr simd<T> splat(T v) {
+template <typename T> LIBC_INLINE constexpr static simd<T> splat(T v) {
   return splat<T, simd_size_v<simd<T>>>(v);
 }
 template <typename T, unsigned N>
-LIBC_INLINE constexpr simd<T, N> iota(T base = T(0), T step = T(1)) {
+LIBC_INLINE constexpr static simd<T, N> iota(T base = T(0), T step = T(1)) {
   simd<T, N> v{};
   for (unsigned i = 0; i < N; ++i)
     v[i] = base + T(i) * step;
   return v;
 }
 template <typename T>
-LIBC_INLINE constexpr simd<T> iota(T base = T(0), T step = T(1)) {
+LIBC_INLINE constexpr static simd<T> iota(T base = T(0), T step = T(1)) {
   return iota<T, simd_size_v<simd<T>>>(base, step);
 }
 
 // Conditional helpers.
 template <typename T, size_t N>
-LIBC_INLINE constexpr simd<T, N> select(simd<bool, N> m, simd<T, N> x,
-                                        simd<T, N> y) {
+LIBC_INLINE constexpr static simd<T, N> select(simd<bool, N> m, simd<T, N> x,
+                                               simd<T, N> y) {
   return m ? x : y;
 }
 

Summary:
It's important that these functions all be local to a TU as to not incur
ABI restrictions. Otherwise, we end up with lots of warnings if we
change or use different vector sizes.
Copy link
Contributor

@michaelrj-google michaelrj-google left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jhuber6 jhuber6 merged commit bd0580c into llvm:main Sep 9, 2025
19 checks passed
@jhuber6 jhuber6 deleted the static branch September 10, 2025 00:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants