@@ -116,42 +116,65 @@ template <class _VecT, class _Iter>
116116 }(make_index_sequence<__simd_vector_size_v<_VecT>>{});
117117}
118118
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);
122122}
123123
124124template <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+ }
127129
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 >));
147144 } 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" );
149163 return 0 ;
150164 }
151165}
152166
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 {
155178 return std::__find_first_set (~__vec);
156179}
157180
0 commit comments