@@ -57,6 +57,29 @@ using simd = T [[clang::ext_vector_type(N)]];
57
57
template <typename T>
58
58
using simd_mask = simd<bool , internal::native_vector_size<T>>;
59
59
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;
60
83
namespace internal {
61
84
62
85
template <typename T>
@@ -123,34 +146,14 @@ LIBC_INLINE constexpr static auto split(cpp::simd<T, N> x) {
123
146
return result;
124
147
}
125
148
126
- } // namespace internal
127
-
128
- // Type trait helpers.
149
+ // Helper trait
129
150
template <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>;
144
152
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
- };
149
153
template <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 > ;
151
155
152
- template <typename T>
153
- using enable_if_simd_t = cpp::enable_if_t <is_simd_v<T>, T>;
156
+ } // namespace internal
154
157
155
158
// Casting.
156
159
template <typename To, typename From, size_t N>
@@ -159,29 +162,34 @@ LIBC_INLINE constexpr static simd<To, N> simd_cast(simd<From, N> v) {
159
162
}
160
163
161
164
// 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));
164
168
}
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));
167
172
}
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);
170
176
}
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);
173
180
}
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);
176
184
}
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) );
180
188
}
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) );
185
193
}
186
194
187
195
// Elementwise operations.
@@ -279,33 +287,32 @@ LIBC_INLINE constexpr static T hmax(simd<T, N> v) {
279
287
}
280
288
281
289
// 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) {
284
292
T tmp;
285
293
__builtin_memcpy (&tmp, ptr, sizeof (T));
286
294
return tmp;
287
295
}
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) {
290
298
return load_unaligned<T>(__builtin_assume_aligned (ptr, alignof (T)));
291
299
}
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) {
294
302
__builtin_memcpy (ptr, &v, sizeof (T));
295
303
}
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) {
298
306
store_unaligned<T>(v, __builtin_assume_aligned (ptr, alignof (T)));
299
307
}
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
302
310
masked_load (simd<bool , simd_size_v<T>> m, void *ptr,
303
311
T passthru = internal::poison<simd_element_type<T>>()) {
304
312
return __builtin_masked_load (m, ptr, passthru);
305
313
}
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) {
309
316
__builtin_masked_store (
310
317
m, v, static_cast <T *>(__builtin_assume_aligned (ptr, alignof (T))));
311
318
}
0 commit comments