1 // x86 specific conversion optimizations -*- C++ -*-
2 
3 // Copyright (C) 2020-2021 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 #ifndef _GLIBCXX_EXPERIMENTAL_SIMD_X86_CONVERSIONS_H
26 #define _GLIBCXX_EXPERIMENTAL_SIMD_X86_CONVERSIONS_H
27 
28 #if __cplusplus >= 201703L
29 
30 // work around PR85827
31 // 1-arg __convert_x86 {{{1
32 template <typename _To, typename _V, typename _Traits>
33   _GLIBCXX_SIMD_INTRINSIC _To
__convert_x86(_V __v)34   __convert_x86(_V __v)
35   {
36     static_assert(__is_vector_type_v<_V>);
37     using _Tp = typename _Traits::value_type;
38     constexpr size_t _Np = _Traits::_S_full_size;
39     [[maybe_unused]] const auto __intrin = __to_intrin(__v);
40     using _Up = typename _VectorTraits<_To>::value_type;
41     constexpr size_t _M = _VectorTraits<_To>::_S_full_size;
42 
43     // [xyz]_to_[xyz] {{{2
44     [[maybe_unused]] constexpr bool __x_to_x
45       = sizeof(__v) <= 16 && sizeof(_To) <= 16;
46     [[maybe_unused]] constexpr bool __x_to_y
47       = sizeof(__v) <= 16 && sizeof(_To) == 32;
48     [[maybe_unused]] constexpr bool __x_to_z
49       = sizeof(__v) <= 16 && sizeof(_To) == 64;
50     [[maybe_unused]] constexpr bool __y_to_x
51       = sizeof(__v) == 32 && sizeof(_To) <= 16;
52     [[maybe_unused]] constexpr bool __y_to_y
53       = sizeof(__v) == 32 && sizeof(_To) == 32;
54     [[maybe_unused]] constexpr bool __y_to_z
55       = sizeof(__v) == 32 && sizeof(_To) == 64;
56     [[maybe_unused]] constexpr bool __z_to_x
57       = sizeof(__v) == 64 && sizeof(_To) <= 16;
58     [[maybe_unused]] constexpr bool __z_to_y
59       = sizeof(__v) == 64 && sizeof(_To) == 32;
60     [[maybe_unused]] constexpr bool __z_to_z
61       = sizeof(__v) == 64 && sizeof(_To) == 64;
62 
63     // iX_to_iX {{{2
64     [[maybe_unused]] constexpr bool __i_to_i
65       = is_integral_v<_Up> && is_integral_v<_Tp>;
66     [[maybe_unused]] constexpr bool __i8_to_i16
67       = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 2;
68     [[maybe_unused]] constexpr bool __i8_to_i32
69       = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 4;
70     [[maybe_unused]] constexpr bool __i8_to_i64
71       = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 8;
72     [[maybe_unused]] constexpr bool __i16_to_i8
73       = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 1;
74     [[maybe_unused]] constexpr bool __i16_to_i32
75       = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 4;
76     [[maybe_unused]] constexpr bool __i16_to_i64
77       = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 8;
78     [[maybe_unused]] constexpr bool __i32_to_i8
79       = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 1;
80     [[maybe_unused]] constexpr bool __i32_to_i16
81       = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 2;
82     [[maybe_unused]] constexpr bool __i32_to_i64
83       = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 8;
84     [[maybe_unused]] constexpr bool __i64_to_i8
85       = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 1;
86     [[maybe_unused]] constexpr bool __i64_to_i16
87       = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 2;
88     [[maybe_unused]] constexpr bool __i64_to_i32
89       = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 4;
90 
91     // [fsu]X_to_[fsu]X {{{2
92     // ibw = integral && byte or word, i.e. char and short with any signedness
93     [[maybe_unused]] constexpr bool __s64_to_f32
94       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 8
95 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
96     [[maybe_unused]] constexpr bool __s32_to_f32
97       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
98 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
99     [[maybe_unused]] constexpr bool __s16_to_f32
100       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 2
101 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
102     [[maybe_unused]] constexpr bool __s8_to_f32
103       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 1
104 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
105     [[maybe_unused]] constexpr bool __u64_to_f32
106       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 8
107 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
108     [[maybe_unused]] constexpr bool __u32_to_f32
109       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
110 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
111     [[maybe_unused]] constexpr bool __u16_to_f32
112       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 2
113 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
114     [[maybe_unused]] constexpr bool __u8_to_f32
115       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 1
116 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
117     [[maybe_unused]] constexpr bool __s64_to_f64
118       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 8
119 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
120     [[maybe_unused]] constexpr bool __s32_to_f64
121       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
122 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
123     [[maybe_unused]] constexpr bool __u64_to_f64
124       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 8
125 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
126     [[maybe_unused]] constexpr bool __u32_to_f64
127       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
128 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
129     [[maybe_unused]] constexpr bool __f32_to_s64
130       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
131 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
132     [[maybe_unused]] constexpr bool __f32_to_s32
133       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
134 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
135     [[maybe_unused]] constexpr bool __f32_to_u64
136       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
137 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
138     [[maybe_unused]] constexpr bool __f32_to_u32
139       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
140 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
141     [[maybe_unused]] constexpr bool __f64_to_s64
142       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
143 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
144     [[maybe_unused]] constexpr bool __f64_to_s32
145       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
146 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
147     [[maybe_unused]] constexpr bool __f64_to_u64
148       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
149 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
150     [[maybe_unused]] constexpr bool __f64_to_u32
151       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
152 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
153     [[maybe_unused]] constexpr bool __ibw_to_f32
154       = is_integral_v<_Tp> && sizeof(_Tp) <= 2
155 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
156     [[maybe_unused]] constexpr bool __ibw_to_f64
157       = is_integral_v<_Tp> && sizeof(_Tp) <= 2
158 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
159     [[maybe_unused]] constexpr bool __f32_to_ibw
160       = is_integral_v<_Up> && sizeof(_Up) <= 2
161 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
162     [[maybe_unused]] constexpr bool __f64_to_ibw
163       = is_integral_v<_Up> && sizeof(_Up) <= 2
164 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
165     [[maybe_unused]] constexpr bool __f32_to_f64
166       = is_floating_point_v<_Tp> && sizeof(_Tp) == 4
167 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
168     [[maybe_unused]] constexpr bool __f64_to_f32
169       = is_floating_point_v<_Tp> && sizeof(_Tp) == 8
170 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
171 
172     if constexpr (__i_to_i && __y_to_x && !__have_avx2) //{{{2
173       return __convert_x86<_To>(__lo128(__v), __hi128(__v));
174     else if constexpr (__i_to_i && __x_to_y && !__have_avx2) //{{{2
175       return __concat(__convert_x86<__vector_type_t<_Up, _M / 2>>(__v),
176 		      __convert_x86<__vector_type_t<_Up, _M / 2>>(
177 			__extract_part<1, _Np / _M * 2>(__v)));
178     else if constexpr (__i_to_i) //{{{2
179       {
180 	static_assert(__x_to_x || __have_avx2,
181 		      "integral conversions with ymm registers require AVX2");
182 	static_assert(__have_avx512bw
183 			|| ((sizeof(_Tp) >= 4 || sizeof(__v) < 64)
184 			    && (sizeof(_Up) >= 4 || sizeof(_To) < 64)),
185 		      "8/16-bit integers in zmm registers require AVX512BW");
186 	static_assert((sizeof(__v) < 64 && sizeof(_To) < 64) || __have_avx512f,
187 		      "integral conversions with ymm registers require AVX2");
188       }
189     if constexpr (is_floating_point_v<_Tp> == is_floating_point_v<_Up> && //{{{2
190 		  sizeof(_Tp) == sizeof(_Up))
191       {
192 	// conversion uses simple bit reinterpretation (or no conversion at all)
193 	if constexpr (_Np >= _M)
194 	  return __intrin_bitcast<_To>(__v);
195 	else
196 	  return __zero_extend(__vector_bitcast<_Up>(__v));
197       }
198     else if constexpr (_Np < _M && sizeof(_To) > 16) //{{{2
199       // zero extend (eg. xmm -> ymm)
200       return __zero_extend(
201 	__convert_x86<__vector_type_t<
202 	  _Up, (16 / sizeof(_Up) > _Np) ? 16 / sizeof(_Up) : _Np>>(__v));
203     else if constexpr (_Np > _M && sizeof(__v) > 16) //{{{2
204       // partial input (eg. ymm -> xmm)
205       return __convert_x86<_To>(__extract_part<0, _Np / _M>(__v));
206     else if constexpr (__i64_to_i32) //{{{2
207       {
208 	if constexpr (__x_to_x && __have_avx512vl)
209 	  return __intrin_bitcast<_To>(_mm_cvtepi64_epi32(__intrin));
210 	else if constexpr (__x_to_x)
211 	  return __auto_bitcast(
212 	    _mm_shuffle_ps(__vector_bitcast<float>(__v), __m128(), 8));
213 	else if constexpr (__y_to_x && __have_avx512vl)
214 	  return __intrin_bitcast<_To>(_mm256_cvtepi64_epi32(__intrin));
215 	else if constexpr (__y_to_x && __have_avx512f)
216 	  return __intrin_bitcast<_To>(
217 	    __lo128(_mm512_cvtepi64_epi32(__auto_bitcast(__v))));
218 	else if constexpr (__y_to_x)
219 	  return __intrin_bitcast<_To>(
220 	    __lo128(_mm256_permute4x64_epi64(_mm256_shuffle_epi32(__intrin, 8),
221 					     0 + 4 * 2)));
222 	else if constexpr (__z_to_y)
223 	  return __intrin_bitcast<_To>(_mm512_cvtepi64_epi32(__intrin));
224       }
225     else if constexpr (__i64_to_i16) //{{{2
226       {
227 	if constexpr (__x_to_x && __have_avx512vl)
228 	  return __intrin_bitcast<_To>(_mm_cvtepi64_epi16(__intrin));
229 	else if constexpr (__x_to_x && __have_avx512f)
230 	  return __intrin_bitcast<_To>(
231 	    __lo128(_mm512_cvtepi64_epi16(__auto_bitcast(__v))));
232 	else if constexpr (__x_to_x && __have_ssse3)
233 	  {
234 	    return __intrin_bitcast<_To>(
235 	      _mm_shuffle_epi8(__intrin,
236 			       _mm_setr_epi8(0, 1, 8, 9, -0x80, -0x80, -0x80,
237 					     -0x80, -0x80, -0x80, -0x80, -0x80,
238 					     -0x80, -0x80, -0x80, -0x80)));
239 	    // fallback without SSSE3
240 	  }
241 	else if constexpr (__y_to_x && __have_avx512vl)
242 	  return __intrin_bitcast<_To>(_mm256_cvtepi64_epi16(__intrin));
243 	else if constexpr (__y_to_x && __have_avx512f)
244 	  return __intrin_bitcast<_To>(
245 	    __lo128(_mm512_cvtepi64_epi16(__auto_bitcast(__v))));
246 	else if constexpr (__y_to_x)
247 	  {
248 	    const auto __a = _mm256_shuffle_epi8(
249 	      __intrin,
250 	      _mm256_setr_epi8(0, 1, 8, 9, -0x80, -0x80, -0x80, -0x80, -0x80,
251 			       -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
252 			       -0x80, -0x80, -0x80, -0x80, 0, 1, 8, 9, -0x80,
253 			       -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
254 			       -0x80));
255 	    return __intrin_bitcast<_To>(__lo128(__a) | __hi128(__a));
256 	  }
257 	else if constexpr (__z_to_x)
258 	  return __intrin_bitcast<_To>(_mm512_cvtepi64_epi16(__intrin));
259       }
260     else if constexpr (__i64_to_i8) //{{{2
261       {
262 	if constexpr (__x_to_x && __have_avx512vl)
263 	  return __intrin_bitcast<_To>(_mm_cvtepi64_epi8(__intrin));
264 	else if constexpr (__x_to_x && __have_avx512f)
265 	  return __intrin_bitcast<_To>(
266 	    __lo128(_mm512_cvtepi64_epi8(__zero_extend(__intrin))));
267 	else if constexpr (__y_to_x && __have_avx512vl)
268 	  return __intrin_bitcast<_To>(_mm256_cvtepi64_epi8(__intrin));
269 	else if constexpr (__y_to_x && __have_avx512f)
270 	  return __intrin_bitcast<_To>(
271 	    _mm512_cvtepi64_epi8(__zero_extend(__intrin)));
272 	else if constexpr (__z_to_x)
273 	  return __intrin_bitcast<_To>(_mm512_cvtepi64_epi8(__intrin));
274       }
275     else if constexpr (__i32_to_i64) //{{{2
276       {
277 	if constexpr (__have_sse4_1 && __x_to_x)
278 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
279 					 ? _mm_cvtepi32_epi64(__intrin)
280 					 : _mm_cvtepu32_epi64(__intrin));
281 	else if constexpr (__x_to_x)
282 	  {
283 	    return __intrin_bitcast<_To>(
284 	      _mm_unpacklo_epi32(__intrin, is_signed_v<_Tp>
285 					     ? _mm_srai_epi32(__intrin, 31)
286 					     : __m128i()));
287 	  }
288 	else if constexpr (__x_to_y)
289 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
290 					 ? _mm256_cvtepi32_epi64(__intrin)
291 					 : _mm256_cvtepu32_epi64(__intrin));
292 	else if constexpr (__y_to_z)
293 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
294 					 ? _mm512_cvtepi32_epi64(__intrin)
295 					 : _mm512_cvtepu32_epi64(__intrin));
296       }
297     else if constexpr (__i32_to_i16) //{{{2
298       {
299 	if constexpr (__x_to_x && __have_avx512vl)
300 	  return __intrin_bitcast<_To>(_mm_cvtepi32_epi16(__intrin));
301 	else if constexpr (__x_to_x && __have_avx512f)
302 	  return __intrin_bitcast<_To>(
303 	    __lo128(_mm512_cvtepi32_epi16(__auto_bitcast(__v))));
304 	else if constexpr (__x_to_x && __have_ssse3)
305 	  return __intrin_bitcast<_To>(_mm_shuffle_epi8(
306 	    __intrin, _mm_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, -0x80, -0x80,
307 				    -0x80, -0x80, -0x80, -0x80, -0x80, -0x80)));
308 	else if constexpr (__x_to_x)
309 	  {
310 	    auto __a = _mm_unpacklo_epi16(__intrin, __m128i()); // 0o.o 1o.o
311 	    auto __b = _mm_unpackhi_epi16(__intrin, __m128i()); // 2o.o 3o.o
312 	    auto __c = _mm_unpacklo_epi16(__a, __b);            // 02oo ..oo
313 	    auto __d = _mm_unpackhi_epi16(__a, __b);            // 13oo ..oo
314 	    return __intrin_bitcast<_To>(
315 	      _mm_unpacklo_epi16(__c, __d)); // 0123 oooo
316 	  }
317 	else if constexpr (__y_to_x && __have_avx512vl)
318 	  return __intrin_bitcast<_To>(_mm256_cvtepi32_epi16(__intrin));
319 	else if constexpr (__y_to_x && __have_avx512f)
320 	  return __intrin_bitcast<_To>(
321 	    __lo128(_mm512_cvtepi32_epi16(__auto_bitcast(__v))));
322 	else if constexpr (__y_to_x)
323 	  {
324 	    auto __a = _mm256_shuffle_epi8(
325 	      __intrin,
326 	      _mm256_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, -0x80, -0x80, -0x80,
327 			       -0x80, -0x80, -0x80, -0x80, -0x80, 0, 1, 4, 5, 8,
328 			       9, 12, 13, -0x80, -0x80, -0x80, -0x80, -0x80,
329 			       -0x80, -0x80, -0x80));
330 	    return __intrin_bitcast<_To>(__lo128(
331 	      _mm256_permute4x64_epi64(__a,
332 				       0xf8))); // __a[0] __a[2] | __a[3] __a[3]
333 	  }
334 	else if constexpr (__z_to_y)
335 	  return __intrin_bitcast<_To>(_mm512_cvtepi32_epi16(__intrin));
336       }
337     else if constexpr (__i32_to_i8) //{{{2
338       {
339 	if constexpr (__x_to_x && __have_avx512vl)
340 	  return __intrin_bitcast<_To>(_mm_cvtepi32_epi8(__intrin));
341 	else if constexpr (__x_to_x && __have_avx512f)
342 	  return __intrin_bitcast<_To>(
343 	    __lo128(_mm512_cvtepi32_epi8(__zero_extend(__intrin))));
344 	else if constexpr (__x_to_x && __have_ssse3)
345 	  {
346 	    return __intrin_bitcast<_To>(
347 	      _mm_shuffle_epi8(__intrin,
348 			       _mm_setr_epi8(0, 4, 8, 12, -0x80, -0x80, -0x80,
349 					     -0x80, -0x80, -0x80, -0x80, -0x80,
350 					     -0x80, -0x80, -0x80, -0x80)));
351 	  }
352 	else if constexpr (__x_to_x)
353 	  {
354 	    const auto __a
355 	      = _mm_unpacklo_epi8(__intrin, __intrin); // 0... .... 1... ....
356 	    const auto __b
357 	      = _mm_unpackhi_epi8(__intrin, __intrin);    // 2... .... 3... ....
358 	    const auto __c = _mm_unpacklo_epi8(__a, __b); // 02.. .... .... ....
359 	    const auto __d = _mm_unpackhi_epi8(__a, __b); // 13.. .... .... ....
360 	    const auto __e = _mm_unpacklo_epi8(__c, __d); // 0123 .... .... ....
361 	    return __intrin_bitcast<_To>(__e & _mm_cvtsi32_si128(-1));
362 	  }
363 	else if constexpr (__y_to_x && __have_avx512vl)
364 	  return __intrin_bitcast<_To>(_mm256_cvtepi32_epi8(__intrin));
365 	else if constexpr (__y_to_x && __have_avx512f)
366 	  return __intrin_bitcast<_To>(
367 	    _mm512_cvtepi32_epi8(__zero_extend(__intrin)));
368 	else if constexpr (__z_to_x)
369 	  return __intrin_bitcast<_To>(_mm512_cvtepi32_epi8(__intrin));
370       }
371     else if constexpr (__i16_to_i64) //{{{2
372       {
373 	if constexpr (__x_to_x && __have_sse4_1)
374 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
375 					 ? _mm_cvtepi16_epi64(__intrin)
376 					 : _mm_cvtepu16_epi64(__intrin));
377 	else if constexpr (__x_to_x && is_signed_v<_Tp>)
378 	  {
379 	    auto __x = _mm_srai_epi16(__intrin, 15);
380 	    auto __y = _mm_unpacklo_epi16(__intrin, __x);
381 	    __x = _mm_unpacklo_epi16(__x, __x);
382 	    return __intrin_bitcast<_To>(_mm_unpacklo_epi32(__y, __x));
383 	  }
384 	else if constexpr (__x_to_x)
385 	  return __intrin_bitcast<_To>(
386 	    _mm_unpacklo_epi32(_mm_unpacklo_epi16(__intrin, __m128i()),
387 			       __m128i()));
388 	else if constexpr (__x_to_y)
389 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
390 					 ? _mm256_cvtepi16_epi64(__intrin)
391 					 : _mm256_cvtepu16_epi64(__intrin));
392 	else if constexpr (__x_to_z)
393 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
394 					 ? _mm512_cvtepi16_epi64(__intrin)
395 					 : _mm512_cvtepu16_epi64(__intrin));
396       }
397     else if constexpr (__i16_to_i32) //{{{2
398       {
399 	if constexpr (__x_to_x && __have_sse4_1)
400 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
401 					 ? _mm_cvtepi16_epi32(__intrin)
402 					 : _mm_cvtepu16_epi32(__intrin));
403 	else if constexpr (__x_to_x && is_signed_v<_Tp>)
404 	  return __intrin_bitcast<_To>(
405 	    _mm_srai_epi32(_mm_unpacklo_epi16(__intrin, __intrin), 16));
406 	else if constexpr (__x_to_x && is_unsigned_v<_Tp>)
407 	  return __intrin_bitcast<_To>(_mm_unpacklo_epi16(__intrin, __m128i()));
408 	else if constexpr (__x_to_y)
409 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
410 					 ? _mm256_cvtepi16_epi32(__intrin)
411 					 : _mm256_cvtepu16_epi32(__intrin));
412 	else if constexpr (__y_to_z)
413 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
414 					 ? _mm512_cvtepi16_epi32(__intrin)
415 					 : _mm512_cvtepu16_epi32(__intrin));
416       }
417     else if constexpr (__i16_to_i8) //{{{2
418       {
419 	if constexpr (__x_to_x && __have_avx512bw_vl)
420 	  return __intrin_bitcast<_To>(_mm_cvtepi16_epi8(__intrin));
421 	else if constexpr (__x_to_x && __have_avx512bw)
422 	  return __intrin_bitcast<_To>(
423 	    __lo128(_mm512_cvtepi16_epi8(__zero_extend(__intrin))));
424 	else if constexpr (__x_to_x && __have_ssse3)
425 	  return __intrin_bitcast<_To>(_mm_shuffle_epi8(
426 	    __intrin, _mm_setr_epi8(0, 2, 4, 6, 8, 10, 12, 14, -0x80, -0x80,
427 				    -0x80, -0x80, -0x80, -0x80, -0x80, -0x80)));
428 	else if constexpr (__x_to_x)
429 	  {
430 	    auto __a
431 	      = _mm_unpacklo_epi8(__intrin, __intrin); // 00.. 11.. 22.. 33..
432 	    auto __b
433 	      = _mm_unpackhi_epi8(__intrin, __intrin); // 44.. 55.. 66.. 77..
434 	    auto __c = _mm_unpacklo_epi8(__a, __b);    // 0404 .... 1515 ....
435 	    auto __d = _mm_unpackhi_epi8(__a, __b);    // 2626 .... 3737 ....
436 	    auto __e = _mm_unpacklo_epi8(__c, __d);    // 0246 0246 .... ....
437 	    auto __f = _mm_unpackhi_epi8(__c, __d);    // 1357 1357 .... ....
438 	    return __intrin_bitcast<_To>(_mm_unpacklo_epi8(__e, __f));
439 	  }
440 	else if constexpr (__y_to_x && __have_avx512bw_vl)
441 	  return __intrin_bitcast<_To>(_mm256_cvtepi16_epi8(__intrin));
442 	else if constexpr (__y_to_x && __have_avx512bw)
443 	  return __intrin_bitcast<_To>(
444 	    __lo256(_mm512_cvtepi16_epi8(__zero_extend(__intrin))));
445 	else if constexpr (__y_to_x)
446 	  {
447 	    auto __a = _mm256_shuffle_epi8(
448 	      __intrin,
449 	      _mm256_setr_epi8(0, 2, 4, 6, 8, 10, 12, 14, -0x80, -0x80, -0x80,
450 			       -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
451 			       -0x80, -0x80, -0x80, -0x80, -0x80, -0x80, 0, 2,
452 			       4, 6, 8, 10, 12, 14));
453 	    return __intrin_bitcast<_To>(__lo128(__a) | __hi128(__a));
454 	  }
455 	else if constexpr (__z_to_y && __have_avx512bw)
456 	  return __intrin_bitcast<_To>(_mm512_cvtepi16_epi8(__intrin));
457 	else if constexpr (__z_to_y)
458 	  __assert_unreachable<_Tp>();
459       }
460     else if constexpr (__i8_to_i64) //{{{2
461       {
462 	if constexpr (__x_to_x && __have_sse4_1)
463 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
464 					 ? _mm_cvtepi8_epi64(__intrin)
465 					 : _mm_cvtepu8_epi64(__intrin));
466 	else if constexpr (__x_to_x && is_signed_v<_Tp>)
467 	  {
468 	    if constexpr (__have_ssse3)
469 	      {
470 		auto __dup = _mm_unpacklo_epi8(__intrin, __intrin);
471 		auto __epi16 = _mm_srai_epi16(__dup, 8);
472 		_mm_shuffle_epi8(__epi16,
473 				 _mm_setr_epi8(0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3,
474 					       3, 3, 3, 3, 3));
475 	      }
476 	    else
477 	      {
478 		auto __x = _mm_unpacklo_epi8(__intrin, __intrin);
479 		__x = _mm_unpacklo_epi16(__x, __x);
480 		return __intrin_bitcast<_To>(
481 		  _mm_unpacklo_epi32(_mm_srai_epi32(__x, 24),
482 				     _mm_srai_epi32(__x, 31)));
483 	      }
484 	  }
485 	else if constexpr (__x_to_x)
486 	  {
487 	    return __intrin_bitcast<_To>(_mm_unpacklo_epi32(
488 	      _mm_unpacklo_epi16(_mm_unpacklo_epi8(__intrin, __m128i()),
489 				 __m128i()),
490 	      __m128i()));
491 	  }
492 	else if constexpr (__x_to_y)
493 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
494 					 ? _mm256_cvtepi8_epi64(__intrin)
495 					 : _mm256_cvtepu8_epi64(__intrin));
496 	else if constexpr (__x_to_z)
497 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
498 					 ? _mm512_cvtepi8_epi64(__intrin)
499 					 : _mm512_cvtepu8_epi64(__intrin));
500       }
501     else if constexpr (__i8_to_i32) //{{{2
502       {
503 	if constexpr (__x_to_x && __have_sse4_1)
504 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
505 					 ? _mm_cvtepi8_epi32(__intrin)
506 					 : _mm_cvtepu8_epi32(__intrin));
507 	else if constexpr (__x_to_x && is_signed_v<_Tp>)
508 	  {
509 	    const auto __x = _mm_unpacklo_epi8(__intrin, __intrin);
510 	    return __intrin_bitcast<_To>(
511 	      _mm_srai_epi32(_mm_unpacklo_epi16(__x, __x), 24));
512 	  }
513 	else if constexpr (__x_to_x && is_unsigned_v<_Tp>)
514 	  return __intrin_bitcast<_To>(
515 	    _mm_unpacklo_epi16(_mm_unpacklo_epi8(__intrin, __m128i()),
516 			       __m128i()));
517 	else if constexpr (__x_to_y)
518 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
519 					 ? _mm256_cvtepi8_epi32(__intrin)
520 					 : _mm256_cvtepu8_epi32(__intrin));
521 	else if constexpr (__x_to_z)
522 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
523 					 ? _mm512_cvtepi8_epi32(__intrin)
524 					 : _mm512_cvtepu8_epi32(__intrin));
525       }
526     else if constexpr (__i8_to_i16) //{{{2
527       {
528 	if constexpr (__x_to_x && __have_sse4_1)
529 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
530 					 ? _mm_cvtepi8_epi16(__intrin)
531 					 : _mm_cvtepu8_epi16(__intrin));
532 	else if constexpr (__x_to_x && is_signed_v<_Tp>)
533 	  return __intrin_bitcast<_To>(
534 	    _mm_srai_epi16(_mm_unpacklo_epi8(__intrin, __intrin), 8));
535 	else if constexpr (__x_to_x && is_unsigned_v<_Tp>)
536 	  return __intrin_bitcast<_To>(_mm_unpacklo_epi8(__intrin, __m128i()));
537 	else if constexpr (__x_to_y)
538 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
539 					 ? _mm256_cvtepi8_epi16(__intrin)
540 					 : _mm256_cvtepu8_epi16(__intrin));
541 	else if constexpr (__y_to_z && __have_avx512bw)
542 	  return __intrin_bitcast<_To>(is_signed_v<_Tp>
543 					 ? _mm512_cvtepi8_epi16(__intrin)
544 					 : _mm512_cvtepu8_epi16(__intrin));
545 	else if constexpr (__y_to_z)
546 	  __assert_unreachable<_Tp>();
547       }
548     else if constexpr (__f32_to_s64) //{{{2
549       {
550 	if constexpr (__have_avx512dq_vl && __x_to_x)
551 	  return __intrin_bitcast<_To>(_mm_cvttps_epi64(__intrin));
552 	else if constexpr (__have_avx512dq_vl && __x_to_y)
553 	  return __intrin_bitcast<_To>(_mm256_cvttps_epi64(__intrin));
554 	else if constexpr (__have_avx512dq && __y_to_z)
555 	  return __intrin_bitcast<_To>(_mm512_cvttps_epi64(__intrin));
556 	// else use scalar fallback
557       }
558     else if constexpr (__f32_to_u64) //{{{2
559       {
560 	if constexpr (__have_avx512dq_vl && __x_to_x)
561 	  return __intrin_bitcast<_To>(_mm_cvttps_epu64(__intrin));
562 	else if constexpr (__have_avx512dq_vl && __x_to_y)
563 	  return __intrin_bitcast<_To>(_mm256_cvttps_epu64(__intrin));
564 	else if constexpr (__have_avx512dq && __y_to_z)
565 	  return __intrin_bitcast<_To>(_mm512_cvttps_epu64(__intrin));
566 	// else use scalar fallback
567       }
568     else if constexpr (__f32_to_s32) //{{{2
569       {
570 	if constexpr (__x_to_x || __y_to_y || __z_to_z)
571 	  {
572 	    // go to fallback, it does the right thing
573 	  }
574 	else
575 	  __assert_unreachable<_Tp>();
576       }
577     else if constexpr (__f32_to_u32) //{{{2
578       {
579 	if constexpr (__have_avx512vl && __x_to_x)
580 	  return __auto_bitcast(_mm_cvttps_epu32(__intrin));
581 	else if constexpr (__have_avx512f && __x_to_x)
582 	  return __auto_bitcast(
583 	    __lo128(_mm512_cvttps_epu32(__auto_bitcast(__v))));
584 	else if constexpr (__have_avx512vl && __y_to_y)
585 	  return __vector_bitcast<_Up>(_mm256_cvttps_epu32(__intrin));
586 	else if constexpr (__have_avx512f && __y_to_y)
587 	  return __vector_bitcast<_Up>(
588 	    __lo256(_mm512_cvttps_epu32(__auto_bitcast(__v))));
589 	else if constexpr (__x_to_x || __y_to_y || __z_to_z)
590 	  {
591 	    // go to fallback, it does the right thing. We can't use the
592 	    // _mm_floor_ps - 0x8000'0000 trick for f32->u32 because it would
593 	    // discard small input values (only 24 mantissa bits)
594 	  }
595 	else
596 	  __assert_unreachable<_Tp>();
597       }
598     else if constexpr (__f32_to_ibw) //{{{2
599       return __convert_x86<_To>(__convert_x86<__vector_type_t<int, _Np>>(__v));
600     else if constexpr (__f64_to_s64) //{{{2
601       {
602 	if constexpr (__have_avx512dq_vl && __x_to_x)
603 	  return __intrin_bitcast<_To>(_mm_cvttpd_epi64(__intrin));
604 	else if constexpr (__have_avx512dq_vl && __y_to_y)
605 	  return __intrin_bitcast<_To>(_mm256_cvttpd_epi64(__intrin));
606 	else if constexpr (__have_avx512dq && __z_to_z)
607 	  return __intrin_bitcast<_To>(_mm512_cvttpd_epi64(__intrin));
608 	// else use scalar fallback
609       }
610     else if constexpr (__f64_to_u64) //{{{2
611       {
612 	if constexpr (__have_avx512dq_vl && __x_to_x)
613 	  return __intrin_bitcast<_To>(_mm_cvttpd_epu64(__intrin));
614 	else if constexpr (__have_avx512dq_vl && __y_to_y)
615 	  return __intrin_bitcast<_To>(_mm256_cvttpd_epu64(__intrin));
616 	else if constexpr (__have_avx512dq && __z_to_z)
617 	  return __intrin_bitcast<_To>(_mm512_cvttpd_epu64(__intrin));
618 	// else use scalar fallback
619       }
620     else if constexpr (__f64_to_s32) //{{{2
621       {
622 	if constexpr (__x_to_x)
623 	  return __intrin_bitcast<_To>(_mm_cvttpd_epi32(__intrin));
624 	else if constexpr (__y_to_x)
625 	  return __intrin_bitcast<_To>(_mm256_cvttpd_epi32(__intrin));
626 	else if constexpr (__z_to_y)
627 	  return __intrin_bitcast<_To>(_mm512_cvttpd_epi32(__intrin));
628       }
629     else if constexpr (__f64_to_u32) //{{{2
630       {
631 	if constexpr (__have_avx512vl && __x_to_x)
632 	  return __intrin_bitcast<_To>(_mm_cvttpd_epu32(__intrin));
633 	else if constexpr (__have_sse4_1 && __x_to_x)
634 	  return __vector_bitcast<_Up, _M>(
635 		   _mm_cvttpd_epi32(_mm_floor_pd(__intrin) - 0x8000'0000u))
636 		 ^ 0x8000'0000u;
637 	else if constexpr (__x_to_x)
638 	  {
639 	    // use scalar fallback: it's only 2 values to convert, can't get
640 	    // much better than scalar decomposition
641 	  }
642 	else if constexpr (__have_avx512vl && __y_to_x)
643 	  return __intrin_bitcast<_To>(_mm256_cvttpd_epu32(__intrin));
644 	else if constexpr (__y_to_x)
645 	  {
646 	    return __intrin_bitcast<_To>(
647 	      __vector_bitcast<_Up>(
648 		_mm256_cvttpd_epi32(_mm256_floor_pd(__intrin) - 0x8000'0000u))
649 	      ^ 0x8000'0000u);
650 	  }
651 	else if constexpr (__z_to_y)
652 	  return __intrin_bitcast<_To>(_mm512_cvttpd_epu32(__intrin));
653       }
654     else if constexpr (__f64_to_ibw) //{{{2
655       {
656 	return __convert_x86<_To>(
657 	  __convert_x86<__vector_type_t<int, (_Np < 4 ? 4 : _Np)>>(__v));
658       }
659     else if constexpr (__s64_to_f32) //{{{2
660       {
661 	if constexpr (__x_to_x && __have_avx512dq_vl)
662 	  return __intrin_bitcast<_To>(_mm_cvtepi64_ps(__intrin));
663 	else if constexpr (__y_to_x && __have_avx512dq_vl)
664 	  return __intrin_bitcast<_To>(_mm256_cvtepi64_ps(__intrin));
665 	else if constexpr (__z_to_y && __have_avx512dq)
666 	  return __intrin_bitcast<_To>(_mm512_cvtepi64_ps(__intrin));
667 	else if constexpr (__z_to_y)
668 	  return __intrin_bitcast<_To>(
669 	    _mm512_cvtpd_ps(__convert_x86<__vector_type_t<double, 8>>(__v)));
670       }
671     else if constexpr (__u64_to_f32) //{{{2
672       {
673 	if constexpr (__x_to_x && __have_avx512dq_vl)
674 	  return __intrin_bitcast<_To>(_mm_cvtepu64_ps(__intrin));
675 	else if constexpr (__y_to_x && __have_avx512dq_vl)
676 	  return __intrin_bitcast<_To>(_mm256_cvtepu64_ps(__intrin));
677 	else if constexpr (__z_to_y && __have_avx512dq)
678 	  return __intrin_bitcast<_To>(_mm512_cvtepu64_ps(__intrin));
679 	else if constexpr (__z_to_y)
680 	  {
681 	    return __intrin_bitcast<_To>(
682 	      __lo256(_mm512_cvtepu32_ps(__auto_bitcast(
683 		_mm512_cvtepi64_epi32(_mm512_srai_epi64(__intrin, 32)))))
684 		* 0x100000000LL
685 	      + __lo256(_mm512_cvtepu32_ps(
686 		__auto_bitcast(_mm512_cvtepi64_epi32(__intrin)))));
687 	  }
688       }
689     else if constexpr (__s32_to_f32) //{{{2
690       {
691 	// use fallback (builtin conversion)
692       }
693     else if constexpr (__u32_to_f32) //{{{2
694       {
695 	if constexpr (__x_to_x && __have_avx512vl)
696 	  {
697 	    // use fallback
698 	  }
699 	else if constexpr (__x_to_x && __have_avx512f)
700 	  return __intrin_bitcast<_To>(
701 	    __lo128(_mm512_cvtepu32_ps(__auto_bitcast(__v))));
702 	else if constexpr (__x_to_x && (__have_fma || __have_fma4))
703 	  // work around PR85819
704 	  return __auto_bitcast(0x10000
705 				  * _mm_cvtepi32_ps(__to_intrin(__v >> 16))
706 				+ _mm_cvtepi32_ps(__to_intrin(__v & 0xffff)));
707 	else if constexpr (__y_to_y && __have_avx512vl)
708 	  {
709 	    // use fallback
710 	  }
711 	else if constexpr (__y_to_y && __have_avx512f)
712 	  return __intrin_bitcast<_To>(
713 	    __lo256(_mm512_cvtepu32_ps(__auto_bitcast(__v))));
714 	else if constexpr (__y_to_y)
715 	  // work around PR85819
716 	  return 0x10000 * _mm256_cvtepi32_ps(__to_intrin(__v >> 16))
717 		 + _mm256_cvtepi32_ps(__to_intrin(__v & 0xffff));
718 	// else use fallback (builtin conversion)
719       }
720     else if constexpr (__ibw_to_f32) //{{{2
721       {
722 	if constexpr (_M <= 4 || __have_avx2)
723 	  return __convert_x86<_To>(
724 	    __convert_x86<__vector_type_t<int, _M>>(__v));
725 	else
726 	  {
727 	    static_assert(__x_to_y);
728 	    __m128i __a, __b;
729 	    if constexpr (__have_sse4_1)
730 	      {
731 		__a = sizeof(_Tp) == 2
732 			? (is_signed_v<_Tp> ? _mm_cvtepi16_epi32(__intrin)
733 					    : _mm_cvtepu16_epi32(__intrin))
734 			: (is_signed_v<_Tp> ? _mm_cvtepi8_epi32(__intrin)
735 					    : _mm_cvtepu8_epi32(__intrin));
736 		const auto __w
737 		  = _mm_shuffle_epi32(__intrin, sizeof(_Tp) == 2 ? 0xee : 0xe9);
738 		__b = sizeof(_Tp) == 2
739 			? (is_signed_v<_Tp> ? _mm_cvtepi16_epi32(__w)
740 					    : _mm_cvtepu16_epi32(__w))
741 			: (is_signed_v<_Tp> ? _mm_cvtepi8_epi32(__w)
742 					    : _mm_cvtepu8_epi32(__w));
743 	      }
744 	    else
745 	      {
746 		__m128i __tmp;
747 		if constexpr (sizeof(_Tp) == 1)
748 		  {
749 		    __tmp = is_signed_v<_Tp>
750 			      ? _mm_srai_epi16(_mm_unpacklo_epi8(__intrin,
751 								 __intrin),
752 					       8)
753 			      : _mm_unpacklo_epi8(__intrin, __m128i());
754 		  }
755 		else
756 		  {
757 		    static_assert(sizeof(_Tp) == 2);
758 		    __tmp = __intrin;
759 		  }
760 		__a = is_signed_v<_Tp>
761 			? _mm_srai_epi32(_mm_unpacklo_epi16(__tmp, __tmp), 16)
762 			: _mm_unpacklo_epi16(__tmp, __m128i());
763 		__b = is_signed_v<_Tp>
764 			? _mm_srai_epi32(_mm_unpackhi_epi16(__tmp, __tmp), 16)
765 			: _mm_unpackhi_epi16(__tmp, __m128i());
766 	      }
767 	    return __convert_x86<_To>(__vector_bitcast<int>(__a),
768 				      __vector_bitcast<int>(__b));
769 	  }
770       }
771     else if constexpr (__s64_to_f64) //{{{2
772       {
773 	if constexpr (__x_to_x && __have_avx512dq_vl)
774 	  return __intrin_bitcast<_To>(_mm_cvtepi64_pd(__intrin));
775 	else if constexpr (__y_to_y && __have_avx512dq_vl)
776 	  return __intrin_bitcast<_To>(_mm256_cvtepi64_pd(__intrin));
777 	else if constexpr (__z_to_z && __have_avx512dq)
778 	  return __intrin_bitcast<_To>(_mm512_cvtepi64_pd(__intrin));
779 	else if constexpr (__z_to_z)
780 	  {
781 	    return __intrin_bitcast<_To>(
782 	      _mm512_cvtepi32_pd(_mm512_cvtepi64_epi32(__to_intrin(__v >> 32)))
783 		* 0x100000000LL
784 	      + _mm512_cvtepu32_pd(_mm512_cvtepi64_epi32(__intrin)));
785 	  }
786       }
787     else if constexpr (__u64_to_f64) //{{{2
788       {
789 	if constexpr (__x_to_x && __have_avx512dq_vl)
790 	  return __intrin_bitcast<_To>(_mm_cvtepu64_pd(__intrin));
791 	else if constexpr (__y_to_y && __have_avx512dq_vl)
792 	  return __intrin_bitcast<_To>(_mm256_cvtepu64_pd(__intrin));
793 	else if constexpr (__z_to_z && __have_avx512dq)
794 	  return __intrin_bitcast<_To>(_mm512_cvtepu64_pd(__intrin));
795 	else if constexpr (__z_to_z)
796 	  {
797 	    return __intrin_bitcast<_To>(
798 	      _mm512_cvtepu32_pd(_mm512_cvtepi64_epi32(__to_intrin(__v >> 32)))
799 		* 0x100000000LL
800 	      + _mm512_cvtepu32_pd(_mm512_cvtepi64_epi32(__intrin)));
801 	  }
802       }
803     else if constexpr (__s32_to_f64) //{{{2
804       {
805 	if constexpr (__x_to_x)
806 	  return __intrin_bitcast<_To>(_mm_cvtepi32_pd(__intrin));
807 	else if constexpr (__x_to_y)
808 	  return __intrin_bitcast<_To>(_mm256_cvtepi32_pd(__intrin));
809 	else if constexpr (__y_to_z)
810 	  return __intrin_bitcast<_To>(_mm512_cvtepi32_pd(__intrin));
811       }
812     else if constexpr (__u32_to_f64) //{{{2
813       {
814 	if constexpr (__x_to_x && __have_avx512vl)
815 	  return __intrin_bitcast<_To>(_mm_cvtepu32_pd(__intrin));
816 	else if constexpr (__x_to_x && __have_avx512f)
817 	  return __intrin_bitcast<_To>(
818 	    __lo128(_mm512_cvtepu32_pd(__auto_bitcast(__v))));
819 	else if constexpr (__x_to_x)
820 	  return __intrin_bitcast<_To>(
821 	    _mm_cvtepi32_pd(__to_intrin(__v ^ 0x8000'0000u)) + 0x8000'0000u);
822 	else if constexpr (__x_to_y && __have_avx512vl)
823 	  return __intrin_bitcast<_To>(_mm256_cvtepu32_pd(__intrin));
824 	else if constexpr (__x_to_y && __have_avx512f)
825 	  return __intrin_bitcast<_To>(
826 	    __lo256(_mm512_cvtepu32_pd(__auto_bitcast(__v))));
827 	else if constexpr (__x_to_y)
828 	  return __intrin_bitcast<_To>(
829 	    _mm256_cvtepi32_pd(__to_intrin(__v ^ 0x8000'0000u)) + 0x8000'0000u);
830 	else if constexpr (__y_to_z)
831 	  return __intrin_bitcast<_To>(_mm512_cvtepu32_pd(__intrin));
832       }
833     else if constexpr (__ibw_to_f64) //{{{2
834       {
835 	return __convert_x86<_To>(
836 	  __convert_x86<__vector_type_t<int, std::max(size_t(4), _M)>>(__v));
837       }
838     else if constexpr (__f32_to_f64) //{{{2
839       {
840 	if constexpr (__x_to_x)
841 	  return __intrin_bitcast<_To>(_mm_cvtps_pd(__intrin));
842 	else if constexpr (__x_to_y)
843 	  return __intrin_bitcast<_To>(_mm256_cvtps_pd(__intrin));
844 	else if constexpr (__y_to_z)
845 	  return __intrin_bitcast<_To>(_mm512_cvtps_pd(__intrin));
846       }
847     else if constexpr (__f64_to_f32) //{{{2
848       {
849 	if constexpr (__x_to_x)
850 	  return __intrin_bitcast<_To>(_mm_cvtpd_ps(__intrin));
851 	else if constexpr (__y_to_x)
852 	  return __intrin_bitcast<_To>(_mm256_cvtpd_ps(__intrin));
853 	else if constexpr (__z_to_y)
854 	  return __intrin_bitcast<_To>(_mm512_cvtpd_ps(__intrin));
855       }
856     else //{{{2
857       __assert_unreachable<_Tp>();
858 
859     // fallback:{{{2
860     return __vector_convert<_To>(__v, make_index_sequence<std::min(_M, _Np)>());
861     //}}}
862   }
863 
864 // }}}
865 // 2-arg __convert_x86 {{{1
866 template <typename _To, typename _V, typename _Traits>
867   _GLIBCXX_SIMD_INTRINSIC _To
__convert_x86(_V __v0,_V __v1)868   __convert_x86(_V __v0, _V __v1)
869   {
870     static_assert(__is_vector_type_v<_V>);
871     using _Tp = typename _Traits::value_type;
872     constexpr size_t _Np = _Traits::_S_full_size;
873     [[maybe_unused]] const auto __i0 = __to_intrin(__v0);
874     [[maybe_unused]] const auto __i1 = __to_intrin(__v1);
875     using _Up = typename _VectorTraits<_To>::value_type;
876     constexpr size_t _M = _VectorTraits<_To>::_S_full_size;
877 
878     static_assert(2 * _Np <= _M,
879 		  "__v1 would be discarded; use the one-argument "
880 		  "__convert_x86 overload instead");
881 
882     // [xyz]_to_[xyz] {{{2
883     [[maybe_unused]] constexpr bool __x_to_x
884       = sizeof(__v0) <= 16 && sizeof(_To) <= 16;
885     [[maybe_unused]] constexpr bool __x_to_y
886       = sizeof(__v0) <= 16 && sizeof(_To) == 32;
887     [[maybe_unused]] constexpr bool __x_to_z
888       = sizeof(__v0) <= 16 && sizeof(_To) == 64;
889     [[maybe_unused]] constexpr bool __y_to_x
890       = sizeof(__v0) == 32 && sizeof(_To) <= 16;
891     [[maybe_unused]] constexpr bool __y_to_y
892       = sizeof(__v0) == 32 && sizeof(_To) == 32;
893     [[maybe_unused]] constexpr bool __y_to_z
894       = sizeof(__v0) == 32 && sizeof(_To) == 64;
895     [[maybe_unused]] constexpr bool __z_to_x
896       = sizeof(__v0) == 64 && sizeof(_To) <= 16;
897     [[maybe_unused]] constexpr bool __z_to_y
898       = sizeof(__v0) == 64 && sizeof(_To) == 32;
899     [[maybe_unused]] constexpr bool __z_to_z
900       = sizeof(__v0) == 64 && sizeof(_To) == 64;
901 
902     // iX_to_iX {{{2
903     [[maybe_unused]] constexpr bool __i_to_i
904       = is_integral_v<_Up> && is_integral_v<_Tp>;
905     [[maybe_unused]] constexpr bool __i8_to_i16
906       = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 2;
907     [[maybe_unused]] constexpr bool __i8_to_i32
908       = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 4;
909     [[maybe_unused]] constexpr bool __i8_to_i64
910       = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 8;
911     [[maybe_unused]] constexpr bool __i16_to_i8
912       = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 1;
913     [[maybe_unused]] constexpr bool __i16_to_i32
914       = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 4;
915     [[maybe_unused]] constexpr bool __i16_to_i64
916       = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 8;
917     [[maybe_unused]] constexpr bool __i32_to_i8
918       = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 1;
919     [[maybe_unused]] constexpr bool __i32_to_i16
920       = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 2;
921     [[maybe_unused]] constexpr bool __i32_to_i64
922       = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 8;
923     [[maybe_unused]] constexpr bool __i64_to_i8
924       = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 1;
925     [[maybe_unused]] constexpr bool __i64_to_i16
926       = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 2;
927     [[maybe_unused]] constexpr bool __i64_to_i32
928       = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 4;
929 
930     // [fsu]X_to_[fsu]X {{{2
931     // ibw = integral && byte or word, i.e. char and short with any signedness
932     [[maybe_unused]] constexpr bool __i64_to_f32
933       = is_integral_v<_Tp> && sizeof(_Tp) == 8
934 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
935     [[maybe_unused]] constexpr bool __s32_to_f32
936       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
937 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
938     [[maybe_unused]] constexpr bool __s16_to_f32
939       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 2
940 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
941     [[maybe_unused]] constexpr bool __s8_to_f32
942       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 1
943 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
944     [[maybe_unused]] constexpr bool __u32_to_f32
945       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
946 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
947     [[maybe_unused]] constexpr bool __u16_to_f32
948       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 2
949 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
950     [[maybe_unused]] constexpr bool __u8_to_f32
951       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 1
952 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
953     [[maybe_unused]] constexpr bool __s64_to_f64
954       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 8
955 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
956     [[maybe_unused]] constexpr bool __s32_to_f64
957       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
958 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
959     [[maybe_unused]] constexpr bool __s16_to_f64
960       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 2
961 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
962     [[maybe_unused]] constexpr bool __s8_to_f64
963       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 1
964 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
965     [[maybe_unused]] constexpr bool __u64_to_f64
966       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 8
967 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
968     [[maybe_unused]] constexpr bool __u32_to_f64
969       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
970 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
971     [[maybe_unused]] constexpr bool __u16_to_f64
972       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 2
973 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
974     [[maybe_unused]] constexpr bool __u8_to_f64
975       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 1
976 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
977     [[maybe_unused]] constexpr bool __f32_to_s64
978       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
979 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
980     [[maybe_unused]] constexpr bool __f32_to_s32
981       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
982 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
983     [[maybe_unused]] constexpr bool __f32_to_u64
984       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
985 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
986     [[maybe_unused]] constexpr bool __f32_to_u32
987       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
988 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
989     [[maybe_unused]] constexpr bool __f64_to_s64
990       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
991 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
992     [[maybe_unused]] constexpr bool __f64_to_s32
993       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
994 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
995     [[maybe_unused]] constexpr bool __f64_to_u64
996       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
997 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
998     [[maybe_unused]] constexpr bool __f64_to_u32
999       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
1000 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
1001     [[maybe_unused]] constexpr bool __f32_to_ibw
1002       = is_integral_v<_Up> && sizeof(_Up) <= 2
1003 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
1004     [[maybe_unused]] constexpr bool __f64_to_ibw
1005       = is_integral_v<_Up> && sizeof(_Up) <= 2
1006 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
1007     [[maybe_unused]] constexpr bool __f32_to_f64
1008       = is_floating_point_v<_Tp> && sizeof(_Tp) == 4
1009 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
1010     [[maybe_unused]] constexpr bool __f64_to_f32
1011       = is_floating_point_v<_Tp> && sizeof(_Tp) == 8
1012 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
1013 
1014     if constexpr (__i_to_i && __y_to_x && !__have_avx2) //{{{2
1015       // <double, 4>, <double, 4> => <short, 8>
1016       return __convert_x86<_To>(__lo128(__v0), __hi128(__v0), __lo128(__v1),
1017 				__hi128(__v1));
1018     else if constexpr (__i_to_i) // assert ISA {{{2
1019       {
1020 	static_assert(__x_to_x || __have_avx2,
1021 		      "integral conversions with ymm registers require AVX2");
1022 	static_assert(__have_avx512bw
1023 			|| ((sizeof(_Tp) >= 4 || sizeof(__v0) < 64)
1024 			    && (sizeof(_Up) >= 4 || sizeof(_To) < 64)),
1025 		      "8/16-bit integers in zmm registers require AVX512BW");
1026 	static_assert((sizeof(__v0) < 64 && sizeof(_To) < 64) || __have_avx512f,
1027 		      "integral conversions with ymm registers require AVX2");
1028       }
1029     // concat => use 1-arg __convert_x86 {{{2
1030     if constexpr (sizeof(__v0) < 16 || (sizeof(__v0) == 16 && __have_avx2)
1031 		  || (sizeof(__v0) == 16 && __have_avx
1032 		      && is_floating_point_v<_Tp>)
1033 		  || (sizeof(__v0) == 32 && __have_avx512f
1034 		      && (sizeof(_Tp) >= 4 || __have_avx512bw)))
1035       {
1036 	// The ISA can handle wider input registers, so concat and use one-arg
1037 	// implementation. This reduces code duplication considerably.
1038 	return __convert_x86<_To>(__concat(__v0, __v1));
1039       }
1040     else //{{{2
1041       {
1042 	// conversion using bit reinterpretation (or no conversion at all)
1043 	// should all go through the concat branch above:
1044 	static_assert(
1045 	  !(is_floating_point_v<
1046 	      _Tp> == is_floating_point_v<_Up> && sizeof(_Tp) == sizeof(_Up)));
1047 	// handle all zero extension{{{2
1048 	if constexpr (2 * _Np < _M && sizeof(_To) > 16)
1049 	  {
1050 	    constexpr size_t Min = 16 / sizeof(_Up);
1051 	    return __zero_extend(
1052 	      __convert_x86<
1053 		__vector_type_t<_Up, (Min > 2 * _Np) ? Min : 2 * _Np>>(__v0,
1054 								       __v1));
1055 	  }
1056 	else if constexpr (__i64_to_i32) //{{{2
1057 	  {
1058 	    if constexpr (__x_to_x)
1059 	      return __auto_bitcast(_mm_shuffle_ps(__auto_bitcast(__v0),
1060 						   __auto_bitcast(__v1), 0x88));
1061 	    else if constexpr (__y_to_y)
1062 	      {
1063 		// AVX512F is not available (would concat otherwise)
1064 		return __auto_bitcast(
1065 		  __xzyw(_mm256_shuffle_ps(__auto_bitcast(__v0),
1066 					   __auto_bitcast(__v1), 0x88)));
1067 		// alternative:
1068 		// const auto v0_abxxcdxx = _mm256_shuffle_epi32(__v0, 8);
1069 		// const auto v1_efxxghxx = _mm256_shuffle_epi32(__v1, 8);
1070 		// const auto v_abefcdgh = _mm256_unpacklo_epi64(v0_abxxcdxx,
1071 		// v1_efxxghxx); return _mm256_permute4x64_epi64(v_abefcdgh,
1072 		// 0x01 * 0 + 0x04 * 2 + 0x10 * 1 + 0x40 * 3);  // abcdefgh
1073 	      }
1074 	    else if constexpr (__z_to_z)
1075 	      return __intrin_bitcast<_To>(
1076 		__concat(_mm512_cvtepi64_epi32(__i0),
1077 			 _mm512_cvtepi64_epi32(__i1)));
1078 	  }
1079 	else if constexpr (__i64_to_i16) //{{{2
1080 	  {
1081 	    if constexpr (__x_to_x)
1082 	      {
1083 		// AVX2 is not available (would concat otherwise)
1084 		if constexpr (__have_sse4_1)
1085 		  {
1086 		    return __intrin_bitcast<_To>(_mm_shuffle_epi8(
1087 		      _mm_blend_epi16(__i0, _mm_slli_si128(__i1, 4), 0x44),
1088 		      _mm_setr_epi8(0, 1, 8, 9, 4, 5, 12, 13, -0x80, -0x80,
1089 				    -0x80, -0x80, -0x80, -0x80, -0x80, -0x80)));
1090 		  }
1091 		else
1092 		  {
1093 		    return __vector_type_t<_Up, _M>{_Up(__v0[0]), _Up(__v0[1]),
1094 						    _Up(__v1[0]), _Up(__v1[1])};
1095 		  }
1096 	      }
1097 	    else if constexpr (__y_to_x)
1098 	      {
1099 		auto __a
1100 		  = _mm256_unpacklo_epi16(__i0, __i1); // 04.. .... 26.. ....
1101 		auto __b
1102 		  = _mm256_unpackhi_epi16(__i0, __i1); // 15.. .... 37.. ....
1103 		auto __c
1104 		  = _mm256_unpacklo_epi16(__a, __b); // 0145 .... 2367 ....
1105 		return __intrin_bitcast<_To>(
1106 		  _mm_unpacklo_epi32(__lo128(__c), __hi128(__c))); // 0123 4567
1107 	      }
1108 	    else if constexpr (__z_to_y)
1109 	      return __intrin_bitcast<_To>(
1110 		__concat(_mm512_cvtepi64_epi16(__i0),
1111 			 _mm512_cvtepi64_epi16(__i1)));
1112 	  }
1113 	else if constexpr (__i64_to_i8) //{{{2
1114 	  {
1115 	    if constexpr (__x_to_x && __have_sse4_1)
1116 	      {
1117 		return __intrin_bitcast<_To>(_mm_shuffle_epi8(
1118 		  _mm_blend_epi16(__i0, _mm_slli_si128(__i1, 4), 0x44),
1119 		  _mm_setr_epi8(0, 8, 4, 12, -0x80, -0x80, -0x80, -0x80, -0x80,
1120 				-0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
1121 				-0x80)));
1122 	      }
1123 	    else if constexpr (__x_to_x && __have_ssse3)
1124 	      {
1125 		return __intrin_bitcast<_To>(_mm_unpacklo_epi16(
1126 		  _mm_shuffle_epi8(
1127 		    __i0, _mm_setr_epi8(0, 8, -0x80, -0x80, -0x80, -0x80, -0x80,
1128 					-0x80, -0x80, -0x80, -0x80, -0x80,
1129 					-0x80, -0x80, -0x80, -0x80)),
1130 		  _mm_shuffle_epi8(
1131 		    __i1, _mm_setr_epi8(0, 8, -0x80, -0x80, -0x80, -0x80, -0x80,
1132 					-0x80, -0x80, -0x80, -0x80, -0x80,
1133 					-0x80, -0x80, -0x80, -0x80))));
1134 	      }
1135 	    else if constexpr (__x_to_x)
1136 	      {
1137 		return __vector_type_t<_Up, _M>{_Up(__v0[0]), _Up(__v0[1]),
1138 						_Up(__v1[0]), _Up(__v1[1])};
1139 	      }
1140 	    else if constexpr (__y_to_x)
1141 	      {
1142 		const auto __a = _mm256_shuffle_epi8(
1143 		  _mm256_blend_epi32(__i0, _mm256_slli_epi64(__i1, 32), 0xAA),
1144 		  _mm256_setr_epi8(0, 8, -0x80, -0x80, 4, 12, -0x80, -0x80,
1145 				   -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
1146 				   -0x80, -0x80, -0x80, -0x80, 0, 8, -0x80,
1147 				   -0x80, 4, 12, -0x80, -0x80, -0x80, -0x80,
1148 				   -0x80, -0x80, -0x80, -0x80));
1149 		return __intrin_bitcast<_To>(__lo128(__a) | __hi128(__a));
1150 	      } // __z_to_x uses concat fallback
1151 	  }
1152 	else if constexpr (__i32_to_i16) //{{{2
1153 	  {
1154 	    if constexpr (__x_to_x)
1155 	      {
1156 		// AVX2 is not available (would concat otherwise)
1157 		if constexpr (__have_sse4_1)
1158 		  {
1159 		    return __intrin_bitcast<_To>(_mm_shuffle_epi8(
1160 		      _mm_blend_epi16(__i0, _mm_slli_si128(__i1, 2), 0xaa),
1161 		      _mm_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10,
1162 				    11, 14, 15)));
1163 		  }
1164 		else if constexpr (__have_ssse3)
1165 		  {
1166 		    return __intrin_bitcast<_To>(
1167 		      _mm_hadd_epi16(__to_intrin(__v0 << 16),
1168 				     __to_intrin(__v1 << 16)));
1169 		    /*
1170 		    return _mm_unpacklo_epi64(
1171 			_mm_shuffle_epi8(__i0, _mm_setr_epi8(0, 1, 4, 5, 8, 9,
1172 		    12, 13, 8, 9, 12, 13, 12, 13, 14, 15)),
1173 		    _mm_shuffle_epi8(__i1, _mm_setr_epi8(0, 1, 4, 5, 8, 9, 12,
1174 		    13, 8, 9, 12, 13, 12, 13, 14, 15)));
1175 							   */
1176 		  }
1177 		else
1178 		  {
1179 		    auto __a = _mm_unpacklo_epi16(__i0, __i1); // 04.. 15..
1180 		    auto __b = _mm_unpackhi_epi16(__i0, __i1); // 26.. 37..
1181 		    auto __c = _mm_unpacklo_epi16(__a, __b);   // 0246 ....
1182 		    auto __d = _mm_unpackhi_epi16(__a, __b);   // 1357 ....
1183 		    return __intrin_bitcast<_To>(
1184 		      _mm_unpacklo_epi16(__c, __d)); // 0123 4567
1185 		  }
1186 	      }
1187 	    else if constexpr (__y_to_y)
1188 	      {
1189 		const auto __shuf
1190 		  = _mm256_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, -0x80, -0x80,
1191 				     -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
1192 				     0, 1, 4, 5, 8, 9, 12, 13, -0x80, -0x80,
1193 				     -0x80, -0x80, -0x80, -0x80, -0x80, -0x80);
1194 		auto __a = _mm256_shuffle_epi8(__i0, __shuf);
1195 		auto __b = _mm256_shuffle_epi8(__i1, __shuf);
1196 		return __intrin_bitcast<_To>(
1197 		  __xzyw(_mm256_unpacklo_epi64(__a, __b)));
1198 	      } // __z_to_z uses concat fallback
1199 	  }
1200 	else if constexpr (__i32_to_i8) //{{{2
1201 	  {
1202 	    if constexpr (__x_to_x && __have_ssse3)
1203 	      {
1204 		const auto shufmask
1205 		  = _mm_setr_epi8(0, 4, 8, 12, -0x80, -0x80, -0x80, -0x80,
1206 				  -0x80, -0x80, -0x80, -0x80, -0x80, -0x80,
1207 				  -0x80, -0x80);
1208 		return __intrin_bitcast<_To>(
1209 		  _mm_unpacklo_epi32(_mm_shuffle_epi8(__i0, shufmask),
1210 				     _mm_shuffle_epi8(__i1, shufmask)));
1211 	      }
1212 	    else if constexpr (__x_to_x)
1213 	      {
1214 		auto __a = _mm_unpacklo_epi8(__i0, __i1); // 04.. .... 15.. ....
1215 		auto __b = _mm_unpackhi_epi8(__i0, __i1); // 26.. .... 37.. ....
1216 		auto __c = _mm_unpacklo_epi8(__a, __b);   // 0246 .... .... ....
1217 		auto __d = _mm_unpackhi_epi8(__a, __b);   // 1357 .... .... ....
1218 		auto __e = _mm_unpacklo_epi8(__c, __d);   // 0123 4567 .... ....
1219 		return __intrin_bitcast<_To>(__e & __m128i{-1, 0});
1220 	      }
1221 	    else if constexpr (__y_to_x)
1222 	      {
1223 		const auto __a = _mm256_shuffle_epi8(
1224 		  _mm256_blend_epi16(__i0, _mm256_slli_epi32(__i1, 16), 0xAA),
1225 		  _mm256_setr_epi8(0, 4, 8, 12, -0x80, -0x80, -0x80, -0x80, 2,
1226 				   6, 10, 14, -0x80, -0x80, -0x80, -0x80, -0x80,
1227 				   -0x80, -0x80, -0x80, 0, 4, 8, 12, -0x80,
1228 				   -0x80, -0x80, -0x80, 2, 6, 10, 14));
1229 		return __intrin_bitcast<_To>(__lo128(__a) | __hi128(__a));
1230 	      } // __z_to_y uses concat fallback
1231 	  }
1232 	else if constexpr (__i16_to_i8) //{{{2
1233 	  {
1234 	    if constexpr (__x_to_x && __have_ssse3)
1235 	      {
1236 		const auto __shuf = reinterpret_cast<__m128i>(
1237 		  __vector_type_t<_UChar, 16>{0, 2, 4, 6, 8, 10, 12, 14, 0x80,
1238 					      0x80, 0x80, 0x80, 0x80, 0x80,
1239 					      0x80, 0x80});
1240 		return __intrin_bitcast<_To>(
1241 		  _mm_unpacklo_epi64(_mm_shuffle_epi8(__i0, __shuf),
1242 				     _mm_shuffle_epi8(__i1, __shuf)));
1243 	      }
1244 	    else if constexpr (__x_to_x)
1245 	      {
1246 		auto __a = _mm_unpacklo_epi8(__i0, __i1); // 08.. 19.. 2A.. 3B..
1247 		auto __b = _mm_unpackhi_epi8(__i0, __i1); // 4C.. 5D.. 6E.. 7F..
1248 		auto __c = _mm_unpacklo_epi8(__a, __b);   // 048C .... 159D ....
1249 		auto __d = _mm_unpackhi_epi8(__a, __b);   // 26AE .... 37BF ....
1250 		auto __e = _mm_unpacklo_epi8(__c, __d);   // 0246 8ACE .... ....
1251 		auto __f = _mm_unpackhi_epi8(__c, __d);   // 1357 9BDF .... ....
1252 		return __intrin_bitcast<_To>(_mm_unpacklo_epi8(__e, __f));
1253 	      }
1254 	    else if constexpr (__y_to_y)
1255 	      {
1256 		return __intrin_bitcast<_To>(__xzyw(_mm256_shuffle_epi8(
1257 		  (__to_intrin(__v0) & _mm256_set1_epi32(0x00ff00ff))
1258 		    | _mm256_slli_epi16(__i1, 8),
1259 		  _mm256_setr_epi8(0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11,
1260 				   13, 15, 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5,
1261 				   7, 9, 11, 13, 15))));
1262 	      } // __z_to_z uses concat fallback
1263 	  }
1264 	else if constexpr (__i64_to_f32) //{{{2
1265 	  {
1266 	    if constexpr (__x_to_x)
1267 	      return __make_wrapper<float>(__v0[0], __v0[1], __v1[0], __v1[1]);
1268 	    else if constexpr (__y_to_y)
1269 	      {
1270 		static_assert(__y_to_y && __have_avx2);
1271 		const auto __a = _mm256_unpacklo_epi32(__i0, __i1); // aeAE cgCG
1272 		const auto __b = _mm256_unpackhi_epi32(__i0, __i1); // bfBF dhDH
1273 		const auto __lo32
1274 		  = _mm256_unpacklo_epi32(__a, __b); // abef cdgh
1275 		const auto __hi32 = __vector_bitcast<
1276 		  conditional_t<is_signed_v<_Tp>, int, _UInt>>(
1277 		  _mm256_unpackhi_epi32(__a, __b)); // ABEF CDGH
1278 		const auto __hi
1279 		  = 0x100000000LL
1280 		    * __convert_x86<__vector_type_t<float, 8>>(__hi32);
1281 		const auto __mid
1282 		  = 0x10000 * _mm256_cvtepi32_ps(_mm256_srli_epi32(__lo32, 16));
1283 		const auto __lo
1284 		  = _mm256_cvtepi32_ps(_mm256_set1_epi32(0x0000ffffu) & __lo32);
1285 		return __xzyw((__hi + __mid) + __lo);
1286 	      }
1287 	    else if constexpr (__z_to_z && __have_avx512dq)
1288 	      {
1289 		return is_signed_v<_Tp> ? __concat(_mm512_cvtepi64_ps(__i0),
1290 						   _mm512_cvtepi64_ps(__i1))
1291 					: __concat(_mm512_cvtepu64_ps(__i0),
1292 						   _mm512_cvtepu64_ps(__i1));
1293 	      }
1294 	    else if constexpr (__z_to_z && is_signed_v<_Tp>)
1295 	      {
1296 		const __m512 __hi32 = _mm512_cvtepi32_ps(
1297 		  __concat(_mm512_cvtepi64_epi32(__to_intrin(__v0 >> 32)),
1298 			   _mm512_cvtepi64_epi32(__to_intrin(__v1 >> 32))));
1299 		const __m512i __lo32 = __concat(_mm512_cvtepi64_epi32(__i0),
1300 						_mm512_cvtepi64_epi32(__i1));
1301 		// split low 32-bits, because if __hi32 is a small negative
1302 		// number, the 24-bit mantissa may lose important information if
1303 		// any of the high 8 bits of __lo32 is set, leading to
1304 		// catastrophic cancelation in the FMA
1305 		const __m512 __hi16
1306 		  = _mm512_cvtepu32_ps(_mm512_set1_epi32(0xffff0000u) & __lo32);
1307 		const __m512 __lo16
1308 		  = _mm512_cvtepi32_ps(_mm512_set1_epi32(0x0000ffffu) & __lo32);
1309 		return (__hi32 * 0x100000000LL + __hi16) + __lo16;
1310 	      }
1311 	    else if constexpr (__z_to_z && is_unsigned_v<_Tp>)
1312 	      {
1313 		return __intrin_bitcast<_To>(
1314 		  _mm512_cvtepu32_ps(__concat(
1315 		    _mm512_cvtepi64_epi32(_mm512_srai_epi64(__i0, 32)),
1316 		    _mm512_cvtepi64_epi32(_mm512_srai_epi64(__i1, 32))))
1317 		    * 0x100000000LL
1318 		  + _mm512_cvtepu32_ps(__concat(_mm512_cvtepi64_epi32(__i0),
1319 						_mm512_cvtepi64_epi32(__i1))));
1320 	      }
1321 	  }
1322 	else if constexpr (__f64_to_s32) //{{{2
1323 	  {
1324 	    // use concat fallback
1325 	  }
1326 	else if constexpr (__f64_to_u32) //{{{2
1327 	  {
1328 	    if constexpr (__x_to_x && __have_sse4_1)
1329 	      {
1330 		return __vector_bitcast<_Up, _M>(_mm_unpacklo_epi64(
1331 			 _mm_cvttpd_epi32(_mm_floor_pd(__i0) - 0x8000'0000u),
1332 			 _mm_cvttpd_epi32(_mm_floor_pd(__i1) - 0x8000'0000u)))
1333 		       ^ 0x8000'0000u;
1334 		// without SSE4.1 just use the scalar fallback, it's only four
1335 		// values
1336 	      }
1337 	    else if constexpr (__y_to_y)
1338 	      {
1339 		return __vector_bitcast<_Up>(
1340 			 __concat(_mm256_cvttpd_epi32(_mm256_floor_pd(__i0)
1341 						      - 0x8000'0000u),
1342 				  _mm256_cvttpd_epi32(_mm256_floor_pd(__i1)
1343 						      - 0x8000'0000u)))
1344 		       ^ 0x8000'0000u;
1345 	      } // __z_to_z uses fallback
1346 	  }
1347 	else if constexpr (__f64_to_ibw) //{{{2
1348 	  {
1349 	    // one-arg __f64_to_ibw goes via _SimdWrapper<int, ?>. The fallback
1350 	    // would go via two independet conversions to _SimdWrapper<_To> and
1351 	    // subsequent interleaving. This is better, because f64->__i32
1352 	    // allows to combine __v0 and __v1 into one register: if constexpr
1353 	    // (__z_to_x || __y_to_x) {
1354 	    return __convert_x86<_To>(
1355 	      __convert_x86<__vector_type_t<int, _Np * 2>>(__v0, __v1));
1356 	    //}
1357 	  }
1358 	else if constexpr (__f32_to_ibw) //{{{2
1359 	  {
1360 	    return __convert_x86<_To>(
1361 	      __convert_x86<__vector_type_t<int, _Np>>(__v0),
1362 	      __convert_x86<__vector_type_t<int, _Np>>(__v1));
1363 	  } //}}}
1364 
1365 	// fallback: {{{2
1366 	if constexpr (sizeof(_To) >= 32)
1367 	  // if _To is ymm or zmm, then _SimdWrapper<_Up, _M / 2> is xmm or ymm
1368 	  return __concat(__convert_x86<__vector_type_t<_Up, _M / 2>>(__v0),
1369 			  __convert_x86<__vector_type_t<_Up, _M / 2>>(__v1));
1370 	else if constexpr (sizeof(_To) == 16)
1371 	  {
1372 	    const auto __lo = __to_intrin(__convert_x86<_To>(__v0));
1373 	    const auto __hi = __to_intrin(__convert_x86<_To>(__v1));
1374 	    if constexpr (sizeof(_Up) * _Np == 8)
1375 	      {
1376 		if constexpr (is_floating_point_v<_Up>)
1377 		  return __auto_bitcast(
1378 		    _mm_unpacklo_pd(__vector_bitcast<double>(__lo),
1379 				    __vector_bitcast<double>(__hi)));
1380 		else
1381 		  return __intrin_bitcast<_To>(_mm_unpacklo_epi64(__lo, __hi));
1382 	      }
1383 	    else if constexpr (sizeof(_Up) * _Np == 4)
1384 	      {
1385 		if constexpr (is_floating_point_v<_Up>)
1386 		  return __auto_bitcast(
1387 		    _mm_unpacklo_ps(__vector_bitcast<float>(__lo),
1388 				    __vector_bitcast<float>(__hi)));
1389 		else
1390 		  return __intrin_bitcast<_To>(_mm_unpacklo_epi32(__lo, __hi));
1391 	      }
1392 	    else if constexpr (sizeof(_Up) * _Np == 2)
1393 	      return __intrin_bitcast<_To>(_mm_unpacklo_epi16(__lo, __hi));
1394 	    else
1395 	      __assert_unreachable<_Tp>();
1396 	  }
1397 	else
1398 	  return __vector_convert<_To>(__v0, __v1, make_index_sequence<_Np>());
1399 	//}}}
1400       }
1401   }
1402 
1403 //}}}1
1404 // 4-arg __convert_x86 {{{1
1405 template <typename _To, typename _V, typename _Traits>
1406   _GLIBCXX_SIMD_INTRINSIC _To
1407   __convert_x86(_V __v0, _V __v1, _V __v2, _V __v3)
1408   {
1409     static_assert(__is_vector_type_v<_V>);
1410     using _Tp = typename _Traits::value_type;
1411     constexpr size_t _Np = _Traits::_S_full_size;
1412     [[maybe_unused]] const auto __i0 = __to_intrin(__v0);
1413     [[maybe_unused]] const auto __i1 = __to_intrin(__v1);
1414     [[maybe_unused]] const auto __i2 = __to_intrin(__v2);
1415     [[maybe_unused]] const auto __i3 = __to_intrin(__v3);
1416     using _Up = typename _VectorTraits<_To>::value_type;
1417     constexpr size_t _M = _VectorTraits<_To>::_S_full_size;
1418 
1419     static_assert(4 * _Np <= _M,
1420 		  "__v2/__v3 would be discarded; use the two/one-argument "
1421 		  "__convert_x86 overload instead");
1422 
1423     // [xyz]_to_[xyz] {{{2
1424     [[maybe_unused]] constexpr bool __x_to_x
1425       = sizeof(__v0) <= 16 && sizeof(_To) <= 16;
1426     [[maybe_unused]] constexpr bool __x_to_y
1427       = sizeof(__v0) <= 16 && sizeof(_To) == 32;
1428     [[maybe_unused]] constexpr bool __x_to_z
1429       = sizeof(__v0) <= 16 && sizeof(_To) == 64;
1430     [[maybe_unused]] constexpr bool __y_to_x
1431       = sizeof(__v0) == 32 && sizeof(_To) <= 16;
1432     [[maybe_unused]] constexpr bool __y_to_y
1433       = sizeof(__v0) == 32 && sizeof(_To) == 32;
1434     [[maybe_unused]] constexpr bool __y_to_z
1435       = sizeof(__v0) == 32 && sizeof(_To) == 64;
1436     [[maybe_unused]] constexpr bool __z_to_x
1437       = sizeof(__v0) == 64 && sizeof(_To) <= 16;
1438     [[maybe_unused]] constexpr bool __z_to_y
1439       = sizeof(__v0) == 64 && sizeof(_To) == 32;
1440     [[maybe_unused]] constexpr bool __z_to_z
1441       = sizeof(__v0) == 64 && sizeof(_To) == 64;
1442 
1443     // iX_to_iX {{{2
1444     [[maybe_unused]] constexpr bool __i_to_i
1445       = is_integral_v<_Up> && is_integral_v<_Tp>;
1446     [[maybe_unused]] constexpr bool __i8_to_i16
1447       = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 2;
1448     [[maybe_unused]] constexpr bool __i8_to_i32
1449       = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 4;
1450     [[maybe_unused]] constexpr bool __i8_to_i64
1451       = __i_to_i && sizeof(_Tp) == 1 && sizeof(_Up) == 8;
1452     [[maybe_unused]] constexpr bool __i16_to_i8
1453       = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 1;
1454     [[maybe_unused]] constexpr bool __i16_to_i32
1455       = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 4;
1456     [[maybe_unused]] constexpr bool __i16_to_i64
1457       = __i_to_i && sizeof(_Tp) == 2 && sizeof(_Up) == 8;
1458     [[maybe_unused]] constexpr bool __i32_to_i8
1459       = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 1;
1460     [[maybe_unused]] constexpr bool __i32_to_i16
1461       = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 2;
1462     [[maybe_unused]] constexpr bool __i32_to_i64
1463       = __i_to_i && sizeof(_Tp) == 4 && sizeof(_Up) == 8;
1464     [[maybe_unused]] constexpr bool __i64_to_i8
1465       = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 1;
1466     [[maybe_unused]] constexpr bool __i64_to_i16
1467       = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 2;
1468     [[maybe_unused]] constexpr bool __i64_to_i32
1469       = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 4;
1470 
1471     // [fsu]X_to_[fsu]X {{{2
1472     // ibw = integral && byte or word, i.e. char and short with any signedness
1473     [[maybe_unused]] constexpr bool __i64_to_f32
1474       = is_integral_v<_Tp> && sizeof(_Tp) == 8
1475 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
1476     [[maybe_unused]] constexpr bool __s32_to_f32
1477       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
1478 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
1479     [[maybe_unused]] constexpr bool __s16_to_f32
1480       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 2
1481 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
1482     [[maybe_unused]] constexpr bool __s8_to_f32
1483       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 1
1484 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
1485     [[maybe_unused]] constexpr bool __u32_to_f32
1486       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
1487 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
1488     [[maybe_unused]] constexpr bool __u16_to_f32
1489       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 2
1490 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
1491     [[maybe_unused]] constexpr bool __u8_to_f32
1492       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 1
1493 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
1494     [[maybe_unused]] constexpr bool __s64_to_f64
1495       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 8
1496 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
1497     [[maybe_unused]] constexpr bool __s32_to_f64
1498       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 4
1499 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
1500     [[maybe_unused]] constexpr bool __s16_to_f64
1501       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 2
1502 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
1503     [[maybe_unused]] constexpr bool __s8_to_f64
1504       = is_integral_v<_Tp> && is_signed_v<_Tp> && sizeof(_Tp) == 1
1505 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
1506     [[maybe_unused]] constexpr bool __u64_to_f64
1507       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 8
1508 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
1509     [[maybe_unused]] constexpr bool __u32_to_f64
1510       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 4
1511 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
1512     [[maybe_unused]] constexpr bool __u16_to_f64
1513       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 2
1514 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
1515     [[maybe_unused]] constexpr bool __u8_to_f64
1516       = is_integral_v<_Tp> && is_unsigned_v<_Tp> && sizeof(_Tp) == 1
1517 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
1518     [[maybe_unused]] constexpr bool __f32_to_s64
1519       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
1520 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
1521     [[maybe_unused]] constexpr bool __f32_to_s32
1522       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
1523 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
1524     [[maybe_unused]] constexpr bool __f32_to_u64
1525       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
1526 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
1527     [[maybe_unused]] constexpr bool __f32_to_u32
1528       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
1529 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
1530     [[maybe_unused]] constexpr bool __f64_to_s64
1531       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 8
1532 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
1533     [[maybe_unused]] constexpr bool __f64_to_s32
1534       = is_integral_v<_Up> && is_signed_v<_Up> && sizeof(_Up) == 4
1535 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
1536     [[maybe_unused]] constexpr bool __f64_to_u64
1537       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 8
1538 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
1539     [[maybe_unused]] constexpr bool __f64_to_u32
1540       = is_integral_v<_Up> && is_unsigned_v<_Up> && sizeof(_Up) == 4
1541 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
1542     [[maybe_unused]] constexpr bool __f32_to_ibw
1543       = is_integral_v<_Up> && sizeof(_Up) <= 2
1544 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 4;
1545     [[maybe_unused]] constexpr bool __f64_to_ibw
1546       = is_integral_v<_Up> && sizeof(_Up) <= 2
1547 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
1548     [[maybe_unused]] constexpr bool __f32_to_f64
1549       = is_floating_point_v<_Tp> && sizeof(_Tp) == 4
1550 	&& is_floating_point_v<_Up> && sizeof(_Up) == 8;
1551     [[maybe_unused]] constexpr bool __f64_to_f32
1552       = is_floating_point_v<_Tp> && sizeof(_Tp) == 8
1553 	&& is_floating_point_v<_Up> && sizeof(_Up) == 4;
1554 
1555     if constexpr (__i_to_i && __y_to_x && !__have_avx2) //{{{2
1556       {
1557 	// <double, 4>, <double, 4>, <double, 4>, <double, 4> => <char, 16>
1558 	return __convert_x86<_To>(__lo128(__v0), __hi128(__v0), __lo128(__v1),
1559 				  __hi128(__v1), __lo128(__v2), __hi128(__v2),
1560 				  __lo128(__v3), __hi128(__v3));
1561       }
1562     else if constexpr (__i_to_i) // assert ISA {{{2
1563       {
1564 	static_assert(__x_to_x || __have_avx2,
1565 		      "integral conversions with ymm registers require AVX2");
1566 	static_assert(__have_avx512bw
1567 			|| ((sizeof(_Tp) >= 4 || sizeof(__v0) < 64)
1568 			    && (sizeof(_Up) >= 4 || sizeof(_To) < 64)),
1569 		      "8/16-bit integers in zmm registers require AVX512BW");
1570 	static_assert((sizeof(__v0) < 64 && sizeof(_To) < 64) || __have_avx512f,
1571 		      "integral conversions with ymm registers require AVX2");
1572       }
1573     // concat => use 2-arg __convert_x86 {{{2
1574     if constexpr (sizeof(__v0) < 16 || (sizeof(__v0) == 16 && __have_avx2)
1575 		  || (sizeof(__v0) == 16 && __have_avx
1576 		      && is_floating_point_v<_Tp>)
1577 		  || (sizeof(__v0) == 32 && __have_avx512f))
1578       {
1579 	// The ISA can handle wider input registers, so concat and use two-arg
1580 	// implementation. This reduces code duplication considerably.
1581 	return __convert_x86<_To>(__concat(__v0, __v1), __concat(__v2, __v3));
1582       }
1583     else //{{{2
1584       {
1585 	// conversion using bit reinterpretation (or no conversion at all)
1586 	// should all go through the concat branch above:
1587 	static_assert(
1588 	  !(is_floating_point_v<
1589 	      _Tp> == is_floating_point_v<_Up> && sizeof(_Tp) == sizeof(_Up)));
1590 	// handle all zero extension{{{2
1591 	if constexpr (4 * _Np < _M && sizeof(_To) > 16)
1592 	  {
1593 	    constexpr size_t Min = 16 / sizeof(_Up);
1594 	    return __zero_extend(
1595 	      __convert_x86<
1596 		__vector_type_t<_Up, (Min > 4 * _Np) ? Min : 4 * _Np>>(
1597 		__v0, __v1, __v2, __v3));
1598 	  }
1599 	else if constexpr (__i64_to_i16) //{{{2
1600 	  {
1601 	    if constexpr (__x_to_x && __have_sse4_1)
1602 	      {
1603 		return __intrin_bitcast<_To>(_mm_shuffle_epi8(
1604 		  _mm_blend_epi16(
1605 		    _mm_blend_epi16(__i0, _mm_slli_si128(__i1, 2), 0x22),
1606 		    _mm_blend_epi16(_mm_slli_si128(__i2, 4),
1607 				    _mm_slli_si128(__i3, 6), 0x88),
1608 		    0xcc),
1609 		  _mm_setr_epi8(0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7,
1610 				14, 15)));
1611 	      }
1612 	    else if constexpr (__y_to_y && __have_avx2)
1613 	      {
1614 		return __intrin_bitcast<_To>(_mm256_shuffle_epi8(
1615 		  __xzyw(_mm256_blend_epi16(
1616 		    __auto_bitcast(
1617 		      _mm256_shuffle_ps(__vector_bitcast<float>(__v0),
1618 					__vector_bitcast<float>(__v2),
1619 					0x88)), // 0.1. 8.9. 2.3. A.B.
1620 		    __to_intrin(__vector_bitcast<int>(_mm256_shuffle_ps(
1621 				  __vector_bitcast<float>(__v1),
1622 				  __vector_bitcast<float>(__v3), 0x88))
1623 				<< 16), // .4.5 .C.D .6.7 .E.F
1624 		    0xaa)               // 0415 8C9D 2637 AEBF
1625 			 ),             // 0415 2637 8C9D AEBF
1626 		  _mm256_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11,
1627 				   14, 15, 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7,
1628 				   10, 11, 14, 15)));
1629 		/*
1630 		auto __a = _mm256_unpacklo_epi16(__v0, __v1);  // 04.. .... 26..
1631 		.... auto __b = _mm256_unpackhi_epi16(__v0, __v1);  // 15..
1632 		.... 37.. .... auto __c = _mm256_unpacklo_epi16(__v2, __v3);  //
1633 		8C.. .... AE.. .... auto __d = _mm256_unpackhi_epi16(__v2,
1634 		__v3);
1635 		// 9D.. .... BF.. .... auto __e = _mm256_unpacklo_epi16(__a,
1636 		__b);
1637 		// 0145 .... 2367 .... auto __f = _mm256_unpacklo_epi16(__c,
1638 		__d);
1639 		// 89CD .... ABEF .... auto __g = _mm256_unpacklo_epi64(__e,
1640 		__f);
1641 		// 0145 89CD 2367 ABEF return __concat(
1642 		    _mm_unpacklo_epi32(__lo128(__g), __hi128(__g)),
1643 		    _mm_unpackhi_epi32(__lo128(__g), __hi128(__g)));  // 0123
1644 		4567 89AB CDEF
1645 		    */
1646 	      } // else use fallback
1647 	  }
1648 	else if constexpr (__i64_to_i8) //{{{2
1649 	  {
1650 	    if constexpr (__x_to_x)
1651 	      {
1652 		// TODO: use fallback for now
1653 	      }
1654 	    else if constexpr (__y_to_x)
1655 	      {
1656 		auto __a
1657 		  = _mm256_srli_epi32(_mm256_slli_epi32(__i0, 24), 24)
1658 		    | _mm256_srli_epi32(_mm256_slli_epi32(__i1, 24), 16)
1659 		    | _mm256_srli_epi32(_mm256_slli_epi32(__i2, 24), 8)
1660 		    | _mm256_slli_epi32(
1661 		      __i3, 24); // 048C .... 159D .... 26AE .... 37BF ....
1662 		/*return _mm_shuffle_epi8(
1663 		    _mm_blend_epi32(__lo128(__a) << 32, __hi128(__a), 0x5),
1664 		    _mm_setr_epi8(4, 12, 0, 8, 5, 13, 1, 9, 6, 14, 2, 10, 7, 15,
1665 		   3, 11));*/
1666 		auto __b = _mm256_unpackhi_epi64(
1667 		  __a, __a); // 159D .... 159D .... 37BF .... 37BF ....
1668 		auto __c = _mm256_unpacklo_epi8(
1669 		  __a, __b); // 0145 89CD .... .... 2367 ABEF .... ....
1670 		return __intrin_bitcast<_To>(
1671 		  _mm_unpacklo_epi16(__lo128(__c),
1672 				     __hi128(__c))); // 0123 4567 89AB CDEF
1673 	      }
1674 	  }
1675 	else if constexpr (__i32_to_i8) //{{{2
1676 	  {
1677 	    if constexpr (__x_to_x)
1678 	      {
1679 		if constexpr (__have_ssse3)
1680 		  {
1681 		    const auto __x0 = __vector_bitcast<_UInt>(__v0) & 0xff;
1682 		    const auto __x1 = (__vector_bitcast<_UInt>(__v1) & 0xff)
1683 				      << 8;
1684 		    const auto __x2 = (__vector_bitcast<_UInt>(__v2) & 0xff)
1685 				      << 16;
1686 		    const auto __x3 = __vector_bitcast<_UInt>(__v3) << 24;
1687 		    return __intrin_bitcast<_To>(
1688 		      _mm_shuffle_epi8(__to_intrin(__x0 | __x1 | __x2 | __x3),
1689 				       _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13,
1690 						     2, 6, 10, 14, 3, 7, 11,
1691 						     15)));
1692 		  }
1693 		else
1694 		  {
1695 		    auto __a
1696 		      = _mm_unpacklo_epi8(__i0, __i2); // 08.. .... 19.. ....
1697 		    auto __b
1698 		      = _mm_unpackhi_epi8(__i0, __i2); // 2A.. .... 3B.. ....
1699 		    auto __c
1700 		      = _mm_unpacklo_epi8(__i1, __i3); // 4C.. .... 5D.. ....
1701 		    auto __d
1702 		      = _mm_unpackhi_epi8(__i1, __i3); // 6E.. .... 7F.. ....
1703 		    auto __e
1704 		      = _mm_unpacklo_epi8(__a, __c); // 048C .... .... ....
1705 		    auto __f
1706 		      = _mm_unpackhi_epi8(__a, __c); // 159D .... .... ....
1707 		    auto __g
1708 		      = _mm_unpacklo_epi8(__b, __d); // 26AE .... .... ....
1709 		    auto __h
1710 		      = _mm_unpackhi_epi8(__b, __d); // 37BF .... .... ....
1711 		    return __intrin_bitcast<_To>(_mm_unpacklo_epi8(
1712 		      _mm_unpacklo_epi8(__e, __g), // 0246 8ACE .... ....
1713 		      _mm_unpacklo_epi8(__f, __h)  // 1357 9BDF .... ....
1714 		      ));                          // 0123 4567 89AB CDEF
1715 		  }
1716 	      }
1717 	    else if constexpr (__y_to_y)
1718 	      {
1719 		const auto __a = _mm256_shuffle_epi8(
1720 		  __to_intrin((__vector_bitcast<_UShort>(_mm256_blend_epi16(
1721 				 __i0, _mm256_slli_epi32(__i1, 16), 0xAA))
1722 			       & 0xff)
1723 			      | (__vector_bitcast<_UShort>(_mm256_blend_epi16(
1724 				   __i2, _mm256_slli_epi32(__i3, 16), 0xAA))
1725 				 << 8)),
1726 		  _mm256_setr_epi8(0, 4, 8, 12, 2, 6, 10, 14, 1, 5, 9, 13, 3, 7,
1727 				   11, 15, 0, 4, 8, 12, 2, 6, 10, 14, 1, 5, 9,
1728 				   13, 3, 7, 11, 15));
1729 		return __intrin_bitcast<_To>(_mm256_permutevar8x32_epi32(
1730 		  __a, _mm256_setr_epi32(0, 4, 1, 5, 2, 6, 3, 7)));
1731 	      }
1732 	  }
1733 	else if constexpr (__i64_to_f32) //{{{2
1734 	  {
1735 	    // this branch is only relevant with AVX and w/o AVX2 (i.e. no ymm
1736 	    // integers)
1737 	    if constexpr (__x_to_y)
1738 	      {
1739 		return __make_wrapper<float>(__v0[0], __v0[1], __v1[0], __v1[1],
1740 					     __v2[0], __v2[1], __v3[0],
1741 					     __v3[1]);
1742 
1743 		const auto __a = _mm_unpacklo_epi32(__i0, __i1);   // acAC
1744 		const auto __b = _mm_unpackhi_epi32(__i0, __i1);   // bdBD
1745 		const auto __c = _mm_unpacklo_epi32(__i2, __i3);   // egEG
1746 		const auto __d = _mm_unpackhi_epi32(__i2, __i3);   // fhFH
1747 		const auto __lo32a = _mm_unpacklo_epi32(__a, __b); // abcd
1748 		const auto __lo32b = _mm_unpacklo_epi32(__c, __d); // efgh
1749 		const auto __hi32 = __vector_bitcast<
1750 		  conditional_t<is_signed_v<_Tp>, int, _UInt>>(
1751 		  __concat(_mm_unpackhi_epi32(__a, __b),
1752 			   _mm_unpackhi_epi32(__c, __d))); // ABCD EFGH
1753 		const auto __hi
1754 		  = 0x100000000LL
1755 		    * __convert_x86<__vector_type_t<float, 8>>(__hi32);
1756 		const auto __mid
1757 		  = 0x10000
1758 		    * _mm256_cvtepi32_ps(__concat(_mm_srli_epi32(__lo32a, 16),
1759 						  _mm_srli_epi32(__lo32b, 16)));
1760 		const auto __lo = _mm256_cvtepi32_ps(
1761 		  __concat(_mm_set1_epi32(0x0000ffffu) & __lo32a,
1762 			   _mm_set1_epi32(0x0000ffffu) & __lo32b));
1763 		return (__hi + __mid) + __lo;
1764 	      }
1765 	  }
1766 	else if constexpr (__f64_to_ibw) //{{{2
1767 	  {
1768 	    return __convert_x86<_To>(
1769 	      __convert_x86<__vector_type_t<int, _Np * 2>>(__v0, __v1),
1770 	      __convert_x86<__vector_type_t<int, _Np * 2>>(__v2, __v3));
1771 	  }
1772 	else if constexpr (__f32_to_ibw) //{{{2
1773 	  {
1774 	    return __convert_x86<_To>(
1775 	      __convert_x86<__vector_type_t<int, _Np>>(__v0),
1776 	      __convert_x86<__vector_type_t<int, _Np>>(__v1),
1777 	      __convert_x86<__vector_type_t<int, _Np>>(__v2),
1778 	      __convert_x86<__vector_type_t<int, _Np>>(__v3));
1779 	  } //}}}
1780 
1781 	// fallback: {{{2
1782 	if constexpr (sizeof(_To) >= 32)
1783 	  // if _To is ymm or zmm, then _SimdWrapper<_Up, _M / 2> is xmm or ymm
1784 	  return __concat(__convert_x86<__vector_type_t<_Up, _M / 2>>(__v0,
1785 								      __v1),
1786 			  __convert_x86<__vector_type_t<_Up, _M / 2>>(__v2,
1787 								      __v3));
1788 	else if constexpr (sizeof(_To) == 16)
1789 	  {
1790 	    const auto __lo = __to_intrin(__convert_x86<_To>(__v0, __v1));
1791 	    const auto __hi = __to_intrin(__convert_x86<_To>(__v2, __v3));
1792 	    if constexpr (sizeof(_Up) * _Np * 2 == 8)
1793 	      {
1794 		if constexpr (is_floating_point_v<_Up>)
1795 		  return __auto_bitcast(_mm_unpacklo_pd(__lo, __hi));
1796 		else
1797 		  return __intrin_bitcast<_To>(_mm_unpacklo_epi64(__lo, __hi));
1798 	      }
1799 	    else if constexpr (sizeof(_Up) * _Np * 2 == 4)
1800 	      {
1801 		if constexpr (is_floating_point_v<_Up>)
1802 		  return __auto_bitcast(_mm_unpacklo_ps(__lo, __hi));
1803 		else
1804 		  return __intrin_bitcast<_To>(_mm_unpacklo_epi32(__lo, __hi));
1805 	      }
1806 	    else
1807 	      __assert_unreachable<_Tp>();
1808 	  }
1809 	else
1810 	  return __vector_convert<_To>(__v0, __v1, __v2, __v3,
1811 				       make_index_sequence<_Np>());
1812 	//}}}2
1813       }
1814   }
1815 
1816 //}}}
1817 // 8-arg __convert_x86 {{{1
1818 template <typename _To, typename _V, typename _Traits>
1819   _GLIBCXX_SIMD_INTRINSIC _To
1820   __convert_x86(_V __v0, _V __v1, _V __v2, _V __v3, _V __v4, _V __v5, _V __v6,
1821 		_V __v7)
1822   {
1823     static_assert(__is_vector_type_v<_V>);
1824     using _Tp = typename _Traits::value_type;
1825     constexpr size_t _Np = _Traits::_S_full_size;
1826     [[maybe_unused]] const auto __i0 = __to_intrin(__v0);
1827     [[maybe_unused]] const auto __i1 = __to_intrin(__v1);
1828     [[maybe_unused]] const auto __i2 = __to_intrin(__v2);
1829     [[maybe_unused]] const auto __i3 = __to_intrin(__v3);
1830     [[maybe_unused]] const auto __i4 = __to_intrin(__v4);
1831     [[maybe_unused]] const auto __i5 = __to_intrin(__v5);
1832     [[maybe_unused]] const auto __i6 = __to_intrin(__v6);
1833     [[maybe_unused]] const auto __i7 = __to_intrin(__v7);
1834     using _Up = typename _VectorTraits<_To>::value_type;
1835     constexpr size_t _M = _VectorTraits<_To>::_S_full_size;
1836 
1837     static_assert(8 * _Np <= _M,
1838 		  "__v4-__v7 would be discarded; use the four/two/one-argument "
1839 		  "__convert_x86 overload instead");
1840 
1841     // [xyz]_to_[xyz] {{{2
1842     [[maybe_unused]] constexpr bool __x_to_x
1843       = sizeof(__v0) <= 16 && sizeof(_To) <= 16;
1844     [[maybe_unused]] constexpr bool __x_to_y
1845       = sizeof(__v0) <= 16 && sizeof(_To) == 32;
1846     [[maybe_unused]] constexpr bool __x_to_z
1847       = sizeof(__v0) <= 16 && sizeof(_To) == 64;
1848     [[maybe_unused]] constexpr bool __y_to_x
1849       = sizeof(__v0) == 32 && sizeof(_To) <= 16;
1850     [[maybe_unused]] constexpr bool __y_to_y
1851       = sizeof(__v0) == 32 && sizeof(_To) == 32;
1852     [[maybe_unused]] constexpr bool __y_to_z
1853       = sizeof(__v0) == 32 && sizeof(_To) == 64;
1854     [[maybe_unused]] constexpr bool __z_to_x
1855       = sizeof(__v0) == 64 && sizeof(_To) <= 16;
1856     [[maybe_unused]] constexpr bool __z_to_y
1857       = sizeof(__v0) == 64 && sizeof(_To) == 32;
1858     [[maybe_unused]] constexpr bool __z_to_z
1859       = sizeof(__v0) == 64 && sizeof(_To) == 64;
1860 
1861     // [if]X_to_i8 {{{2
1862     [[maybe_unused]] constexpr bool __i_to_i
1863       = is_integral_v<_Up> && is_integral_v<_Tp>;
1864     [[maybe_unused]] constexpr bool __i64_to_i8
1865       = __i_to_i && sizeof(_Tp) == 8 && sizeof(_Up) == 1;
1866     [[maybe_unused]] constexpr bool __f64_to_i8
1867       = is_integral_v<_Up> && sizeof(_Up) == 1
1868 	&& is_floating_point_v<_Tp> && sizeof(_Tp) == 8;
1869 
1870     if constexpr (__i_to_i) // assert ISA {{{2
1871       {
1872 	static_assert(__x_to_x || __have_avx2,
1873 		      "integral conversions with ymm registers require AVX2");
1874 	static_assert(__have_avx512bw
1875 			|| ((sizeof(_Tp) >= 4 || sizeof(__v0) < 64)
1876 			    && (sizeof(_Up) >= 4 || sizeof(_To) < 64)),
1877 		      "8/16-bit integers in zmm registers require AVX512BW");
1878 	static_assert((sizeof(__v0) < 64 && sizeof(_To) < 64) || __have_avx512f,
1879 		      "integral conversions with ymm registers require AVX2");
1880       }
1881     // concat => use 4-arg __convert_x86 {{{2
1882     if constexpr (sizeof(__v0) < 16 || (sizeof(__v0) == 16 && __have_avx2)
1883 		  || (sizeof(__v0) == 16 && __have_avx
1884 		      && is_floating_point_v<_Tp>)
1885 		  || (sizeof(__v0) == 32 && __have_avx512f))
1886       {
1887 	// The ISA can handle wider input registers, so concat and use two-arg
1888 	// implementation. This reduces code duplication considerably.
1889 	return __convert_x86<_To>(__concat(__v0, __v1), __concat(__v2, __v3),
1890 				  __concat(__v4, __v5), __concat(__v6, __v7));
1891       }
1892     else //{{{2
1893       {
1894 	// conversion using bit reinterpretation (or no conversion at all)
1895 	// should all go through the concat branch above:
1896 	static_assert(
1897 	  !(is_floating_point_v<
1898 	      _Tp> == is_floating_point_v<_Up> && sizeof(_Tp) == sizeof(_Up)));
1899 	static_assert(!(8 * _Np < _M && sizeof(_To) > 16),
1900 		      "zero extension should be impossible");
1901 	if constexpr (__i64_to_i8) //{{{2
1902 	  {
1903 	    if constexpr (__x_to_x && __have_ssse3)
1904 	      {
1905 		// unsure whether this is better than the variant below
1906 		return __intrin_bitcast<_To>(_mm_shuffle_epi8(
1907 		  __to_intrin(
1908 		    (((__v0 & 0xff) | ((__v1 & 0xff) << 8))
1909 		     | (((__v2 & 0xff) << 16) | ((__v3 & 0xff) << 24)))
1910 		    | ((((__v4 & 0xff) << 32) | ((__v5 & 0xff) << 40))
1911 		       | (((__v6 & 0xff) << 48) | (__v7 << 56)))),
1912 		  _mm_setr_epi8(0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14,
1913 				7, 15)));
1914 	      }
1915 	    else if constexpr (__x_to_x)
1916 	      {
1917 		const auto __a = _mm_unpacklo_epi8(__i0, __i1); // ac
1918 		const auto __b = _mm_unpackhi_epi8(__i0, __i1); // bd
1919 		const auto __c = _mm_unpacklo_epi8(__i2, __i3); // eg
1920 		const auto __d = _mm_unpackhi_epi8(__i2, __i3); // fh
1921 		const auto __e = _mm_unpacklo_epi8(__i4, __i5); // ik
1922 		const auto __f = _mm_unpackhi_epi8(__i4, __i5); // jl
1923 		const auto __g = _mm_unpacklo_epi8(__i6, __i7); // mo
1924 		const auto __h = _mm_unpackhi_epi8(__i6, __i7); // np
1925 		return __intrin_bitcast<_To>(_mm_unpacklo_epi64(
1926 		  _mm_unpacklo_epi32(_mm_unpacklo_epi8(__a, __b),  // abcd
1927 				     _mm_unpacklo_epi8(__c, __d)), // efgh
1928 		  _mm_unpacklo_epi32(_mm_unpacklo_epi8(__e, __f),  // ijkl
1929 				     _mm_unpacklo_epi8(__g, __h))  // mnop
1930 		  ));
1931 	      }
1932 	    else if constexpr (__y_to_y)
1933 	      {
1934 		auto __a = // 048C GKOS 159D HLPT 26AE IMQU 37BF JNRV
1935 		  __to_intrin(
1936 		    (((__v0 & 0xff) | ((__v1 & 0xff) << 8))
1937 		     | (((__v2 & 0xff) << 16) | ((__v3 & 0xff) << 24)))
1938 		    | ((((__v4 & 0xff) << 32) | ((__v5 & 0xff) << 40))
1939 		       | (((__v6 & 0xff) << 48) | ((__v7 << 56)))));
1940 		/*
1941 		auto __b = _mm256_unpackhi_epi64(__a, __a);  // 159D HLPT 159D
1942 		HLPT 37BF JNRV 37BF JNRV auto __c = _mm256_unpacklo_epi8(__a,
1943 		__b);  // 0145 89CD GHKL OPST 2367 ABEF IJMN QRUV auto __d =
1944 		__xzyw(__c); // 0145 89CD 2367 ABEF GHKL OPST IJMN QRUV return
1945 		_mm256_shuffle_epi8(
1946 		    __d, _mm256_setr_epi8(0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12,
1947 		13, 6, 7, 14, 15, 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7,
1948 		14, 15));
1949 					*/
1950 		auto __b = _mm256_shuffle_epi8( // 0145 89CD GHKL OPST 2367 ABEF
1951 						// IJMN QRUV
1952 		  __a, _mm256_setr_epi8(0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13,
1953 					6, 14, 7, 15, 0, 8, 1, 9, 2, 10, 3, 11,
1954 					4, 12, 5, 13, 6, 14, 7, 15));
1955 		auto __c
1956 		  = __xzyw(__b); // 0145 89CD 2367 ABEF GHKL OPST IJMN QRUV
1957 		return __intrin_bitcast<_To>(_mm256_shuffle_epi8(
1958 		  __c, _mm256_setr_epi8(0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13,
1959 					6, 7, 14, 15, 0, 1, 8, 9, 2, 3, 10, 11,
1960 					4, 5, 12, 13, 6, 7, 14, 15)));
1961 	      }
1962 	    else if constexpr (__z_to_z)
1963 	      {
1964 		return __concat(
1965 		  __convert_x86<__vector_type_t<_Up, _M / 2>>(__v0, __v1, __v2,
1966 							      __v3),
1967 		  __convert_x86<__vector_type_t<_Up, _M / 2>>(__v4, __v5, __v6,
1968 							      __v7));
1969 	      }
1970 	  }
1971 	else if constexpr (__f64_to_i8) //{{{2
1972 	  {
1973 	    return __convert_x86<_To>(
1974 	      __convert_x86<__vector_type_t<int, _Np * 2>>(__v0, __v1),
1975 	      __convert_x86<__vector_type_t<int, _Np * 2>>(__v2, __v3),
1976 	      __convert_x86<__vector_type_t<int, _Np * 2>>(__v4, __v5),
1977 	      __convert_x86<__vector_type_t<int, _Np * 2>>(__v6, __v7));
1978 	  }
1979 	else // unreachable {{{2
1980 	  __assert_unreachable<_Tp>();
1981 	//}}}
1982 
1983 	// fallback: {{{2
1984 	if constexpr (sizeof(_To) >= 32)
1985 	  // if _To is ymm or zmm, then _SimdWrapper<_Up, _M / 2> is xmm or ymm
1986 	  return __concat(
1987 	    __convert_x86<__vector_type_t<_Up, _M / 2>>(__v0, __v1, __v2, __v3),
1988 	    __convert_x86<__vector_type_t<_Up, _M / 2>>(__v4, __v5, __v6,
1989 							__v7));
1990 	else if constexpr (sizeof(_To) == 16)
1991 	  {
1992 	    const auto __lo
1993 	      = __to_intrin(__convert_x86<_To>(__v0, __v1, __v2, __v3));
1994 	    const auto __hi
1995 	      = __to_intrin(__convert_x86<_To>(__v4, __v5, __v6, __v7));
1996 	    static_assert(sizeof(_Up) == 1 && _Np == 2);
1997 	    return __intrin_bitcast<_To>(_mm_unpacklo_epi64(__lo, __hi));
1998 	  }
1999 	else
2000 	  {
2001 	    __assert_unreachable<_Tp>();
2002 	    // return __vector_convert<_To>(__v0, __v1, __v2, __v3, __v4, __v5,
2003 	    // __v6, __v7,
2004 	    //                             make_index_sequence<_Np>());
2005 	  } //}}}2
2006       }
2007   }
2008 
2009 //}}}
2010 // 16-arg __convert_x86 {{{1
2011 template <typename _To, typename _V, typename _Traits>
2012   _GLIBCXX_SIMD_INTRINSIC _To
2013   __convert_x86(_V __v0, _V __v1, _V __v2, _V __v3, _V __v4, _V __v5, _V __v6,
2014 		_V __v7, _V __v8, _V __v9, _V __v10, _V __v11, _V __v12,
2015 		_V __v13, _V __v14, _V __v15)
2016   {
2017     // concat => use 8-arg __convert_x86
2018     return __convert_x86<_To>(__concat(__v0, __v1), __concat(__v2, __v3),
2019 			      __concat(__v4, __v5), __concat(__v6, __v7),
2020 			      __concat(__v8, __v9), __concat(__v10, __v11),
2021 			      __concat(__v12, __v13), __concat(__v14, __v15));
2022   }
2023 
2024 //}}}
2025 
2026 #endif // __cplusplus >= 201703L
2027 #endif // _GLIBCXX_EXPERIMENTAL_SIMD_X86_CONVERSIONS_H
2028 
2029 // vim: foldmethod=marker
2030