Skip to content

Commit 31699d5

Browse files
committed
Refactor ABI tag deduction and rebinding
ChangeLog: * constexpr_tests.cpp: Adjust and test for more expected ABI tags. * generic-traits_tests.cpp: Add tests for __float_from, __abi_tag, __native_abi, _Abi::_S_resize, and __abi_rebind. * include/bits/simd_complex.h (__to_cx_ileav): Deduce new ABI tag from __abi_rebind. Handle size 1 / bool case. (basic_mask): Constrain to size >= 2. (basic_mask::_DataType): Use __component_mask_for_ileav / __component_mask_for_ctgus. (basic_mask::_M_get_ileav_data): New. (basic_mask::_M_chunk): Simplify and fix chunking to array of size 1 masks. (basic_mask::_S_concat): Use _M_get_ileav_data instead of _M_data. (basic_vec): Constrain to size >= 2. (basic_vec::_M_get_ileav_data): Renamed from _M_get_ileav. (basic_vec::_M_chunk): Deduce intermediate chunk type from _TSimd. (basic_vec::_S_concat): Use _M_get_ileav_data instead of _M_data. (basic_mask::_S_unwrap_cx_ctgus): Remove in favor of _M_get_ctgus_data. (basic_mask::_M_get_ctgus_data): New. (basic_mask::_S_concat): Use _M_get_ctgus_data. (_CxCtgus basic_vec): Also take _CxIleav size 1 vecs. (basic_vec::_S_is_scalar): Determine from _RealSimd::_S_is_scalar. (basic_vec::_M_concat_data): Implement for size one. (basic_vec::_M_get_ileav_data, _S_init): New. * include/bits/simd_details.h (__float_from): New. (_ScalarAbi::_S_resize): Rename from _M_resize and declare static. (_Abi): Allow _S_size == _S_nreg. (_Abi::_DataType, _MaskDataType): Return scalar type / bool for size 1. Allow _Cx variants. (_Abi::_S_resize): Rename from _M_resize, declare static, and return _Abi<1, 1, ...> for size 1. (__abi_tag, __deduce_abi): Adjust for _S_resize change. (__abi_rebind): Make more use of _S_resize and stick with either _Abi or _ScalarAbi. (__component_mask_for_ileav, __component_mask_for_ctgus): New. (__similar_resized_vec): Remove. __similar_vec is sufficient now. * include/bits/simd_mask.h (resize): Constrain to _Np >= 1. Simplify constraint to basic_vec. (__extract_simd_at): Extend condition from __scalar_abi_tag to size 1. (basic_mask): Adjust constraint to also cover size 1 _Cx masks. (basic_mask;:_S_has_bool_member, _S_is_scalar): Derive from the type of _DataType. (basic_mask::_M_get_ileav_data, _M_get_ctgus_data): New. (basic_mask::_Abi0, _Abi1): Use _S_resize with pre-determined size and number of registers to find the member ABI tags. (basic_mask::basic_mask(basic_mask)): Handle, simplfy, and fix conversion to size 1 members. * include/bits/simd_vec.h (basic_vec): Generalize _S_is_scalar to any size 1 and ensure _S_use_bitmask is not true for a simple bool mask. * include/bits/simd_x86.h: Move __float_from to simd_details.h.
1 parent 2bebaa1 commit 31699d5

7 files changed

Lines changed: 279 additions & 139 deletions

File tree

constexpr_tests.cpp

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,20 @@ namespace LWG4420
5959
}
6060
#endif
6161

