native 0.0.1
Vectors, masks and wide register packs for C++26
Loading...
Searching...
No Matches
avx512cd.h
1// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0
2#pragma once
3#include "native/config.h"
4#include "native/attributes.h"
5#include "native/isa.h"
6#if NATIVE_HOST_X86
7#include <immintrin.h>
8#endif
9#if NATIVE_HOST_X86 || defined(NATIVE_DOXYGEN)
10namespace native::detail::x86_avx512cd {
11 // Internal register helpers for native.x86.avx512cd.
12
13 template<isa<x86> Arch>
14 requires(Arch.has(x86_feature::avx512f) &&
15 Arch.has(x86_feature::avx512cd) &&
16 Arch.has(x86_feature::avx512vl))
17 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
18 __m128i vpconflictd(__m128i value) noexcept {
19 return _mm_conflict_epi32(value);
20 }
21
22 template<isa<x86> Arch>
23 requires(Arch.has(x86_feature::avx512f) &&
24 Arch.has(x86_feature::avx512cd) &&
25 Arch.has(x86_feature::avx512vl))
26 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
27 __m128i mask_vpconflictd(__m128i source, __mmask8 mask, __m128i value) noexcept {
28 return _mm_mask_conflict_epi32(source, mask, value);
29 }
30
31 template<isa<x86> Arch>
32 requires(Arch.has(x86_feature::avx512f) &&
33 Arch.has(x86_feature::avx512cd) &&
34 Arch.has(x86_feature::avx512vl))
35 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
36 __m128i maskz_vpconflictd(__mmask8 mask, __m128i value) noexcept {
37 return _mm_maskz_conflict_epi32(mask, value);
38 }
39
40 template<isa<x86> Arch>
41 requires(Arch.has(x86_feature::avx512f) &&
42 Arch.has(x86_feature::avx512cd) &&
43 Arch.has(x86_feature::avx512vl))
44 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
45 __m128i vplzcntd(__m128i value) noexcept {
46 return _mm_lzcnt_epi32(value);
47 }
48
49 template<isa<x86> Arch>
50 requires(Arch.has(x86_feature::avx512f) &&
51 Arch.has(x86_feature::avx512cd) &&
52 Arch.has(x86_feature::avx512vl))
53 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
54 __m128i mask_vplzcntd(__m128i source, __mmask8 mask, __m128i value) noexcept {
55 return _mm_mask_lzcnt_epi32(source, mask, value);
56 }
57
58 template<isa<x86> Arch>
59 requires(Arch.has(x86_feature::avx512f) &&
60 Arch.has(x86_feature::avx512cd) &&
61 Arch.has(x86_feature::avx512vl))
62 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
63 __m128i maskz_vplzcntd(__mmask8 mask, __m128i value) noexcept {
64 return _mm_maskz_lzcnt_epi32(mask, value);
65 }
66
67 template<isa<x86> Arch>
68 requires(Arch.has(x86_feature::avx512f) &&
69 Arch.has(x86_feature::avx512cd) &&
70 Arch.has(x86_feature::avx512vl))
71 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
72 __m128i vpconflictq(__m128i value) noexcept {
73 return _mm_conflict_epi64(value);
74 }
75
76 template<isa<x86> Arch>
77 requires(Arch.has(x86_feature::avx512f) &&
78 Arch.has(x86_feature::avx512cd) &&
79 Arch.has(x86_feature::avx512vl))
80 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
81 __m128i mask_vpconflictq(__m128i source, __mmask8 mask, __m128i value) noexcept {
82 return _mm_mask_conflict_epi64(source, mask, value);
83 }
84
85 template<isa<x86> Arch>
86 requires(Arch.has(x86_feature::avx512f) &&
87 Arch.has(x86_feature::avx512cd) &&
88 Arch.has(x86_feature::avx512vl))
89 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
90 __m128i maskz_vpconflictq(__mmask8 mask, __m128i value) noexcept {
91 return _mm_maskz_conflict_epi64(mask, value);
92 }
93
94 template<isa<x86> Arch>
95 requires(Arch.has(x86_feature::avx512f) &&
96 Arch.has(x86_feature::avx512cd) &&
97 Arch.has(x86_feature::avx512vl))
98 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
99 __m128i vplzcntq(__m128i value) noexcept {
100 return _mm_lzcnt_epi64(value);
101 }
102
103 template<isa<x86> Arch>
104 requires(Arch.has(x86_feature::avx512f) &&
105 Arch.has(x86_feature::avx512cd) &&
106 Arch.has(x86_feature::avx512vl))
107 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
108 __m128i mask_vplzcntq(__m128i source, __mmask8 mask, __m128i value) noexcept {
109 return _mm_mask_lzcnt_epi64(source, mask, value);
110 }
111
112 template<isa<x86> Arch>
113 requires(Arch.has(x86_feature::avx512f) &&
114 Arch.has(x86_feature::avx512cd) &&
115 Arch.has(x86_feature::avx512vl))
116 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
117 __m128i maskz_vplzcntq(__mmask8 mask, __m128i value) noexcept {
118 return _mm_maskz_lzcnt_epi64(mask, value);
119 }
120
121 template<isa<x86> Arch>
122 requires(Arch.has(x86_feature::avx512f) &&
123 Arch.has(x86_feature::avx512cd) &&
124 Arch.has(x86_feature::avx512vl))
125 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
126 __m256i vpconflictd(__m256i value) noexcept {
127 return _mm256_conflict_epi32(value);
128 }
129
130 template<isa<x86> Arch>
131 requires(Arch.has(x86_feature::avx512f) &&
132 Arch.has(x86_feature::avx512cd) &&
133 Arch.has(x86_feature::avx512vl))
134 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
135 __m256i mask_vpconflictd(__m256i source, __mmask8 mask, __m256i value) noexcept {
136 return _mm256_mask_conflict_epi32(source, mask, value);
137 }
138
139 template<isa<x86> Arch>
140 requires(Arch.has(x86_feature::avx512f) &&
141 Arch.has(x86_feature::avx512cd) &&
142 Arch.has(x86_feature::avx512vl))
143 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
144 __m256i maskz_vpconflictd(__mmask8 mask, __m256i value) noexcept {
145 return _mm256_maskz_conflict_epi32(mask, value);
146 }
147
148 template<isa<x86> Arch>
149 requires(Arch.has(x86_feature::avx512f) &&
150 Arch.has(x86_feature::avx512cd) &&
151 Arch.has(x86_feature::avx512vl))
152 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
153 __m256i vplzcntd(__m256i value) noexcept {
154 return _mm256_lzcnt_epi32(value);
155 }
156
157 template<isa<x86> Arch>
158 requires(Arch.has(x86_feature::avx512f) &&
159 Arch.has(x86_feature::avx512cd) &&
160 Arch.has(x86_feature::avx512vl))
161 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
162 __m256i mask_vplzcntd(__m256i source, __mmask8 mask, __m256i value) noexcept {
163 return _mm256_mask_lzcnt_epi32(source, mask, value);
164 }
165
166 template<isa<x86> Arch>
167 requires(Arch.has(x86_feature::avx512f) &&
168 Arch.has(x86_feature::avx512cd) &&
169 Arch.has(x86_feature::avx512vl))
170 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
171 __m256i maskz_vplzcntd(__mmask8 mask, __m256i value) noexcept {
172 return _mm256_maskz_lzcnt_epi32(mask, value);
173 }
174
175 template<isa<x86> Arch>
176 requires(Arch.has(x86_feature::avx512f) &&
177 Arch.has(x86_feature::avx512cd) &&
178 Arch.has(x86_feature::avx512vl))
179 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
180 __m256i vpconflictq(__m256i value) noexcept {
181 return _mm256_conflict_epi64(value);
182 }
183
184 template<isa<x86> Arch>
185 requires(Arch.has(x86_feature::avx512f) &&
186 Arch.has(x86_feature::avx512cd) &&
187 Arch.has(x86_feature::avx512vl))
188 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
189 __m256i mask_vpconflictq(__m256i source, __mmask8 mask, __m256i value) noexcept {
190 return _mm256_mask_conflict_epi64(source, mask, value);
191 }
192
193 template<isa<x86> Arch>
194 requires(Arch.has(x86_feature::avx512f) &&
195 Arch.has(x86_feature::avx512cd) &&
196 Arch.has(x86_feature::avx512vl))
197 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
198 __m256i maskz_vpconflictq(__mmask8 mask, __m256i value) noexcept {
199 return _mm256_maskz_conflict_epi64(mask, value);
200 }
201
202 template<isa<x86> Arch>
203 requires(Arch.has(x86_feature::avx512f) &&
204 Arch.has(x86_feature::avx512cd) &&
205 Arch.has(x86_feature::avx512vl))
206 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
207 __m256i vplzcntq(__m256i value) noexcept {
208 return _mm256_lzcnt_epi64(value);
209 }
210
211 template<isa<x86> Arch>
212 requires(Arch.has(x86_feature::avx512f) &&
213 Arch.has(x86_feature::avx512cd) &&
214 Arch.has(x86_feature::avx512vl))
215 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
216 __m256i mask_vplzcntq(__m256i source, __mmask8 mask, __m256i value) noexcept {
217 return _mm256_mask_lzcnt_epi64(source, mask, value);
218 }
219
220 template<isa<x86> Arch>
221 requires(Arch.has(x86_feature::avx512f) &&
222 Arch.has(x86_feature::avx512cd) &&
223 Arch.has(x86_feature::avx512vl))
224 native_nodiscard native_inline native_const native_target("avx512f,avx512cd,avx512vl")
225 __m256i maskz_vplzcntq(__mmask8 mask, __m256i value) noexcept {
226 return _mm256_maskz_lzcnt_epi64(mask, value);
227 }
228
229 template<isa<x86> Arch>
230 requires(Arch.has(x86_feature::avx512f) &&
231 Arch.has(x86_feature::avx512cd))
233 __m512i vpconflictd(__m512i value) noexcept {
234 return _mm512_conflict_epi32(value);
235 }
236
237 template<isa<x86> Arch>
238 requires(Arch.has(x86_feature::avx512f) &&
239 Arch.has(x86_feature::avx512cd))
241 __m512i mask_vpconflictd(__m512i source, __mmask16 mask, __m512i value) noexcept {
242 return _mm512_mask_conflict_epi32(source, mask, value);
243 }
244
245 template<isa<x86> Arch>
246 requires(Arch.has(x86_feature::avx512f) &&
247 Arch.has(x86_feature::avx512cd))
249 __m512i maskz_vpconflictd(__mmask16 mask, __m512i value) noexcept {
250 return _mm512_maskz_conflict_epi32(mask, value);
251 }
252
253 template<isa<x86> Arch>
254 requires(Arch.has(x86_feature::avx512f) &&
255 Arch.has(x86_feature::avx512cd))
257 __m512i vplzcntd(__m512i value) noexcept {
258 return _mm512_lzcnt_epi32(value);
259 }
260
261 template<isa<x86> Arch>
262 requires(Arch.has(x86_feature::avx512f) &&
263 Arch.has(x86_feature::avx512cd))
265 __m512i mask_vplzcntd(__m512i source, __mmask16 mask, __m512i value) noexcept {
266 return _mm512_mask_lzcnt_epi32(source, mask, value);
267 }
268
269 template<isa<x86> Arch>
270 requires(Arch.has(x86_feature::avx512f) &&
271 Arch.has(x86_feature::avx512cd))
273 __m512i maskz_vplzcntd(__mmask16 mask, __m512i value) noexcept {
274 return _mm512_maskz_lzcnt_epi32(mask, value);
275 }
276
277 template<isa<x86> Arch>
278 requires(Arch.has(x86_feature::avx512f) &&
279 Arch.has(x86_feature::avx512cd))
281 __m512i vpconflictq(__m512i value) noexcept {
282 return _mm512_conflict_epi64(value);
283 }
284
285 template<isa<x86> Arch>
286 requires(Arch.has(x86_feature::avx512f) &&
287 Arch.has(x86_feature::avx512cd))
289 __m512i mask_vpconflictq(__m512i source, __mmask8 mask, __m512i value) noexcept {
290 return _mm512_mask_conflict_epi64(source, mask, value);
291 }
292
293 template<isa<x86> Arch>
294 requires(Arch.has(x86_feature::avx512f) &&
295 Arch.has(x86_feature::avx512cd))
297 __m512i maskz_vpconflictq(__mmask8 mask, __m512i value) noexcept {
298 return _mm512_maskz_conflict_epi64(mask, value);
299 }
300
301 template<isa<x86> Arch>
302 requires(Arch.has(x86_feature::avx512f) &&
303 Arch.has(x86_feature::avx512cd))
305 __m512i vplzcntq(__m512i value) noexcept {
306 return _mm512_lzcnt_epi64(value);
307 }
308
309 template<isa<x86> Arch>
310 requires(Arch.has(x86_feature::avx512f) &&
311 Arch.has(x86_feature::avx512cd))
313 __m512i mask_vplzcntq(__m512i source, __mmask8 mask, __m512i value) noexcept {
314 return _mm512_mask_lzcnt_epi64(source, mask, value);
315 }
316
317 template<isa<x86> Arch>
318 requires(Arch.has(x86_feature::avx512f) &&
319 Arch.has(x86_feature::avx512cd))
321 __m512i maskz_vplzcntq(__mmask8 mask, __m512i value) noexcept {
322 return _mm512_maskz_lzcnt_epi64(mask, value);
323 }
324}
325#endif
326
327#include <array>
328#include <bit>
329#include <cstddef>
330#include <cstdint>
331
332namespace native::detail::x86_avx512cd_constant {
333 // Used only during constant evaluation, independently of the runtime target.
334 template<bool Conflict, class V>
335 constexpr V evaluate(V value, V source, std::uint64_t mask) noexcept {
336 using value_type = typename V::value_type;
337 std::array<value_type, V::lanes> input{};
338 std::array<value_type, V::lanes> result{};
339 value.store(input.data());
340 source.store(result.data());
341 for (std::size_t lane = 0; lane < V::lanes; ++lane) {
342 if (!((mask >> lane) & 1)) {
343 continue;
344 }
345 if constexpr (Conflict) {
346 value_type matches = 0;
347 // The writemask controls destination lanes, never comparison inputs.
348 for (std::size_t earlier = 0; earlier < lane; ++earlier) {
349 if (input[earlier] == input[lane]) {
350 matches |= value_type{1} << earlier;
351 }
352 }
353 result[lane] = matches;
354 } else {
355 result[lane] = static_cast<value_type>(std::countl_zero(input[lane]));
356 }
357 }
358 return V::load(result.data());
359 }
360}
Compiler attributes for host code, with shader-safe shared modifiers.
#define native_inline
inline [[always_inline]]
Definition attributes.h:212
#define native_nodiscard
C++17 [[nodiscard]].
Definition attributes.h:189
#define native_const
[[const]] is not const
Definition attributes.h:108
#define native_target(x)
this indicates a required feature set for the current multiversioned function.
Definition attributes.h:476
typename mask_traits< std::remove_cvref_t< T > >::type mask
Definition mask_traits.h:22