From 489b58b79782fa361c0d7e852e0e684d743c8399 Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Mon, 3 Jun 2024 12:02:07 +0200 Subject: libstdc++: Fix simd conversion for -fno-signed-char for Clang The special case for Clang in the trait producing a signed integer type lead to the trait returning 'char' where it should have been 'signed char'. This workaround was introduced because on Clang the return type of vector compares was not convertible to '_SimdWrapper< __int_for_sizeof_t<...' unless '__int_for_sizeof_t' was an alias for 'char'. In order to not rewrite the complete mask type code (there is code scattered around the implementation assuming signed integers), this needs to be 'signed char'; so the special case for Clang needs to be removed. The conversion issue is now solved in _SimdWrapper, which now additionally allows conversion from vector types with compatible integral type. Signed-off-by: Matthias Kretz libstdc++-v3/ChangeLog: PR libstdc++/115308 * include/experimental/bits/simd.h (__int_for_sizeof): Remove special cases for __clang__. (_SimdWrapper): Change constructor overload set to allow conversion from vector types with integral conversions via bit reinterpretation. (cherry picked from commit 8e36cf4c5c9140915d0019999db132a900b48037) --- libstdc++-v3/include/experimental/bits/simd.h | 45 ++++++++++++++++----------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/libstdc++-v3/include/experimental/bits/simd.h b/libstdc++-v3/include/experimental/bits/simd.h index 7c52462..cb1f13d 100644 --- a/libstdc++-v3/include/experimental/bits/simd.h +++ b/libstdc++-v3/include/experimental/bits/simd.h @@ -606,19 +606,12 @@ template static_assert(_Bytes > 0); if constexpr (_Bytes == sizeof(int)) return int(); - #ifdef __clang__ - else if constexpr (_Bytes == sizeof(char)) - return char(); - #else else if constexpr (_Bytes == sizeof(_SChar)) return _SChar(); - #endif else if constexpr (_Bytes == sizeof(short)) return short(); - #ifndef __clang__ else if constexpr (_Bytes == sizeof(long)) return long(); - #endif else if constexpr (_Bytes == sizeof(_LLong)) return _LLong(); #ifdef __SIZEOF_INT128__ @@ -2747,6 +2740,8 @@ template // }}} // _SimdWrapper{{{ +struct _DisabledSimdWrapper; + template struct _SimdWrapper< _Tp, _Width, @@ -2756,16 +2751,17 @@ template == sizeof(__vector_type_t<_Tp, _Width>), __vector_type_t<_Tp, _Width>> { - using _Base - = _SimdWrapperBase<__has_iec559_behavior<__signaling_NaN, _Tp>::value - && sizeof(_Tp) * _Width - == sizeof(__vector_type_t<_Tp, _Width>), - __vector_type_t<_Tp, _Width>>; + static constexpr bool _S_need_default_init + = __has_iec559_behavior<__signaling_NaN, _Tp>::value + and sizeof(_Tp) * _Width == sizeof(__vector_type_t<_Tp, _Width>); + + using _BuiltinType = __vector_type_t<_Tp, _Width>; + + using _Base = _SimdWrapperBase<_S_need_default_init, _BuiltinType>; static_assert(__is_vectorizable_v<_Tp>); static_assert(_Width >= 2); // 1 doesn't make sense, use _Tp directly then - using _BuiltinType = __vector_type_t<_Tp, _Width>; using value_type = _Tp; static inline constexpr size_t _S_full_size @@ -2801,13 +2797,26 @@ template _GLIBCXX_SIMD_INTRINSIC constexpr _SimdWrapper& operator=(_SimdWrapper&&) = default; - template >, - is_same<_V, __intrinsic_type_t<_Tp, _Width>>>>> + // Convert from exactly matching __vector_type_t + using _SimdWrapperBase<_S_need_default_init, _BuiltinType>::_SimdWrapperBase; + + // Convert from __intrinsic_type_t if __intrinsic_type_t and __vector_type_t differ, otherwise + // this ctor should not exist. Making the argument type unusable is our next best solution. + _GLIBCXX_SIMD_INTRINSIC constexpr + _SimdWrapper(conditional_t>, + _DisabledSimdWrapper, __intrinsic_type_t<_Tp, _Width>> __x) + : _Base(__vector_bitcast<_Tp, _Width>(__x)) {} + + // Convert from different __vector_type_t, but only if bit reinterpretation is a correct + // conversion of the value_type + template , + typename = enable_if_t + and is_integral_v>> _GLIBCXX_SIMD_INTRINSIC constexpr _SimdWrapper(_V __x) - // __vector_bitcast can convert e.g. __m128 to __vector(2) float - : _Base(__vector_bitcast<_Tp, _Width>(__x)) {} + : _Base(reinterpret_cast<_BuiltinType>(__x)) {} template && ...) -- cgit v1.1