62+
constexpr auto default_mask_abi_variant =
63+
#ifdef __AVX512F__
64+
simd::_AbiVariant::_BitMask;
65+
#else
66+
simd::_AbiVariant();
67+
#endif
68+
6269
namespace test01
6370
{
6471
using std::same_as;
6572

66-
static_assert(same_as<simd::vec<int, 1>::abi_type, simd::_ScalarAbi<1>>);
67-
static_assert(same_as<simd::vec<float, 1>::abi_type, simd::_ScalarAbi<1>>);
73+
using Abi1 = simd::_Abi_t<1, 1, default_mask_abi_variant>;
74+
static_assert(same_as<simd::vec<int, 1>::abi_type, Abi1>);
75+
static_assert(same_as<simd::vec<float, 1>::abi_type, Abi1>);
6876

6977
#if defined __SSE__ && !defined __AVX__
7078
static_assert(same_as<simd::vec<float>::abi_type, simd::_Abi_t<4, 1>>);
@@ -88,18 +96,43 @@ namespace test02
8896
static_assert(!destructible<simd::basic_mask<7>>);
8997

9098
template <int N>
91-
using expected_abi
92-
#ifdef __AVX512F__
93-
= _Abi_t<N, 1, _AbiVariant::_BitMask, _AbiVariant::_CxIleav>;
94-
#elif defined __SSE2__
95-
= _Abi_t<N, 1, _AbiVariant::_CxIleav>;
96-
#else
97-
// FIXME: With SSE the answer depends on T
98-
= _ScalarAbi<N>;
99-
#endif
99+
using expected_abi = _Abi_t<N, 1, default_mask_abi_variant, _AbiVariant::_CxIleav>;
100100

101101
static_assert(same_as<simd::vec<complex<float>, 1>::abi_type, expected_abi<1>>);
102+
#ifdef __AVX__
102103
static_assert(same_as<simd::vec<complex<double>, 1>::abi_type, expected_abi<1>>);
104+
#else
105+
static_assert(same_as<simd::vec<complex<double>, 1>::abi_type, simd::_ScalarAbi<1>>);
106+
#endif
107+
108+
#if defined __AVX512F__
109+
static_assert(same_as<simd::vec<complex<float>, 2>::abi_type,
110+
_Abi_t<2, 1, _AbiVariant::_CxIleav, _AbiVariant::_BitMask>>);
111+
static_assert(same_as<simd::vec<complex<double>, 2>::abi_type,
112+
_Abi_t<2, 1, _AbiVariant::_CxIleav, _AbiVariant::_BitMask>>);
113+
static_assert(same_as<simd::vec<complex<float>, 4>::abi_type,
114+
_Abi_t<4, 1, _AbiVariant::_CxIleav, _AbiVariant::_BitMask>>);
115+
static_assert(same_as<simd::vec<complex<double>, 4>::abi_type,
116+
_Abi_t<4, 1, _AbiVariant::_CxIleav, _AbiVariant::_BitMask>>);
117+
#elif defined __AVX__
118+
static_assert(same_as<simd::vec<complex<float>, 2>::abi_type,
119+
_Abi_t<2, 1, _AbiVariant::_CxIleav>>);
120+
static_assert(same_as<simd::vec<complex<double>, 2>::abi_type,
121+
_Abi_t<2, 1, _AbiVariant::_CxIleav>>);
122+
static_assert(same_as<simd::vec<complex<float>, 4>::abi_type,
123+
_Abi_t<4, 1, _AbiVariant::_CxIleav>>);
124+
static_assert(same_as<simd::vec<complex<double>, 4>::abi_type,
125+
_Abi_t<4, 2, _AbiVariant::_CxIleav>>);
126+
#elif defined __SSE__
127+
static_assert(same_as<simd::vec<complex<float>, 2>::abi_type,
128+
_Abi_t<2, 1, _AbiVariant::_CxIleav>>);
129+
static_assert(same_as<simd::vec<complex<double>, 2>::abi_type,
130+
_ScalarAbi<2>>);
131+
static_assert(same_as<simd::vec<complex<float>, 4>::abi_type,
132+
_Abi_t<4, 2, _AbiVariant::_CxIleav>>);
133+
static_assert(same_as<simd::vec<complex<double>, 4>::abi_type,
134+
_ScalarAbi<4>>);
135+
#endif
103136

104137
static_assert(same_as<simd::vec<int>::mask_type, simd::mask<int>>);
105138
static_assert(same_as<simd::vec<float>::mask_type, simd::mask<float>>);
@@ -108,12 +141,6 @@ namespace test02
108141
static_assert(destructible<simd::vec<complex<float>>>);
109142
static_assert(same_as<simd::vec<complex<float>>::mask_type, simd::mask<complex<float>>>);
110143
static_assert(same_as<simd::vec<complex<float>, 1>::mask_type, simd::mask<complex<float>, 1>>);
111-
static_assert(same_as<simd::vec<complex<double>>::mask_type::abi_type,
112-
expected_abi<simd::vec<complex<double>>::size()>>);
113-
114-
// not the same because of the __deduce_t difference above
115-
static_assert(!same_as<simd::vec<complex<float>, 1>::mask_type, simd::vec<double, 1>::mask_type>);
116-
117144

118145
// ensure 'true ? int : vec<float>' doesn't work
119146
template <typename T>

generic-traits_tests.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ using std::complex;
1616
using std::float16_t;
1717
using std::float32_t;
1818
using std::float64_t;
19+
using std::is_same_v;
1920

2021
using namespace std::simd;
2122

@@ -40,6 +41,12 @@ void test()
4041
static_assert(sizeof(__integer_from<N>) == N);
4142
static_assert(__vectorizable<__integer_from<N>>);
4243
}
44+
template for (constexpr int N : {2, 4, 8})
45+
{
46+
static_assert(std::floating_point<__float_from<N>>);
47+
static_assert(sizeof(__float_from<N>) == N);
48+
static_assert(__vectorizable<__float_from<N>>);
49+
}
4350

