|
17 | 17 | #include <type_traits> |
18 | 18 |
|
19 | 19 | #include "../config/xsimd_macros.hpp" |
| 20 | +#include "../type_traits.hpp" |
20 | 21 | #include "../types/xsimd_sve_register.hpp" |
21 | 22 |
|
22 | 23 | // Define a inline namespace with the explicit SVE vector size to avoid ODR violation |
@@ -88,103 +89,36 @@ namespace xsimd |
88 | 89 | template <class T> |
89 | 90 | using sve_enable_all_t = std::enable_if_t<std::is_arithmetic<T>::value, int>; |
90 | 91 |
|
91 | | - // Trait describing the SVE types that correspond to a scalar, |
92 | | - // parameterised by (byte size, signedness, floating-point-ness). |
93 | | - // |
94 | | - // `scalar` is the matching fixed-width scalar (int8_t, ..., float, |
95 | | - // double). SVE load/store intrinsics are overloaded on these |
96 | | - // pointer types, so remapping integers through `scalar` avoids |
97 | | - // platform quirks such as darwin arm64's `long` vs `long long` |
98 | | - // distinction and rejects `char` as an element type. |
99 | | - // |
100 | | - // `sizeless` is the matching sizeless SVE type. xsimd stores SVE |
101 | | - // vectors as fixed-size attributed types (arm_sve_vector_bits), |
102 | | - // which clang treats as implicitly convertible to every sizeless |
103 | | - // SVE type — including multi-vector tuples — making the overloaded |
104 | | - // svreinterpret_*/svsel/etc. intrinsics ambiguous. Static-casting |
105 | | - // to `sizeless` first collapses the overload set to the single |
| 92 | + // Sizeless SVE type for T. |
| 93 | + // xsimd stores SVE vectors as fixed-size attributed types (arm_sve_vector_bits), |
| 94 | + // which clang treats as implicitly convertible to every sizeless SVE |
| 95 | + // type — including multi-vector tuples — making the overloaded |
| 96 | + // svreinterpret_*/svsel/etc. // intrinsics ambiguous. |
| 97 | + // Static-casting to `sizeless` first collapses the overload set to the single |
106 | 98 | // 1-vector candidate. |
107 | | - template <size_t N, bool Signed, bool FP> |
108 | | - struct sve_type; |
109 | | - template <> |
110 | | - struct sve_type<1, true, false> |
111 | | - { |
112 | | - using scalar = int8_t; |
113 | | - using sizeless = svint8_t; |
114 | | - }; |
115 | | - template <> |
116 | | - struct sve_type<1, false, false> |
117 | | - { |
118 | | - using scalar = uint8_t; |
119 | | - using sizeless = svuint8_t; |
120 | | - }; |
121 | | - template <> |
122 | | - struct sve_type<2, true, false> |
123 | | - { |
124 | | - using scalar = int16_t; |
125 | | - using sizeless = svint16_t; |
126 | | - }; |
127 | | - template <> |
128 | | - struct sve_type<2, false, false> |
129 | | - { |
130 | | - using scalar = uint16_t; |
131 | | - using sizeless = svuint16_t; |
132 | | - }; |
133 | | - template <> |
134 | | - struct sve_type<4, true, false> |
135 | | - { |
136 | | - using scalar = int32_t; |
137 | | - using sizeless = svint32_t; |
138 | | - }; |
139 | | - template <> |
140 | | - struct sve_type<4, false, false> |
141 | | - { |
142 | | - using scalar = uint32_t; |
143 | | - using sizeless = svuint32_t; |
144 | | - }; |
145 | | - template <> |
146 | | - struct sve_type<8, true, false> |
147 | | - { |
148 | | - using scalar = int64_t; |
149 | | - using sizeless = svint64_t; |
150 | | - }; |
151 | | - template <> |
152 | | - struct sve_type<8, false, false> |
153 | | - { |
154 | | - using scalar = uint64_t; |
155 | | - using sizeless = svuint64_t; |
156 | | - }; |
157 | | - template <> |
158 | | - struct sve_type<4, true, true> |
159 | | - { |
160 | | - using scalar = float; |
161 | | - using sizeless = svfloat32_t; |
162 | | - }; |
163 | | - template <> |
164 | | - struct sve_type<8, true, true> |
165 | | - { |
166 | | - using scalar = double; |
167 | | - using sizeless = svfloat64_t; |
168 | | - }; |
169 | | - |
170 | 99 | template <class T> |
171 | | - using sve_type_for = sve_type<sizeof(T), std::is_signed<T>::value, std::is_floating_point<T>::value>; |
| 100 | + using sve_sizeless_t = xsimd::types::detail::sve_vector_type<T>; |
172 | 101 |
|
173 | | - template <class T> |
174 | | - using sve_sizeless_t = typename sve_type_for<T>::sizeless; |
175 | | - |
176 | | - // Remap integer Ts to their matching fixed-width counterpart (via |
177 | | - // sve_type::scalar) so svld1/svst1 see the pointer type their |
178 | | - // overload set expects; pass non-integer Ts through unchanged. |
179 | | - template <class T, bool IsInt = std::is_integral<std::decay_t<T>>::value> |
| 102 | + // Remap integer Ts to their matching fixed-width counterpart so |
| 103 | + // svld1/svst1 see the pointer type their overload set expects; |
| 104 | + // pass non-integer Ts through unchanged. Uses sized_int_t / |
| 105 | + // sized_uint_t / sized_fp_t which already enumerate scalar types. |
| 106 | + template <class T, int = 0> |
180 | 107 | struct sve_fix_integer_impl |
181 | 108 | { |
182 | 109 | using type = T; |
183 | 110 | }; |
| 111 | + |
| 112 | + template <class T> |
| 113 | + struct sve_fix_integer_impl<T, sve_enable_signed_int_t<std::decay_t<T>> {}> |
| 114 | + { |
| 115 | + using type = xsimd::sized_int_t<sizeof(std::decay_t<T>)>; |
| 116 | + }; |
| 117 | + |
184 | 118 | template <class T> |
185 | | - struct sve_fix_integer_impl<T, true> |
| 119 | + struct sve_fix_integer_impl<T, sve_enable_unsigned_int_t<std::decay_t<T>> {}> |
186 | 120 | { |
187 | | - using type = typename sve_type_for<std::decay_t<T>>::scalar; |
| 121 | + using type = xsimd::sized_uint_t<sizeof(std::decay_t<T>)>; |
188 | 122 | }; |
189 | 123 |
|
190 | 124 | template <class T> |
|
0 commit comments