3#include "native/config.h"
9#if NATIVE_HOST_X86 || defined(NATIVE_DOXYGEN)
10namespace native::detail::x86_vbmi {
13 template<isa<x86> Arch>
14 requires(Arch.has(x86_feature::avx512f) &&
15 Arch.has(x86_feature::avx512bw) &&
16 Arch.has(x86_feature::avx512vbmi) &&
17 Arch.has(x86_feature::avx512vl))
21 __m128i value) noexcept {
22 return _mm_permutexvar_epi8(indices, value);
25 template<isa<x86> Arch>
26 requires(Arch.has(x86_feature::avx512f) &&
27 Arch.has(x86_feature::avx512bw) &&
28 Arch.has(x86_feature::avx512vbmi) &&
29 Arch.has(x86_feature::avx512vl))
35 __m128i value) noexcept {
36 return _mm_mask_permutexvar_epi8(source,
mask, indices, value);
39 template<isa<x86> Arch>
40 requires(Arch.has(x86_feature::avx512f) &&
41 Arch.has(x86_feature::avx512bw) &&
42 Arch.has(x86_feature::avx512vbmi) &&
43 Arch.has(x86_feature::avx512vl))
48 __m128i value) noexcept {
49 return _mm_maskz_permutexvar_epi8(
mask, indices, value);
52 template<isa<x86> Arch>
53 requires(Arch.has(x86_feature::avx512f) &&
54 Arch.has(x86_feature::avx512bw) &&
55 Arch.has(x86_feature::avx512vbmi) &&
56 Arch.has(x86_feature::avx512vl))
62 return _mm_permutex2var_epi8(a, indices, b);
65 template<isa<x86> Arch>
66 requires(Arch.has(x86_feature::avx512f) &&
67 Arch.has(x86_feature::avx512bw) &&
68 Arch.has(x86_feature::avx512vbmi) &&
69 Arch.has(x86_feature::avx512vl))
71 __m128i mask_vpermt2b(
76 return _mm_mask_permutex2var_epi8(a,
mask, indices, b);
79 template<isa<x86> Arch>
80 requires(Arch.has(x86_feature::avx512f) &&
81 Arch.has(x86_feature::avx512bw) &&
82 Arch.has(x86_feature::avx512vbmi) &&
83 Arch.has(x86_feature::avx512vl))
85 __m128i maskz_vpermt2b(
90 return _mm_maskz_permutex2var_epi8(
mask, a, indices, b);
93 template<isa<x86> Arch>
94 requires(Arch.has(x86_feature::avx512f) &&
95 Arch.has(x86_feature::avx512bw) &&
96 Arch.has(x86_feature::avx512vbmi) &&
97 Arch.has(x86_feature::avx512vl))
102 __m128i b) noexcept {
103 return _mm_permutex2var_epi8(a, indices, b);
106 template<isa<x86> Arch>
107 requires(Arch.has(x86_feature::avx512f) &&
108 Arch.has(x86_feature::avx512bw) &&
109 Arch.has(x86_feature::avx512vbmi) &&
110 Arch.has(x86_feature::avx512vl))
112 __m128i mask_vpermi2b(
116 __m128i b) noexcept {
117 return _mm_mask2_permutex2var_epi8(a, indices,
mask, b);
120 template<isa<x86> Arch>
121 requires(Arch.has(x86_feature::avx512f) &&
122 Arch.has(x86_feature::avx512bw) &&
123 Arch.has(x86_feature::avx512vbmi) &&
124 Arch.has(x86_feature::avx512vl))
126 __m128i maskz_vpermi2b(
130 __m128i b) noexcept {
131 return _mm_maskz_permutex2var_epi8(
mask, a, indices, b);
134 template<isa<x86> Arch>
135 requires(Arch.has(x86_feature::avx512f) &&
136 Arch.has(x86_feature::avx512bw) &&
137 Arch.has(x86_feature::avx512vbmi) &&
138 Arch.has(x86_feature::avx512vl))
140 __m128i vpmultishiftqb(
142 __m128i value) noexcept {
143 return _mm_multishift_epi64_epi8(control, value);
146 template<isa<x86> Arch>
147 requires(Arch.has(x86_feature::avx512f) &&
148 Arch.has(x86_feature::avx512bw) &&
149 Arch.has(x86_feature::avx512vbmi) &&
150 Arch.has(x86_feature::avx512vl))
152 __m128i mask_vpmultishiftqb(
156 __m128i value) noexcept {
157 return _mm_mask_multishift_epi64_epi8(source,
mask, control, value);
160 template<isa<x86> Arch>
161 requires(Arch.has(x86_feature::avx512f) &&
162 Arch.has(x86_feature::avx512bw) &&
163 Arch.has(x86_feature::avx512vbmi) &&
164 Arch.has(x86_feature::avx512vl))
166 __m128i maskz_vpmultishiftqb(
169 __m128i value) noexcept {
170 return _mm_maskz_multishift_epi64_epi8(
mask, control, value);
173 template<isa<x86> Arch>
174 requires(Arch.has(x86_feature::avx512f) &&
175 Arch.has(x86_feature::avx512bw) &&
176 Arch.has(x86_feature::avx512vbmi) &&
177 Arch.has(x86_feature::avx512vl))
181 __m256i value) noexcept {
182 return _mm256_permutexvar_epi8(indices, value);
185 template<isa<x86> Arch>
186 requires(Arch.has(x86_feature::avx512f) &&
187 Arch.has(x86_feature::avx512bw) &&
188 Arch.has(x86_feature::avx512vbmi) &&
189 Arch.has(x86_feature::avx512vl))
195 __m256i value) noexcept {
196 return _mm256_mask_permutexvar_epi8(source,
mask, indices, value);
199 template<isa<x86> Arch>
200 requires(Arch.has(x86_feature::avx512f) &&
201 Arch.has(x86_feature::avx512bw) &&
202 Arch.has(x86_feature::avx512vbmi) &&
203 Arch.has(x86_feature::avx512vl))
205 __m256i maskz_vpermb(
208 __m256i value) noexcept {
209 return _mm256_maskz_permutexvar_epi8(
mask, indices, value);
212 template<isa<x86> Arch>
213 requires(Arch.has(x86_feature::avx512f) &&
214 Arch.has(x86_feature::avx512bw) &&
215 Arch.has(x86_feature::avx512vbmi) &&
216 Arch.has(x86_feature::avx512vl))
221 __m256i b) noexcept {
222 return _mm256_permutex2var_epi8(a, indices, b);
225 template<isa<x86> Arch>
226 requires(Arch.has(x86_feature::avx512f) &&
227 Arch.has(x86_feature::avx512bw) &&
228 Arch.has(x86_feature::avx512vbmi) &&
229 Arch.has(x86_feature::avx512vl))
231 __m256i mask_vpermt2b(
235 __m256i b) noexcept {
236 return _mm256_mask_permutex2var_epi8(a,
mask, indices, b);
239 template<isa<x86> Arch>
240 requires(Arch.has(x86_feature::avx512f) &&
241 Arch.has(x86_feature::avx512bw) &&
242 Arch.has(x86_feature::avx512vbmi) &&
243 Arch.has(x86_feature::avx512vl))
245 __m256i maskz_vpermt2b(
249 __m256i b) noexcept {
250 return _mm256_maskz_permutex2var_epi8(
mask, a, indices, b);
253 template<isa<x86> Arch>
254 requires(Arch.has(x86_feature::avx512f) &&
255 Arch.has(x86_feature::avx512bw) &&
256 Arch.has(x86_feature::avx512vbmi) &&
257 Arch.has(x86_feature::avx512vl))
262 __m256i b) noexcept {
263 return _mm256_permutex2var_epi8(a, indices, b);
266 template<isa<x86> Arch>
267 requires(Arch.has(x86_feature::avx512f) &&
268 Arch.has(x86_feature::avx512bw) &&
269 Arch.has(x86_feature::avx512vbmi) &&
270 Arch.has(x86_feature::avx512vl))
272 __m256i mask_vpermi2b(
276 __m256i b) noexcept {
277 return _mm256_mask2_permutex2var_epi8(a, indices,
mask, b);
280 template<isa<x86> Arch>
281 requires(Arch.has(x86_feature::avx512f) &&
282 Arch.has(x86_feature::avx512bw) &&
283 Arch.has(x86_feature::avx512vbmi) &&
284 Arch.has(x86_feature::avx512vl))
286 __m256i maskz_vpermi2b(
290 __m256i b) noexcept {
291 return _mm256_maskz_permutex2var_epi8(
mask, a, indices, b);
294 template<isa<x86> Arch>
295 requires(Arch.has(x86_feature::avx512f) &&
296 Arch.has(x86_feature::avx512bw) &&
297 Arch.has(x86_feature::avx512vbmi) &&
298 Arch.has(x86_feature::avx512vl))
300 __m256i vpmultishiftqb(
302 __m256i value) noexcept {
303 return _mm256_multishift_epi64_epi8(control, value);
306 template<isa<x86> Arch>
307 requires(Arch.has(x86_feature::avx512f) &&
308 Arch.has(x86_feature::avx512bw) &&
309 Arch.has(x86_feature::avx512vbmi) &&
310 Arch.has(x86_feature::avx512vl))
312 __m256i mask_vpmultishiftqb(
316 __m256i value) noexcept {
317 return _mm256_mask_multishift_epi64_epi8(source,
mask, control, value);
320 template<isa<x86> Arch>
321 requires(Arch.has(x86_feature::avx512f) &&
322 Arch.has(x86_feature::avx512bw) &&
323 Arch.has(x86_feature::avx512vbmi) &&
324 Arch.has(x86_feature::avx512vl))
326 __m256i maskz_vpmultishiftqb(
329 __m256i value) noexcept {
330 return _mm256_maskz_multishift_epi64_epi8(
mask, control, value);
333 template<isa<x86> Arch>
334 requires(Arch.has(x86_feature::avx512f) &&
335 Arch.has(x86_feature::avx512bw) &&
336 Arch.has(x86_feature::avx512vbmi))
340 __m512i value) noexcept {
341 return _mm512_permutexvar_epi8(indices, value);
344 template<isa<x86> Arch>
345 requires(Arch.has(x86_feature::avx512f) &&
346 Arch.has(x86_feature::avx512bw) &&
347 Arch.has(x86_feature::avx512vbmi))
353 __m512i value) noexcept {
354 return _mm512_mask_permutexvar_epi8(source,
mask, indices, value);
357 template<isa<x86> Arch>
358 requires(Arch.has(x86_feature::avx512f) &&
359 Arch.has(x86_feature::avx512bw) &&
360 Arch.has(x86_feature::avx512vbmi))
362 __m512i maskz_vpermb(
365 __m512i value) noexcept {
366 return _mm512_maskz_permutexvar_epi8(
mask, indices, value);
369 template<isa<x86> Arch>
370 requires(Arch.has(x86_feature::avx512f) &&
371 Arch.has(x86_feature::avx512bw) &&
372 Arch.has(x86_feature::avx512vbmi))
377 __m512i b) noexcept {
378 return _mm512_permutex2var_epi8(a, indices, b);
381 template<isa<x86> Arch>
382 requires(Arch.has(x86_feature::avx512f) &&
383 Arch.has(x86_feature::avx512bw) &&
384 Arch.has(x86_feature::avx512vbmi))
386 __m512i mask_vpermt2b(
390 __m512i b) noexcept {
391 return _mm512_mask_permutex2var_epi8(a,
mask, indices, b);
394 template<isa<x86> Arch>
395 requires(Arch.has(x86_feature::avx512f) &&
396 Arch.has(x86_feature::avx512bw) &&
397 Arch.has(x86_feature::avx512vbmi))
399 __m512i maskz_vpermt2b(
403 __m512i b) noexcept {
404 return _mm512_maskz_permutex2var_epi8(
mask, a, indices, b);
407 template<isa<x86> Arch>
408 requires(Arch.has(x86_feature::avx512f) &&
409 Arch.has(x86_feature::avx512bw) &&
410 Arch.has(x86_feature::avx512vbmi))
415 __m512i b) noexcept {
416 return _mm512_permutex2var_epi8(a, indices, b);
419 template<isa<x86> Arch>
420 requires(Arch.has(x86_feature::avx512f) &&
421 Arch.has(x86_feature::avx512bw) &&
422 Arch.has(x86_feature::avx512vbmi))
424 __m512i mask_vpermi2b(
428 __m512i b) noexcept {
429 return _mm512_mask2_permutex2var_epi8(a, indices,
mask, b);
432 template<isa<x86> Arch>
433 requires(Arch.has(x86_feature::avx512f) &&
434 Arch.has(x86_feature::avx512bw) &&
435 Arch.has(x86_feature::avx512vbmi))
437 __m512i maskz_vpermi2b(
441 __m512i b) noexcept {
442 return _mm512_maskz_permutex2var_epi8(
mask, a, indices, b);
445 template<isa<x86> Arch>
446 requires(Arch.has(x86_feature::avx512f) &&
447 Arch.has(x86_feature::avx512bw) &&
448 Arch.has(x86_feature::avx512vbmi))
450 __m512i vpmultishiftqb(
452 __m512i value) noexcept {
453 return _mm512_multishift_epi64_epi8(control, value);
456 template<isa<x86> Arch>
457 requires(Arch.has(x86_feature::avx512f) &&
458 Arch.has(x86_feature::avx512bw) &&
459 Arch.has(x86_feature::avx512vbmi))
461 __m512i mask_vpmultishiftqb(
465 __m512i value) noexcept {
466 return _mm512_mask_multishift_epi64_epi8(source,
mask, control, value);
469 template<isa<x86> Arch>
470 requires(Arch.has(x86_feature::avx512f) &&
471 Arch.has(x86_feature::avx512bw) &&
472 Arch.has(x86_feature::avx512vbmi))
474 __m512i maskz_vpmultishiftqb(
477 __m512i value) noexcept {
478 return _mm512_maskz_multishift_epi64_epi8(
mask, control, value);
488namespace native::detail::x86_vbmi_constant {
489 template<
bool Two,
class V>
490 constexpr V permute(V indices, V a, V b, V source, std::uint64_t
mask)
noexcept {
491 std::array<std::uint8_t, V::lanes> selectors{}, first{}, second{}, result{};
492 indices.store(selectors.data());
493 a.store(first.data());
494 b.store(second.data());
495 source.store(result.data());
496 for (std::size_t lane = 0; lane < V::lanes; ++lane) {
497 if ((
mask >> lane) & 1) {
498 auto index = selectors[lane] & (V::lanes * (Two ? 2 : 1) - 1);
499 result[lane] = index < V::lanes ? first[index] : second[index - V::lanes];
502 return V::load(result.data());
505 template<
class C,
class V>
506 constexpr C multishift(C control, V value, C source, std::uint64_t
mask)
noexcept {
507 std::array<std::uint8_t, C::lanes> selectors{}, result{};
508 std::array<std::uint64_t, V::lanes> words{};
509 control.store(selectors.data());
510 value.store(words.data());
511 source.store(result.data());
512 for (std::size_t lane = 0; lane < C::lanes; ++lane) {
513 if ((
mask >> lane) & 1) {
515 result[lane] =
static_cast<std::uint8_t
>(std::rotr(words[lane / 8], selectors[lane] & 63));
518 return C::load(result.data());
Compiler attributes for host code, with shader-safe shared modifiers.
#define native_inline
inline [[always_inline]]
#define native_nodiscard
C++17 [[nodiscard]].
#define native_const
[[const]] is not const
#define native_target(x)
this indicates a required feature set for the current multiversioned function.
typename mask_traits< std::remove_cvref_t< T > >::type mask