4451
static_assert(__div_ceil(5, 3) == 2);
4552

@@ -48,6 +55,45 @@ void test()
4855

4956
static_assert(__scalar_abi_tag<_ScalarAbi<1>>);
5057
static_assert(__scalar_abi_tag<_ScalarAbi<2>>);
58+
static_assert(!__scalar_abi_tag<_Abi_t<1, 1>>);
59+
60+
static_assert(__abi_tag<_ScalarAbi<1>>);
61+
static_assert(__abi_tag<_ScalarAbi<2>>);
62+
static_assert(__abi_tag<_Abi_t<1, 1, _AbiVariant::_CxIleav>>);
63+
static_assert(__abi_tag<_Abi_t<1, 1, _AbiVariant::_CxCtgus>>);
64+
65+
using AN = decltype(__native_abi<float>());
66+
using A1 = decltype(__native_abi<float>()._S_resize<1>());
67+
static_assert(A1::_S_size == 1);
68+
static_assert(A1::_S_nreg == 1);
69+
static_assert(A1::_S_variant == AN::_S_variant);
70+
static_assert(__scalar_abi_tag<A1> == __scalar_abi_tag<AN>);
71+
static_assert(is_same_v<decltype(__abi_rebind<float, AN::_S_size, A1>()), AN>);
72+
if constexpr (AN::_S_size >= 2) // the target has SIMD support for float
73+
{
74+
{
75+
using A2 = decltype(__abi_rebind<float, 2, AN>());
76+
static_assert(A2::_S_size == 2);
77+
static_assert(A2::_S_nreg == 1);
78+
static_assert(A2::_S_variant == AN::_S_variant);
79+
using A2x = decltype(__abi_rebind<float, 2, decltype(__abi_rebind<float, 1, A2>())>());
80+
static_assert(is_same_v<A2, A2x>);
81+
}
82+
using A4 = decltype(__abi_rebind<float, 4, AN>());
83+
static_assert(A4::_S_size == 4);
84+
85+
// at this point we unconditionally expect _CxIleav from __abi_rebind:
86+
using AC2 = decltype(__abi_rebind<complex<float>, 2, AN>());
87+
static_assert(AC2::_S_size == 2);
88+
static_assert(AC2::_S_nreg == A4::_S_nreg);
89+
static_assert(AC2::_S_variant != A4::_S_variant);
90+
static_assert(__filter_abi_variant(AC2::_S_variant, _AbiVariant::_MaskVariants)
91+
== A4::_S_variant);
92+
static_assert(__filter_abi_variant(AC2::_S_variant, _AbiVariant::_CxVariants)
93+
== _AbiVariant::_CxIleav);
94+
static_assert(AC2::_S_is_cx_ileav);
95+
static_assert(!AC2::_S_is_cx_ctgus);
96+
}
5197

5298
static_assert(__streq_to_1("1"));
5399
static_assert(!__streq_to_1(""));

0 commit comments

Comments
 (0)