Message ID | 3553838.ebMzRN9Arp@excalibur |
---|---|
State | New |
Headers | show |
Series | stdx::simd optimizations, corrections, and cleanups | expand |
While testing newer patches I found several missing conversions from __bit_cast to simd_bit_cast in this patch (i.e. where bit casting to / from fixed_size was sometimes required). Corrected patch attached. From: Matthias Kretz <kretz@kde.org> The __bit_cast function was a hack to achieve what __builtin_bit_cast can do, therefore use __builtin_bit_cast if possible. However, __builtin_bit_cast cannot be used to cast from/to fixed_size_simd, since it isn't trivially copyable (in the language sense — in principle it is). Therefore add __proposed::simd_bit_cast to enable the use case required in the test framework. Signed-off-by: Matthias Kretz <m.kretz@gsi.de> libstdc++-v3/ChangeLog: * include/experimental/bits/simd.h (__bit_cast): Implement via __builtin_bit_cast #if available. (__proposed::simd_bit_cast): Add overloads for simd and simd_mask, which use __builtin_bit_cast (or __bit_cast #if not available), which return an object of the requested type with the same bits as the argument. * include/experimental/bits/simd_math.h: Use simd_bit_cast instead of __bit_cast to allow casts to fixed_size_simd. (copysign): Remove branch that was only required if __bit_cast cannot be constexpr. * testsuite/experimental/simd/tests/bits/test_values.h: Switch from __bit_cast to __proposed::simd_bit_cast since the former will not cast fixed_size objects anymore. --- libstdc++-v3/include/experimental/bits/simd.h | 57 ++++++++++++++++++- .../include/experimental/bits/simd_math.h | 36 +++++------- .../simd/tests/bits/test_values.h | 8 +-- 3 files changed, 75 insertions(+), 26 deletions(-) -- ────────────────────────────────────────────────────────────────────────── Dr. Matthias Kretz https://mattkretz.github.io GSI Helmholtz Centre for Heavy Ion Research https://gsi.de std::experimental::simd https://github.com/VcDevel/std-simd ──────────────────────────────────────────────────────────────────────────
For -ffast-math there was a missing using namespace __proposed left. The attached patch resolves the issue. From: Matthias Kretz <m.kretz@gsi.de> The __bit_cast function was a hack to achieve what __builtin_bit_cast can do, therefore use __builtin_bit_cast if possible. However, __builtin_bit_cast cannot be used to cast from/to fixed_size_simd, since it isn't trivially copyable (in the language sense — in principle it is). Therefore add __proposed::simd_bit_cast to enable the use case required in the test framework. Signed-off-by: Matthias Kretz <m.kretz@gsi.de> libstdc++-v3/ChangeLog: * include/experimental/bits/simd.h (__bit_cast): Implement via __builtin_bit_cast #if available. (__proposed::simd_bit_cast): Add overloads for simd and simd_mask, which use __builtin_bit_cast (or __bit_cast #if not available), which return an object of the requested type with the same bits as the argument. * include/experimental/bits/simd_math.h: Use simd_bit_cast instead of __bit_cast to allow casts to fixed_size_simd. (copysign): Remove branch that was only required if __bit_cast cannot be constexpr. * testsuite/experimental/simd/tests/bits/test_values.h: Switch from __bit_cast to __proposed::simd_bit_cast since the former will not cast fixed_size objects anymore. --- libstdc++-v3/include/experimental/bits/simd.h | 57 ++++++++++++++++++- .../include/experimental/bits/simd_math.h | 37 ++++++------ .../simd/tests/bits/test_values.h | 8 +-- 3 files changed, 76 insertions(+), 26 deletions(-)
On Thu, Jun 24, 2021 at 04:01:34PM +0200, Matthias Kretz wrote: > --- a/libstdc++-v3/include/experimental/bits/simd.h > +++ b/libstdc++-v3/include/experimental/bits/simd.h > @@ -1598,7 +1598,9 @@ template <typename _To, typename _From> > _GLIBCXX_SIMD_INTRINSIC constexpr _To > __bit_cast(const _From __x) > { > - // TODO: implement with / replace by __builtin_bit_cast ASAP > +#if __has_builtin(__builtin_bit_cast) Shouldn't that use #if _GLIBCXX_HAS_BUILTIN(__builtin_bit_cast) in c++config to define a new macro and use that macro here? Though it is true that c++config already uses #if __has_builtin(__builtin_is_constant_evaluated) and so would fail miserably for compilers that don't support __has_builtin Jakub
On Thu, 24 Jun 2021 at 15:08, Jakub Jelinek wrote: > > On Thu, Jun 24, 2021 at 04:01:34PM +0200, Matthias Kretz wrote: > > --- a/libstdc++-v3/include/experimental/bits/simd.h > > +++ b/libstdc++-v3/include/experimental/bits/simd.h > > @@ -1598,7 +1598,9 @@ template <typename _To, typename _From> > > _GLIBCXX_SIMD_INTRINSIC constexpr _To > > __bit_cast(const _From __x) > > { > > - // TODO: implement with / replace by __builtin_bit_cast ASAP > > +#if __has_builtin(__builtin_bit_cast) > > Shouldn't that use #if _GLIBCXX_HAS_BUILTIN(__builtin_bit_cast) in > c++config to define a new macro and use that macro here? > Though it is true that c++config already uses > #if __has_builtin(__builtin_is_constant_evaluated) > and so would fail miserably for compilers that don't support __has_builtin GCC was the last of our supported compilers to implement __has_builtin, so for GCC trunk we can assume that it's always supported. The code in c++config.h still has some value for built-ins that aren't called __builtin_xxx because older versions of Clang need different handling for those. But for __builtin_bit_cast and __builtin_is_constant_evaluted we can just use __is_builtin directly.
On Thu, 24 Jun 2021 at 15:11, Jonathan Wakely wrote: > > On Thu, 24 Jun 2021 at 15:08, Jakub Jelinek wrote: > > > > On Thu, Jun 24, 2021 at 04:01:34PM +0200, Matthias Kretz wrote: > > > --- a/libstdc++-v3/include/experimental/bits/simd.h > > > +++ b/libstdc++-v3/include/experimental/bits/simd.h > > > @@ -1598,7 +1598,9 @@ template <typename _To, typename _From> > > > _GLIBCXX_SIMD_INTRINSIC constexpr _To > > > __bit_cast(const _From __x) > > > { > > > - // TODO: implement with / replace by __builtin_bit_cast ASAP > > > +#if __has_builtin(__builtin_bit_cast) > > > > Shouldn't that use #if _GLIBCXX_HAS_BUILTIN(__builtin_bit_cast) in > > c++config to define a new macro and use that macro here? > > Though it is true that c++config already uses > > #if __has_builtin(__builtin_is_constant_evaluated) > > and so would fail miserably for compilers that don't support __has_builtin > > GCC was the last of our supported compilers to implement > __has_builtin, so for GCC trunk we can assume that it's always > supported. > > The code in c++config.h still has some value for built-ins that aren't > called __builtin_xxx because older versions of Clang need different > handling for those. But for __builtin_bit_cast and > __builtin_is_constant_evaluted we can just use __is_builtin directly. s/__is_builtin/__has_builtin/
On Thu, Jun 24, 2021 at 03:11:01PM +0100, Jonathan Wakely wrote: > On Thu, 24 Jun 2021 at 15:08, Jakub Jelinek wrote: > > > > On Thu, Jun 24, 2021 at 04:01:34PM +0200, Matthias Kretz wrote: > > > --- a/libstdc++-v3/include/experimental/bits/simd.h > > > +++ b/libstdc++-v3/include/experimental/bits/simd.h > > > @@ -1598,7 +1598,9 @@ template <typename _To, typename _From> > > > _GLIBCXX_SIMD_INTRINSIC constexpr _To > > > __bit_cast(const _From __x) > > > { > > > - // TODO: implement with / replace by __builtin_bit_cast ASAP > > > +#if __has_builtin(__builtin_bit_cast) > > > > Shouldn't that use #if _GLIBCXX_HAS_BUILTIN(__builtin_bit_cast) in > > c++config to define a new macro and use that macro here? > > Though it is true that c++config already uses > > #if __has_builtin(__builtin_is_constant_evaluated) > > and so would fail miserably for compilers that don't support __has_builtin > > GCC was the last of our supported compilers to implement > __has_builtin, so for GCC trunk we can assume that it's always > supported. We don't support mixing GCC and libstdc++ versions, so I'm not worried about GCC. At least according to godbolt, already clang 3.0 supports it which is 10 years old, so probably fine too, but ICC 19.0/19.1 still doesn't support it, only ICC 2021 does. And ICC 19.1 seems to be released in October 2020. So, wouldn't it be better not to #undef _GLIBCXX_HAS_BUILTIN, move its definition a little bit earlier and use it also for __builtin_is_constant_evaluated? Jakub
On Thu, 24 Jun 2021 at 15:21, Jakub Jelinek <jakub@redhat.com> wrote: > > On Thu, Jun 24, 2021 at 03:11:01PM +0100, Jonathan Wakely wrote: > > On Thu, 24 Jun 2021 at 15:08, Jakub Jelinek wrote: > > > > > > On Thu, Jun 24, 2021 at 04:01:34PM +0200, Matthias Kretz wrote: > > > > --- a/libstdc++-v3/include/experimental/bits/simd.h > > > > +++ b/libstdc++-v3/include/experimental/bits/simd.h > > > > @@ -1598,7 +1598,9 @@ template <typename _To, typename _From> > > > > _GLIBCXX_SIMD_INTRINSIC constexpr _To > > > > __bit_cast(const _From __x) > > > > { > > > > - // TODO: implement with / replace by __builtin_bit_cast ASAP > > > > +#if __has_builtin(__builtin_bit_cast) > > > > > > Shouldn't that use #if _GLIBCXX_HAS_BUILTIN(__builtin_bit_cast) in > > > c++config to define a new macro and use that macro here? > > > Though it is true that c++config already uses > > > #if __has_builtin(__builtin_is_constant_evaluated) > > > and so would fail miserably for compilers that don't support __has_builtin > > > > GCC was the last of our supported compilers to implement > > __has_builtin, so for GCC trunk we can assume that it's always > > supported. > > We don't support mixing GCC and libstdc++ versions, so I'm not worried > about GCC. At least according to godbolt, already clang 3.0 supports it > which is 10 years old, so probably fine too, but ICC 19.0/19.1 still doesn't > support it, only ICC 2021 does. And ICC 19.1 seems to be released in > October 2020. > > So, wouldn't it be better not to #undef _GLIBCXX_HAS_BUILTIN, move its > definition a little bit earlier and use it also for > __builtin_is_constant_evaluated? I discussed this with Judy Ward on the Intel compiler team. If you're using their compiler, you should be using the latest version. They also claim 100% compatibility with GCC, for versions they've been able to test. So if you are using libstdc++ headers from a GCC release that supports __has_builtin, then you need to use a release of the Intel compiler that supports __has_builtin. Otherwise, it's unsupported. So in GCC 12 C++ headers we support GCC 12, versions of Intel compatible with GCC 12, and the last few releases of Clang. All of those have __has_builtin. Rather than use the _GLIBCXX_HAS_BUILTIN macro more widely, I'd prefer to not use it where it isn't needed, as in the attached (untested) patch. diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 9911d4deb72..3c075966660 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -55,7 +55,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef __cpp_lib_is_constant_evaluated // Support P1032R1 in C++20 (but not P0980R1 yet). # define __cpp_lib_constexpr_string 201811L -#elif __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#elif __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) // Support P0426R1 changes to char_traits in C++17. # define __cpp_lib_constexpr_string 201611L #elif __cplusplus > 201703L diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 9314117aed8..3ec668b65cf 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -720,13 +720,11 @@ namespace std # define _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 1 #endif -#ifdef __has_builtin -# ifdef __is_identifier +#ifdef __is_identifier // Intel and older Clang require !__is_identifier for some built-ins: -# define _GLIBCXX_HAS_BUILTIN(B) __has_builtin(B) || ! __is_identifier(B) -# else -# define _GLIBCXX_HAS_BUILTIN(B) __has_builtin(B) -# endif +# define _GLIBCXX_HAS_BUILTIN(B) __has_builtin(B) || ! __is_identifier(B) +#else +# define _GLIBCXX_HAS_BUILTIN(B) __has_builtin(B) #endif #if _GLIBCXX_HAS_BUILTIN(__has_unique_object_representations) @@ -737,18 +735,10 @@ namespace std # define _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE 1 #endif -#if _GLIBCXX_HAS_BUILTIN(__builtin_is_constant_evaluated) -# define _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 1 -#endif - #if _GLIBCXX_HAS_BUILTIN(__is_same) # define _GLIBCXX_HAVE_BUILTIN_IS_SAME 1 #endif -#if _GLIBCXX_HAS_BUILTIN(__builtin_launder) -# define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1 -#endif - #undef _GLIBCXX_HAS_BUILTIN diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index 3da6e28a513..77ad7be5dfb 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -238,7 +238,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef __cpp_lib_is_constant_evaluated // Unofficial macro indicating P1032R1 support in C++20 # define __cpp_lib_constexpr_char_traits 201811L -#elif __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#elif __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) // Unofficial macro indicating P0426R1 support in C++17 # define __cpp_lib_constexpr_char_traits 201611L #endif @@ -295,7 +295,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__n == 0) return 0; -#if __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) { for (size_t __i = 0; __i < __n; ++__i) @@ -312,7 +312,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX17_CONSTEXPR size_t length(const char_type* __s) { -#if __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) return __gnu_cxx::char_traits<char_type>::length(__s); #endif @@ -324,7 +324,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__n == 0) return 0; -#if __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); #endif @@ -422,7 +422,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__n == 0) return 0; -#if __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); #endif @@ -432,7 +432,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX17_CONSTEXPR size_t length(const char_type* __s) { -#if __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) return __gnu_cxx::char_traits<char_type>::length(__s); #endif @@ -444,7 +444,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__n == 0) return 0; -#if __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); #endif @@ -539,7 +539,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__n == 0) return 0; -#if __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); #endif @@ -549,7 +549,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX17_CONSTEXPR size_t length(const char_type* __s) { -#if __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) return __gnu_cxx::char_traits<char_type>::length(__s); #endif @@ -564,7 +564,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__n == 0) return 0; -#if __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201703L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); #endif diff --git a/libstdc++-v3/include/bits/stl_function.h b/libstdc++-v3/include/bits/stl_function.h index 073018d522d..774a9829284 100644 --- a/libstdc++-v3/include/bits/stl_function.h +++ b/libstdc++-v3/include/bits/stl_function.h @@ -413,12 +413,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX14_CONSTEXPR bool operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW { -#if __cplusplus >= 201402L -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201402L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) -#else - if (__builtin_constant_p(__x > __y)) -#endif return __x > __y; #endif return (__UINTPTR_TYPE__)__x > (__UINTPTR_TYPE__)__y; @@ -432,12 +428,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX14_CONSTEXPR bool operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW { -#if __cplusplus >= 201402L -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201402L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) -#else - if (__builtin_constant_p(__x < __y)) -#endif return __x < __y; #endif return (__UINTPTR_TYPE__)__x < (__UINTPTR_TYPE__)__y; @@ -451,12 +443,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX14_CONSTEXPR bool operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW { -#if __cplusplus >= 201402L -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201402L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) -#else - if (__builtin_constant_p(__x >= __y)) -#endif return __x >= __y; #endif return (__UINTPTR_TYPE__)__x >= (__UINTPTR_TYPE__)__y; @@ -470,12 +458,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX14_CONSTEXPR bool operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW { -#if __cplusplus >= 201402L -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __cplusplus >= 201402L && __has_builtin(__builtin_is_constant_evaluated) if (__builtin_is_constant_evaluated()) -#else - if (__builtin_constant_p(__x <= __y)) -#endif return __x <= __y; #endif return (__UINTPTR_TYPE__)__x <= (__UINTPTR_TYPE__)__y; diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h index c0144ced979..c54311a22d1 100644 --- a/libstdc++-v3/include/debug/helper_functions.h +++ b/libstdc++-v3/include/debug/helper_functions.h @@ -125,7 +125,7 @@ namespace __gnu_debug __check_singular(_Iterator const& __x) { return -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __has_builtin(__builtin_is_constant_evaluated) __builtin_is_constant_evaluated() ? false : #endif __check_singular_aux(std::__addressof(__x)); @@ -138,7 +138,7 @@ namespace __gnu_debug __check_singular(_Tp* const& __ptr) { return -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __has_builtin(__builtin_is_constant_evaluated) __builtin_is_constant_evaluated() ? false : #endif __ptr == 0; diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit index c5aae8bab03..ee8e001fd44 100644 --- a/libstdc++-v3/include/std/bit +++ b/libstdc++-v3/include/std/bit @@ -265,7 +265,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // representable as a value of _Tp, and so the result is undefined. // Want that undefined behaviour to be detected in constant expressions, // by UBSan, and by debug assertions. -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __has_builtin(__builtin_is_constant_evaluated) if (!__builtin_is_constant_evaluated()) { __glibcxx_assert( __shift_exponent != __int_traits<_Tp>::__digits ); diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index d9068a06f08..95a60e406a8 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -3316,7 +3316,7 @@ template <typename _From, typename _To> inline constexpr bool is_scoped_enum_v = is_scoped_enum<_Tp>::value; #endif // C++23 -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#if __has_builtin(__builtin_is_constant_evaluated) #define __cpp_lib_is_constant_evaluated 201811L diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index 27bcd32cb60..3bb50d37a72 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -111,7 +111,7 @@ #endif #define __cpp_lib_is_invocable 201703 #define __cpp_lib_is_swappable 201603 -#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER +#if __has_builtin(__builtin_launder) # define __cpp_lib_launder 201606 #endif #define __cpp_lib_logical_traits 201510 @@ -130,7 +130,7 @@ #define __cpp_lib_chrono 201611 #define __cpp_lib_clamp 201603 #if __cplusplus == 201703L // N.B. updated value in C++20 -# if _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +# if __has_builtin(__builtin_is_constant_evaluated) # define __cpp_lib_constexpr_char_traits 201611L # define __cpp_lib_constexpr_string 201611L # endif @@ -188,7 +188,7 @@ #endif #define __cpp_lib_endian 201907L #define __cpp_lib_int_pow2 202002L -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +#ifdef __has_builtin(__builtin_is_constant_evaluated) # define __cpp_lib_is_constant_evaluated 201811L #endif #define __cpp_lib_is_nothrow_convertible 201806L diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new index 3349b13fd1b..8774b333b90 100644 --- a/libstdc++-v3/libsupc++/new +++ b/libstdc++-v3/libsupc++/new @@ -182,8 +182,7 @@ inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { } //@} } // extern "C++" -#if __cplusplus >= 201703L -#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER +#if __cplusplus >= 201703L && __has_builtin(__builtin_launder) namespace std { #define __cpp_lib_launder 201606 @@ -206,7 +205,6 @@ namespace std void launder(volatile void*) = delete; void launder(const volatile void*) = delete; } -#endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER #endif // C++17 #if __cplusplus > 201703L
On Thu, 24 Jun 2021 at 15:34, Jonathan Wakely wrote: > Rather than use the _GLIBCXX_HAS_BUILTIN macro more widely, I'd prefer > to not use it where it isn't needed, as in the attached (untested) > patch. My rationale for this is that I'd prefer to use standardized features like __has_include and __has_cpp_attribute where possible, instead of adding more and more configure macros. You don't need to look in c++config.h to see how the macro is defined if you just use a standard feature directly. __has_builtin obviously isn't standardized, but as long as it's available on all the compilers we care about (which it is) then the same rationale applies.
On Thu, Jun 24, 2021 at 03:40:09PM +0100, Jonathan Wakely wrote: > On Thu, 24 Jun 2021 at 15:34, Jonathan Wakely wrote: > > Rather than use the _GLIBCXX_HAS_BUILTIN macro more widely, I'd prefer > > to not use it where it isn't needed, as in the attached (untested) > > patch. > > My rationale for this is that I'd prefer to use standardized features > like __has_include and __has_cpp_attribute where possible, instead of > adding more and more configure macros. You don't need to look in > c++config.h to see how the macro is defined if you just use a standard > feature directly. > > __has_builtin obviously isn't standardized, but as long as it's > available on all the compilers we care about (which it is) then the > same rationale applies. Okay. Jakub
On Thu, 24 Jun 2021 at 15:02, Matthias Kretz wrote: > > For -ffast-math there was a missing using namespace __proposed left. The > attached patch resolves the issue. OK for trunk, please push (after adding yourself to the "Write After Approval" section of MAINTAINERS as per https://gcc.gnu.org/gitwrite.html as your first commit). Thanks! > From: Matthias Kretz <m.kretz@gsi.de> > > The __bit_cast function was a hack to achieve what __builtin_bit_cast > can do, therefore use __builtin_bit_cast if possible. However, > __builtin_bit_cast cannot be used to cast from/to fixed_size_simd, since > it isn't trivially copyable (in the language sense — in principle it > is). Therefore add __proposed::simd_bit_cast to enable the use case > required in the test framework. > > Signed-off-by: Matthias Kretz <m.kretz@gsi.de> > > libstdc++-v3/ChangeLog: > > * include/experimental/bits/simd.h (__bit_cast): Implement via > __builtin_bit_cast #if available. > (__proposed::simd_bit_cast): Add overloads for simd and > simd_mask, which use __builtin_bit_cast (or __bit_cast #if not > available), which return an object of the requested type with > the same bits as the argument. > * include/experimental/bits/simd_math.h: Use simd_bit_cast > instead of __bit_cast to allow casts to fixed_size_simd. > (copysign): Remove branch that was only required if __bit_cast > cannot be constexpr. > * testsuite/experimental/simd/tests/bits/test_values.h: Switch > from __bit_cast to __proposed::simd_bit_cast since the former > will not cast fixed_size objects anymore. > --- > libstdc++-v3/include/experimental/bits/simd.h | 57 ++++++++++++++++++- > .../include/experimental/bits/simd_math.h | 37 ++++++------ > .../simd/tests/bits/test_values.h | 8 +-- > 3 files changed, 76 insertions(+), 26 deletions(-) > > > -- > ────────────────────────────────────────────────────────────────────────── > Dr. Matthias Kretz https://mattkretz.github.io > GSI Helmholtz Centre for Heavy Ion Research https://gsi.de > std::experimental::simd https://github.com/VcDevel/std-simd > ──────────────────────────────────────────────────────────────────────────
diff --git a/libstdc++-v3/include/experimental/bits/simd.h b/libstdc++-v3/include/experimental/bits/simd.h index 163f1b574e2..5d243f22434 100644 --- a/libstdc++-v3/include/experimental/bits/simd.h +++ b/libstdc++-v3/include/experimental/bits/simd.h @@ -1598,7 +1598,9 @@ template <typename _To, typename _From> _GLIBCXX_SIMD_INTRINSIC constexpr _To __bit_cast(const _From __x) { - // TODO: implement with / replace by __builtin_bit_cast ASAP +#if __has_builtin(__builtin_bit_cast) + return __builtin_bit_cast(_To, __x); +#else static_assert(sizeof(_To) == sizeof(_From)); constexpr bool __to_is_vectorizable = is_arithmetic_v<_To> || is_enum_v<_To>; @@ -1629,6 +1631,7 @@ template <typename _To, typename _From> reinterpret_cast<const char*>(&__x), sizeof(_To)); return __r; } +#endif } // }}} @@ -2900,6 +2903,41 @@ template <typename _Tp, typename _Up, typename _Ap, return {__private_init, _RM::abi_type::_MaskImpl::template _S_convert< typename _RM::simd_type::value_type>(__x)}; } + +template <typename _To, typename _Up, typename _Abi> + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR + _To + simd_bit_cast(const simd<_Up, _Abi>& __x) + { + using _Tp = typename _To::value_type; + using _ToMember = typename _SimdTraits<_Tp, typename _To::abi_type>::_SimdMember; + using _From = simd<_Up, _Abi>; + using _FromMember = typename _SimdTraits<_Up, _Abi>::_SimdMember; + // with concepts, the following should be constraints + static_assert(sizeof(_To) == sizeof(_From)); + static_assert(is_trivially_copyable_v<_Tp> && is_trivially_copyable_v<_Up>); + static_assert(is_trivially_copyable_v<_ToMember> && is_trivially_copyable_v<_FromMember>); +#if __has_builtin(__builtin_bit_cast) + return {__private_init, __builtin_bit_cast(_ToMember, __data(__x))}; +#else + return {__private_init, __bit_cast<_ToMember>(__data(__x))}; +#endif + } + +template <typename _To, typename _Up, typename _Abi> + _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_SIMD_CONSTEXPR + _To + simd_bit_cast(const simd_mask<_Up, _Abi>& __x) + { + using _From = simd_mask<_Up, _Abi>; + static_assert(sizeof(_To) == sizeof(_From)); + static_assert(is_trivially_copyable_v<_To> && is_trivially_copyable_v<_From>); +#if __has_builtin(__builtin_bit_cast) + return __builtin_bit_cast(_To, __x); +#else + return __bit_cast<_To>(__x); +#endif + } } // namespace __proposed // simd_cast {{{2 diff --git a/libstdc++-v3/include/experimental/bits/simd_math.h b/libstdc++-v3/include/experimental/bits/simd_math.h index d954e761eee..3ade293fcbf 100644 --- a/libstdc++-v3/include/experimental/bits/simd_math.h +++ b/libstdc++-v3/include/experimental/bits/simd_math.h @@ -700,11 +700,9 @@ template <typename _Tp, typename _Abi> // (inf and NaN are excluded by -ffinite-math-only) const auto __iszero_inf_nan = __x == 0; #else - const auto __as_int - = __bit_cast<rebind_simd_t<__int_for_sizeof_t<_Tp>, _V>>(abs(__x)); - const auto __inf - = __bit_cast<rebind_simd_t<__int_for_sizeof_t<_Tp>, _V>>( - _V(__infinity_v<_Tp>)); + using _Ip = __int_for_sizeof_t<_Tp>; + const auto __as_int = simd_bit_cast<rebind_simd_t<_Ip, _V>>(abs(__x)); + const auto __inf = simd_bit_cast<rebind_simd_t<_Ip, _V>>(_V(__infinity_v<_Tp>)); const auto __iszero_inf_nan = static_simd_cast<typename _V::mask_type>( __as_int == 0 || __as_int >= __inf); #endif diff --git a/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h b/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h index b69bd0b704d..67aa870659b 100644 --- a/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h +++ b/libstdc++-v3/testsuite/experimental/simd/tests/bits/test_values.h @@ -221,11 +221,11 @@ template <class V> if constexpr (sizeof(T) <= sizeof(double)) { using I = rebind_simd_t<__int_for_sizeof_t<T>, V>; - const I abs_x = __bit_cast<I>(abs(x)); - const I min = __bit_cast<I>(V(std::__norm_min_v<T>)); - const I max = __bit_cast<I>(V(std::__finite_max_v<T>)); + const I abs_x = simd_bit_cast<I>(abs(x)); + const I min = simd_bit_cast<I>(V(std::__norm_min_v<T>)); + const I max = simd_bit_cast<I>(V(std::__finite_max_v<T>)); return static_simd_cast<typename V::mask_type>( - __bit_cast<I>(x) == 0 || (abs_x >= min && abs_x <= max)); + simd_bit_cast<I>(x) == 0 || (abs_x >= min && abs_x <= max)); } else {