[PATCH] libstdc++: simd: x86: accept 64-bit long double as double [PR124657]
Jonathan Wakely
jwakely@redhat.com
Tue Apr 21 08:27:36 GMT 2026
On Tue, 21 Apr 2026 at 05:58, Alexandre Oliva <oliva@adacore.com> wrote:
>
> On Apr 9, 2026, Alexandre Oliva <oliva@adacore.com> wrote:
>
> > We probably need a better abstraction.
>
> Here's one:
>
> Various simd_x86 functions that handle double need to be adjusted to
> match 64-bit long double as well.
>
> Introduce __is_x86_ps<_Tp>() and __is_x86_pd<_Tp>() and use them
> instead of is_same_v<_Tp, float> and is_same_v<_Tp, double>,
> respectively.
>
> Regstrapped on x86_64-linux-gnu. Also tested pr109261_constexpr_simd.cc
> with -mlong-double-64. Ok to install? (presumably for stage1)
>
>
> for libstdc++-v3/ChangeLog
>
> PR libstdc++/124657
> * include/experimental/bits/simd_x86.h
> (__is_x86_ps<_Tp>): New. Replace is_same_v<_Tp, float> with it.
> (__is_x86_pd<_Tp>): New. Replace is_same_v<_Tp, double> with it.
> ---
> libstdc++-v3/include/experimental/bits/simd_x86.h | 79 ++++++++++++---------
> 1 file changed, 47 insertions(+), 32 deletions(-)
>
> diff --git a/libstdc++-v3/include/experimental/bits/simd_x86.h b/libstdc++-v3/include/experimental/bits/simd_x86.h
> index 74c7a61998e0d..73c10c1dcbbe7 100644
> --- a/libstdc++-v3/include/experimental/bits/simd_x86.h
> +++ b/libstdc++-v3/include/experimental/bits/simd_x86.h
> @@ -415,13 +415,28 @@ template <size_t _Np, typename _Tp, typename _Kp>
> #endif
>
> // ISA & type detection {{{
> +template <typename _Tp>
> + constexpr bool
> + __is_x86_ps()
> + {
> + return is_same_v<_Tp, float>;
> + }
> +
> +template <typename _Tp>
> + constexpr bool
> + __is_x86_pd()
> + {
> + return is_same_v<_Tp, double>
> + || (sizeof (long double) == sizeof (double) && is_same_v<_Tp, long double>);
This would be ever so slightly more efficient as:
if constexpr (is_same_v<_Tp, double>)
return true;
else
#if __LDBL_MANT_DIG__ == __DBL_MANT_DIG__
return is_same_v<_Tp, long double>;
#else
return false;
#endif
because it wouldn't instantiate the is_same_v variable templates
unless required, and wouldn't care about long double for the common
case of 80-bit long double.
But the patch seems reasonable to me. Matthias?
> + }
> +
> template <typename _Tp, size_t _Np>
> constexpr bool
> __is_sse_ps()
> {
> return __have_sse
> - && is_same_v<_Tp,
> - float> && sizeof(__intrinsic_type_t<_Tp, _Np>) == 16;
> + && __is_x86_ps<_Tp>()
> + && sizeof(__intrinsic_type_t<_Tp, _Np>) == 16;
> }
>
> template <typename _Tp, size_t _Np>
> @@ -429,8 +444,8 @@ template <typename _Tp, size_t _Np>
> __is_sse_pd()
> {
> return __have_sse2
> - && is_same_v<_Tp,
> - double> && sizeof(__intrinsic_type_t<_Tp, _Np>) == 16;
> + && __is_x86_pd<_Tp>()
> + && sizeof(__intrinsic_type_t<_Tp, _Np>) == 16;
> }
>
> template <typename _Tp, size_t _Np>
> @@ -438,8 +453,8 @@ template <typename _Tp, size_t _Np>
> __is_avx_ps()
> {
> return __have_avx
> - && is_same_v<_Tp,
> - float> && sizeof(__intrinsic_type_t<_Tp, _Np>) == 32;
> + && __is_x86_ps<_Tp>()
> + && sizeof(__intrinsic_type_t<_Tp, _Np>) == 32;
> }
>
> template <typename _Tp, size_t _Np>
> @@ -447,8 +462,8 @@ template <typename _Tp, size_t _Np>
> __is_avx_pd()
> {
> return __have_avx
> - && is_same_v<_Tp,
> - double> && sizeof(__intrinsic_type_t<_Tp, _Np>) == 32;
> + && __is_x86_pd<_Tp>()
> + && sizeof(__intrinsic_type_t<_Tp, _Np>) == 32;
> }
>
> template <typename _Tp, size_t _Np>
> @@ -456,8 +471,8 @@ template <typename _Tp, size_t _Np>
> __is_avx512_ps()
> {
> return __have_avx512f
> - && is_same_v<_Tp,
> - float> && sizeof(__intrinsic_type_t<_Tp, _Np>) == 64;
> + && __is_x86_ps<_Tp>()
> + && sizeof(__intrinsic_type_t<_Tp, _Np>) == 64;
> }
>
> template <typename _Tp, size_t _Np>
> @@ -465,8 +480,8 @@ template <typename _Tp, size_t _Np>
> __is_avx512_pd()
> {
> return __have_avx512f
> - && is_same_v<_Tp,
> - double> && sizeof(__intrinsic_type_t<_Tp, _Np>) == 64;
> + && __is_x86_pd<_Tp>()
> + && sizeof(__intrinsic_type_t<_Tp, _Np>) == 64;
> }
>
> // }}}
> @@ -2397,9 +2412,9 @@ template <typename _Abi, typename>
> [[maybe_unused]] const auto __yi = __to_intrin(__y);
> if constexpr (sizeof(__xi) == 64)
> {
> - if constexpr (is_same_v<_Tp, float>)
> + if constexpr (__is_x86_ps<_Tp> ())
> return _mm512_mask_cmp_ps_mask(__k1, __xi, __yi, _CMP_LT_OS);
> - else if constexpr (is_same_v<_Tp, double>)
> + else if constexpr (__is_x86_pd<_Tp> ())
> return _mm512_mask_cmp_pd_mask(__k1, __xi, __yi, _CMP_LT_OS);
> else if constexpr (is_signed_v<_Tp> && sizeof(_Tp) == 1)
> return _mm512_mask_cmplt_epi8_mask(__k1, __xi, __yi);
> @@ -2422,9 +2437,9 @@ template <typename _Abi, typename>
> }
> else if constexpr (sizeof(__xi) == 32)
> {
> - if constexpr (is_same_v<_Tp, float>)
> + if constexpr (__is_x86_ps<_Tp> ())
> return _mm256_mask_cmp_ps_mask(__k1, __xi, __yi, _CMP_LT_OS);
> - else if constexpr (is_same_v<_Tp, double>)
> + else if constexpr (__is_x86_pd<_Tp> ())
> return _mm256_mask_cmp_pd_mask(__k1, __xi, __yi, _CMP_LT_OS);
> else if constexpr (is_signed_v<_Tp> && sizeof(_Tp) == 1)
> return _mm256_mask_cmplt_epi8_mask(__k1, __xi, __yi);
> @@ -2447,9 +2462,9 @@ template <typename _Abi, typename>
> }
> else if constexpr (sizeof(__xi) == 16)
> {
> - if constexpr (is_same_v<_Tp, float>)
> + if constexpr (__is_x86_ps<_Tp> ())
> return _mm_mask_cmp_ps_mask(__k1, __xi, __yi, _CMP_LT_OS);
> - else if constexpr (is_same_v<_Tp, double>)
> + else if constexpr (__is_x86_pd<_Tp> ())
> return _mm_mask_cmp_pd_mask(__k1, __xi, __yi, _CMP_LT_OS);
> else if constexpr (is_signed_v<_Tp> && sizeof(_Tp) == 1)
> return _mm_mask_cmplt_epi8_mask(__k1, __xi, __yi);
> @@ -2505,9 +2520,9 @@ template <typename _Abi, typename>
> [[maybe_unused]] const auto __yi = __to_intrin(__y);
> if constexpr (sizeof(__xi) == 64)
> {
> - if constexpr (is_same_v<_Tp, float>)
> + if constexpr (__is_x86_ps<_Tp> ())
> return _mm512_mask_cmp_ps_mask(__k1, __xi, __yi, _CMP_LE_OS);
> - else if constexpr (is_same_v<_Tp, double>)
> + else if constexpr (__is_x86_pd<_Tp> ())
> return _mm512_mask_cmp_pd_mask(__k1, __xi, __yi, _CMP_LE_OS);
> else if constexpr (is_signed_v<_Tp> && sizeof(_Tp) == 1)
> return _mm512_mask_cmple_epi8_mask(__k1, __xi, __yi);
> @@ -2530,9 +2545,9 @@ template <typename _Abi, typename>
> }
> else if constexpr (sizeof(__xi) == 32)
> {
> - if constexpr (is_same_v<_Tp, float>)
> + if constexpr (__is_x86_ps<_Tp> ())
> return _mm256_mask_cmp_ps_mask(__k1, __xi, __yi, _CMP_LE_OS);
> - else if constexpr (is_same_v<_Tp, double>)
> + else if constexpr (__is_x86_pd<_Tp> ())
> return _mm256_mask_cmp_pd_mask(__k1, __xi, __yi, _CMP_LE_OS);
> else if constexpr (is_signed_v<_Tp> && sizeof(_Tp) == 1)
> return _mm256_mask_cmple_epi8_mask(__k1, __xi, __yi);
> @@ -2555,9 +2570,9 @@ template <typename _Abi, typename>
> }
> else if constexpr (sizeof(__xi) == 16)
> {
> - if constexpr (is_same_v<_Tp, float>)
> + if constexpr (__is_x86_ps<_Tp> ())
> return _mm_mask_cmp_ps_mask(__k1, __xi, __yi, _CMP_LE_OS);
> - else if constexpr (is_same_v<_Tp, double>)
> + else if constexpr (__is_x86_pd<_Tp> ())
> return _mm_mask_cmp_pd_mask(__k1, __xi, __yi, _CMP_LE_OS);
> else if constexpr (is_signed_v<_Tp> && sizeof(_Tp) == 1)
> return _mm_mask_cmple_epi8_mask(__k1, __xi, __yi);
> @@ -5021,10 +5036,10 @@ template <typename _Abi, typename>
> = _Abi::template _S_implicit_mask_intrin<_Tp>();
> return 0 != __testc(__a, __b);
> }
> - else if constexpr (is_same_v<_Tp, float>)
> + else if constexpr (__is_x86_ps<_Tp> ())
> return (_mm_movemask_ps(__a) & ((1 << _Np) - 1))
> == (1 << _Np) - 1;
> - else if constexpr (is_same_v<_Tp, double>)
> + else if constexpr (__is_x86_pd<_Tp> ())
> return (_mm_movemask_pd(__a) & ((1 << _Np) - 1))
> == (1 << _Np) - 1;
> else
> @@ -5084,9 +5099,9 @@ template <typename _Abi, typename>
> else
> return 0 == __testz(__a, __a);
> }
> - else if constexpr (is_same_v<_Tp, float>)
> + else if constexpr (__is_x86_ps<_Tp> ())
> return (_mm_movemask_ps(__a) & ((1 << _Np) - 1)) != 0;
> - else if constexpr (is_same_v<_Tp, double>)
> + else if constexpr (__is_x86_pd<_Tp> ())
> return (_mm_movemask_pd(__a) & ((1 << _Np) - 1)) != 0;
> else
> return (_mm_movemask_epi8(__a) & ((1 << (_Np * sizeof(_Tp))) - 1))
> @@ -5120,9 +5135,9 @@ template <typename _Abi, typename>
> else
> return 0 != __testz(__a, __a);
> }
> - else if constexpr (is_same_v<_Tp, float>)
> + else if constexpr (__is_x86_ps<_Tp> ())
> return (__movemask(__a) & ((1 << _Np) - 1)) == 0;
> - else if constexpr (is_same_v<_Tp, double>)
> + else if constexpr (__is_x86_pd<_Tp> ())
> return (__movemask(__a) & ((1 << _Np) - 1)) == 0;
> else
> return (__movemask(__a) & int((1ull << (_Np * sizeof(_Tp))) - 1))
> @@ -5150,13 +5165,13 @@ template <typename _Abi, typename>
> = _Abi::template _S_implicit_mask_intrin<_Tp>();
> return 0 != __testnzc(__a, __b);
> }
> - else if constexpr (is_same_v<_Tp, float>)
> + else if constexpr (__is_x86_ps<_Tp> ())
> {
> constexpr int __allbits = (1 << _Np) - 1;
> const auto __tmp = _mm_movemask_ps(__a) & __allbits;
> return __tmp > 0 && __tmp < __allbits;
> }
> - else if constexpr (is_same_v<_Tp, double>)
> + else if constexpr (__is_x86_pd<_Tp> ())
> {
> constexpr int __allbits = (1 << _Np) - 1;
> const auto __tmp = _mm_movemask_pd(__a) & __allbits;
More information about the Libstdc++
mailing list