@@ -57,6 +57,29 @@ using simd = T [[clang::ext_vector_type(N)]];
5757template <typename T>
5858using simd_mask = simd<bool , internal::native_vector_size<T>>;
5959
60+ // Type trait helpers.
61+ template <typename T>
62+ struct simd_size : cpp::integral_constant<size_t , __builtin_vectorelements(T)> {
63+ };
64+ template <class T > constexpr size_t simd_size_v = simd_size<T>::value;
65+
66+ template <typename T> struct is_simd : cpp::integral_constant<bool , false > {};
67+ template <typename T, unsigned N>
68+ struct is_simd <simd<T, N>> : cpp::integral_constant<bool , true > {};
69+ template <class T > constexpr bool is_simd_v = is_simd<T>::value;
70+
71+ template <typename T>
72+ struct is_simd_mask : cpp::integral_constant<bool , false > {};
73+ template <unsigned N>
74+ struct is_simd_mask <simd<bool , N>> : cpp::integral_constant<bool , true > {};
75+ template <class T > constexpr bool is_simd_mask_v = is_simd_mask<T>::value;
76+
77+ template <typename T> struct simd_element_type ;
78+ template <typename T, size_t N> struct simd_element_type <simd<T, N>> {
79+ using type = T;
80+ };
81+ template <typename T>
82+ using simd_element_type_t = typename simd_element_type<T>::type;
6083namespace internal {
6184
6285template <typename T>
@@ -123,34 +146,14 @@ LIBC_INLINE constexpr static auto split(cpp::simd<T, N> x) {
123146 return result;
124147}
125148
126- } // namespace internal
127-
128- // Type trait helpers.
149+ // Helper trait
129150template <typename T>
130- struct simd_size : cpp::integral_constant<size_t , __builtin_vectorelements(T)> {
131- };
132- template <class T > constexpr size_t simd_size_v = simd_size<T>::value;
133-
134- template <typename T> struct is_simd : cpp::integral_constant<bool , false > {};
135- template <typename T, unsigned N>
136- struct is_simd <simd<T, N>> : cpp::integral_constant<bool , true > {};
137- template <class T > constexpr bool is_simd_v = is_simd<T>::value;
138-
139- template <typename T>
140- struct is_simd_mask : cpp::integral_constant<bool , false > {};
141- template <unsigned N>
142- struct is_simd_mask <simd<bool , N>> : cpp::integral_constant<bool , true > {};
143- template <class T > constexpr bool is_simd_mask_v = is_simd_mask<T>::value;
151+ using enable_if_integral_t = cpp::enable_if_t <cpp::is_integral_v<T>, T>;
144152
145- template <typename T> struct simd_element_type ;
146- template <typename T, size_t N> struct simd_element_type <simd<T, N>> {
147- using type = T;
148- };
149153template <typename T>
150- using simd_element_type_t = typename simd_element_type<T>::type ;
154+ using enable_if_simd_t = cpp:: enable_if_t <is_simd_v<T>, bool > ;
151155
152- template <typename T>
153- using enable_if_simd_t = cpp::enable_if_t <is_simd_v<T>, T>;
156+ } // namespace internal
154157
155158// Casting.
156159template <typename To, typename From, size_t N>
@@ -159,29 +162,34 @@ LIBC_INLINE constexpr static simd<To, N> simd_cast(simd<From, N> v) {
159162}
160163
161164// SIMD mask operations.
162- template <size_t N> LIBC_INLINE constexpr static bool all_of (simd<bool , N> m) {
163- return __builtin_reduce_and (m);
165+ template <typename T, size_t N, internal::enable_if_integral_t <T> = 0 >
166+ LIBC_INLINE constexpr static bool all_of (simd<T, N> v) {
167+ return __builtin_reduce_and (simd_cast<bool >(v));
164168}
165- template <size_t N> LIBC_INLINE constexpr static bool any_of (simd<bool , N> m) {
166- return __builtin_reduce_or (m);
169+ template <typename T, size_t N, internal::enable_if_integral_t <T> = 0 >
170+ LIBC_INLINE constexpr static bool any_of (simd<T, N> v) {
171+ return __builtin_reduce_or (simd_cast<bool >(v));
167172}
168- template <size_t N> LIBC_INLINE constexpr static bool none_of (simd<bool , N> m) {
169- return !any_of (m);
173+ template <typename T, size_t N, internal::enable_if_integral_t <T> = 0 >
174+ LIBC_INLINE constexpr static bool none_of (simd<T, N> v) {
175+ return !any_of (v);
170176}
171- template <size_t N> LIBC_INLINE constexpr static bool some_of (simd<bool , N> m) {
172- return any_of (m) && !all_of (m);
177+ template <typename T, size_t N, internal::enable_if_integral_t <T> = 0 >
178+ LIBC_INLINE constexpr static bool some_of (simd<T, N> v) {
179+ return any_of (v) && !all_of (v);
173180}
174- template <size_t N> LIBC_INLINE constexpr static int popcount (simd<bool , N> m) {
175- return __builtin_popcountg (m);
181+ template <typename T, size_t N, internal::enable_if_integral_t <T> = 0 >
182+ LIBC_INLINE constexpr static int popcount (simd<T, N> v) {
183+ return __builtin_popcountg (v);
176184}
177- template <size_t N>
178- LIBC_INLINE constexpr static int find_first_set (simd<bool , N> m ) {
179- return __builtin_ctzg (m );
185+ template <typename T, size_t N, internal:: enable_if_integral_t <T> = 0 >
186+ LIBC_INLINE constexpr static int find_first_set (simd<T , N> v ) {
187+ return __builtin_ctzg (simd_cast< bool >(v) );
180188}
181- template <size_t N>
182- LIBC_INLINE constexpr static int find_last_set (simd<bool , N> m ) {
183- constexpr size_t size = simd_size_v<simd<bool , N>>;
184- return size - 1 - __builtin_clzg (m );
189+ template <typename T, size_t N, internal:: enable_if_integral_t <T> = 0 >
190+ LIBC_INLINE constexpr static int find_last_set (simd<T , N> v ) {
191+ constexpr size_t size = simd_size_v<simd<T , N>>;
192+ return size - 1 - __builtin_clzg (simd_cast< bool >(v) );
185193}
186194
187195// Elementwise operations.
@@ -279,33 +287,32 @@ LIBC_INLINE constexpr static T hmax(simd<T, N> v) {
279287}
280288
281289// Accessor helpers.
282- template <typename T>
283- LIBC_INLINE enable_if_simd_t <T> load_unaligned (const void *ptr) {
290+ template <typename T, internal:: enable_if_simd_t <T> = 0 >
291+ LIBC_INLINE T load_unaligned (const void *ptr) {
284292 T tmp;
285293 __builtin_memcpy (&tmp, ptr, sizeof (T));
286294 return tmp;
287295}
288- template <typename T>
289- LIBC_INLINE enable_if_simd_t <T> load_aligned (const void *ptr) {
296+ template <typename T, internal:: enable_if_simd_t <T> = 0 >
297+ LIBC_INLINE T load_aligned (const void *ptr) {
290298 return load_unaligned<T>(__builtin_assume_aligned (ptr, alignof (T)));
291299}
292- template <typename T>
293- LIBC_INLINE enable_if_simd_t <T> store_unaligned (T v, void *ptr) {
300+ template <typename T, internal:: enable_if_simd_t <T> = 0 >
301+ LIBC_INLINE T store_unaligned (T v, void *ptr) {
294302 __builtin_memcpy (ptr, &v, sizeof (T));
295303}
296- template <typename T>
297- LIBC_INLINE enable_if_simd_t <T> store_aligned (T v, void *ptr) {
304+ template <typename T, internal:: enable_if_simd_t <T> = 0 >
305+ LIBC_INLINE T store_aligned (T v, void *ptr) {
298306 store_unaligned<T>(v, __builtin_assume_aligned (ptr, alignof (T)));
299307}
300- template <typename T>
301- LIBC_INLINE enable_if_simd_t <T>
308+ template <typename T, internal:: enable_if_simd_t <T> = 0 >
309+ LIBC_INLINE T
302310masked_load (simd<bool , simd_size_v<T>> m, void *ptr,
303311 T passthru = internal::poison<simd_element_type<T>>()) {
304312 return __builtin_masked_load (m, ptr, passthru);
305313}
306- template <typename T>
307- LIBC_INLINE enable_if_simd_t <T> masked_store (simd<bool , simd_size_v<T>> m, T v,
308- void *ptr) {
314+ template <typename T, internal::enable_if_simd_t <T> = 0 >
315+ LIBC_INLINE T masked_store (simd<bool , simd_size_v<T>> m, T v, void *ptr) {
309316 __builtin_masked_store (
310317 m, v, static_cast <T *>(__builtin_assume_aligned (ptr, alignof (T))));
311318}
0 commit comments