@@ -116,42 +116,65 @@ template <class _VecT, class _Iter>
116
116
}(make_index_sequence<__simd_vector_size_v<_VecT>>{});
117
117
}
118
118
119
- template <class _Tp , size_t _Np>
120
- [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of (__simd_vector<_Tp , _Np> __vec) noexcept {
121
- return __builtin_reduce_and (__builtin_convertvector ( __vec, __simd_vector< bool , _Np>) );
119
+ template <size_t _Np>
120
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of (__simd_vector<bool , _Np> __vec) noexcept {
121
+ return __builtin_reduce_and (__vec);
122
122
}
123
123
124
124
template <class _Tp , size_t _Np>
125
- [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set (__simd_vector<_Tp, _Np> __vec) noexcept {
126
- using __mask_vec = __simd_vector<bool , _Np>;
125
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI auto __as_mask (__simd_vector<_Tp, _Np> __vec) noexcept {
126
+ static_assert (!is_same<_Tp, bool >::value, " vector type should not be a bool!" );
127
+ return __builtin_convertvector (__vec, __simd_vector<bool , _Np>);
128
+ }
127
129
128
- // This has MSan disabled du to https://github.com/llvm/llvm-project/issues/85876
129
- auto __impl = [&]<class _MaskT >(_MaskT) _LIBCPP_NO_SANITIZE (" memory" ) noexcept {
130
- # if defined(_LIBCPP_BIG_ENDIAN)
131
- return std::min<size_t >(
132
- _Np, std::__countl_zero (__builtin_bit_cast (_MaskT, __builtin_convertvector (__vec, __mask_vec))));
133
- # else
134
- return std::min<size_t >(
135
- _Np, std::__countr_zero (__builtin_bit_cast (_MaskT, __builtin_convertvector (__vec, __mask_vec))));
136
- # endif
137
- };
138
-
139
- if constexpr (sizeof (__mask_vec) == sizeof (uint8_t )) {
140
- return __impl (uint8_t {});
141
- } else if constexpr (sizeof (__mask_vec) == sizeof (uint16_t )) {
142
- return __impl (uint16_t {});
143
- } else if constexpr (sizeof (__mask_vec) == sizeof (uint32_t )) {
144
- return __impl (uint32_t {});
145
- } else if constexpr (sizeof (__mask_vec) == sizeof (uint64_t )) {
146
- return __impl (uint64_t {});
130
+ // This uses __builtin_convertvector around the __builtin_shufflevector to work around #107981.
131
+ template <size_t _Np>
132
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI __simd_vector<bool , 8 >
133
+ __extend_vector (__simd_vector<bool , _Np> __vec) noexcept {
134
+ using _VecT = __simd_vector<bool , _Np>;
135
+ if constexpr (_Np == 4 ) {
136
+ return __builtin_convertvector (
137
+ __builtin_shufflevector (__vec, _VecT{}, 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ), __simd_vector<bool , 8 >);
138
+ } else if constexpr (_Np == 2 ) {
139
+ return std::__extend_vector (
140
+ __builtin_convertvector (__builtin_shufflevector (__vec, _VecT{}, 0 , 1 , 2 , 3 ), __simd_vector<bool , 4 >));
141
+ } else if constexpr (_Np == 1 ) {
142
+ return std::__extend_vector (
143
+ __builtin_convertvector (__builtin_shufflevector (__vec, _VecT{}, 0 , 1 ), __simd_vector<bool , 2 >));
147
144
} else {
148
- static_assert (sizeof (__mask_vec) == 0 , " unexpected required size for mask integer type" );
145
+ static_assert (sizeof (_VecT) == 0 , " Unexpected vector size" );
146
+ }
147
+ }
148
+
149
+ template <size_t _Np>
150
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI auto __to_int_mask (__simd_vector<bool , _Np> __vec) {
151
+ if constexpr (_Np < 8 ) {
152
+ return std::__bit_cast<uint8_t >(std::__extend_vector (__vec));
153
+ } else if constexpr (_Np == 8 ) {
154
+ return std::__bit_cast<uint8_t >(__vec);
155
+ } else if constexpr (_Np == 16 ) {
156
+ return std::__bit_cast<uint16_t >(__vec);
157
+ } else if constexpr (_Np == 32 ) {
158
+ return std::__bit_cast<uint32_t >(__vec);
159
+ } else if constexpr (_Np == 64 ) {
160
+ return std::__bit_cast<uint64_t >(__vec);
161
+ } else {
162
+ static_assert (sizeof (__simd_vector<bool , _Np>) == 0 , " Unexpected vector size" );
149
163
return 0 ;
150
164
}
151
165
}
152
166
153
- template <class _Tp , size_t _Np>
154
- [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set (__simd_vector<_Tp, _Np> __vec) noexcept {
167
+ template <size_t _Np>
168
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set (__simd_vector<bool , _Np> __vec) noexcept {
169
+ # if defined(_LIBCPP_BIG_ENDIAN)
170
+ return std::min<size_t >(_Np, std::__countl_zero (std::__to_int_mask (__vec)));
171
+ # else
172
+ return std::min<size_t >(_Np, std::__countr_zero (std::__to_int_mask (__vec)));
173
+ # endif
174
+ }
175
+
176
+ template <size_t _Np>
177
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set (__simd_vector<bool , _Np> __vec) noexcept {
155
178
return std::__find_first_set (~__vec);
156
179
}
157
180
0 commit comments