native 0.0.1
Vectors, masks and wide register packs for C++26
Loading...
Searching...
No Matches
isa.h
1// SPDX-FileCopyrightText: 2026 Edward Kmett <ekmett@gmail.com>
2// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0
3#pragma once
4#include "native/config.h"
5#include <array>
6#include <concepts>
7#include <cstddef>
8#include <cstdint>
9#include <string_view>
10#include <type_traits>
11#include <utility>
12
13namespace native {
15 enum class x86_feature : std::uint64_t {
16 mmx, sse, sse2, sse3, ssse3, sse41,
17 sse42, popcnt, avx, avx2, fma, f16c,
18 bmi1, bmi2, avx512f, avx512dq, avx512bw, avx512vl,
19 avx512bf16, avx512fp16, aes, pclmul, cx16, avx512cd,
20 avx512ifma, lzcnt, movbe, sahf, mwaitx, waitpkg, crc32, gfni, avx512vpopcntdq,
21 vpclmulqdq, avxvnni, avx512vnni, avxvnniint8, avxvnniint16, avx512bitalg, avx512vbmi, avx512vbmi2, sha, vaes, avxifma, adx, sha512, sm3, sm4, avxneconvert
22 };
23
24 enum class arm_feature : std::uint64_t {
25 neon, neon_fp16, neon_bf16, aes, sha2, sha3,
26 crc, lse, rdm, fp16fml, dotprod, complxnum,
27 jsconv, rcpc, pauth, i8mm, pmull, sha1, sha512, ebf16, sm3, sm4
28 };
29
30 enum class wasm_feature : std::uint64_t { simd128, relaxed_simd };
32 inline constexpr std::size_t wasm_feature_count=std::size_t(wasm_feature::relaxed_simd)+1;
34 inline constexpr std::size_t x86_feature_count=std::size_t(x86_feature::avxneconvert)+1;
36 inline constexpr std::size_t arm_feature_count=std::size_t(arm_feature::sm4)+1;
37
39 template<architecture Family=target_arch> struct isa;
40
41 namespace detail {
42 template<class T> concept instruction_feature=
43 std::same_as<T,x86_feature> || std::same_as<T,arm_feature> || std::same_as<T,wasm_feature>;
44 template<instruction_feature E> inline constexpr std::size_t feature_count=
45 std::same_as<E,x86_feature> ? x86_feature_count :
46 std::same_as<E,arm_feature> ? arm_feature_count : wasm_feature_count;
47 template<instruction_feature E> inline constexpr architecture family_of=
48 std::same_as<E,x86_feature> ? x86 : std::same_as<E,arm_feature> ? arm : wasm;
49 template<architecture Family> struct feature_traits;
50 template<> struct feature_traits<x86> { using type=x86_feature; static constexpr auto count=x86_feature_count; };
51 template<> struct feature_traits<arm> { using type=arm_feature; static constexpr auto count=arm_feature_count; };
52 template<> struct feature_traits<wasm> { using type=wasm_feature; static constexpr auto count=wasm_feature_count; };
53 enum class unknown_feature : std::uint64_t {};
54 template<> struct feature_traits<architecture::unknown> { using type=unknown_feature; static constexpr std::size_t count=0; };
55 }
56
58 template<architecture Family> struct isa {
60 using feature_type=typename detail::feature_traits<Family>::type;
62 static constexpr architecture family=Family;
64 static constexpr auto feature_count=detail::feature_traits<Family>::count;
66 std::array<std::uint64_t,(feature_count+1+63)/64> flags{};
68 constexpr isa() noexcept=default;
70 constexpr isa(feature_type f) noexcept { set(f,true); }
72 constexpr bool get(feature_type f) const noexcept {
73 auto i=std::uint64_t(f);
74 return i<feature_count && ((flags[i/64]>>(i%64))&1);
75 }
76
78 constexpr void set(feature_type f,bool value) noexcept {
79 auto i=std::uint64_t(f);
80 if(i>=feature_count) {
81 if(!value) return;
83 }
84 auto mask=std::uint64_t{1}<<(i%64);
85 auto & word=flags[i/64];
86 word=(word&~mask)|(value?mask:0);
87 }
88
89 constexpr bool has(feature_type f) const noexcept { return get(f); }
91 constexpr bool has(isa other) const noexcept {
92 for(std::size_t i=0;i<flags.size();++i)
93 if((flags[i]&other.flags[i])!=other.flags[i]) return false;
94 return true;
95 }
96
97 constexpr bool valid() const noexcept {
98 constexpr auto used=feature_count%64;
99 constexpr auto mask=used ? (std::uint64_t{1}<<used)-1 : 0;
100 return (flags.back()&~mask)==0;
101 }
102
103 constexpr bool operator==(isa const &) const=default;
104 };
105
107 template<> struct isa<x86> {
109 using feature_type=typename detail::feature_traits<x86>::type;
111 static constexpr architecture family=x86;
113 static constexpr auto feature_count=detail::feature_traits<x86>::count;
115 std::array<std::uint64_t,(feature_count+1+63)/64> flags{};
117 constexpr isa() noexcept=default;
119 constexpr isa(feature_type f) noexcept { set(f,true); }
121 constexpr bool get(feature_type f) const noexcept {
122 auto i=std::uint64_t(f);
123 return i<feature_count && ((flags[i/64]>>(i%64))&1);
124 }
125
127 constexpr void set(feature_type f,bool value) noexcept {
128 auto i=std::uint64_t(f);
129 if(i>=feature_count) {
130 if(!value) return;
132 }
133 auto mask=std::uint64_t{1}<<(i%64);
134 auto & word=flags[i/64];
135 word=(word&~mask)|(value?mask:0);
136 }
137
138 constexpr bool has(feature_type f) const noexcept { return get(f); }
140 constexpr bool has(isa other) const noexcept {
141 for(std::size_t i=0;i<flags.size();++i)
142 if((flags[i]&other.flags[i])!=other.flags[i]) return false;
143 return true;
144 }
145
146 constexpr bool valid() const noexcept {
147 constexpr auto used=feature_count%64;
148 constexpr auto mask=used ? (std::uint64_t{1}<<used)-1 : 0;
149 return (flags.back()&~mask)==0;
150 }
151
152 constexpr bool operator==(isa const &) const=default;
153 __declspec(property(get=get_mmx,put=set_mmx)) bool mmx;
154 __declspec(property(get=get_sse,put=set_sse)) bool sse;
155 __declspec(property(get=get_sse2,put=set_sse2)) bool sse2;
156 __declspec(property(get=get_sse3,put=set_sse3)) bool sse3;
157 __declspec(property(get=get_ssse3,put=set_ssse3)) bool ssse3;
158 __declspec(property(get=get_sse41,put=set_sse41)) bool sse41;
159 __declspec(property(get=get_sse42,put=set_sse42)) bool sse42;
160 __declspec(property(get=get_popcnt,put=set_popcnt)) bool popcnt;
161 __declspec(property(get=get_avx,put=set_avx)) bool avx;
162 __declspec(property(get=get_avx2,put=set_avx2)) bool avx2;
163 __declspec(property(get=get_fma,put=set_fma)) bool fma;
164 __declspec(property(get=get_f16c,put=set_f16c)) bool f16c;
165 __declspec(property(get=get_bmi1,put=set_bmi1)) bool bmi1;
166 __declspec(property(get=get_bmi2,put=set_bmi2)) bool bmi2;
167 __declspec(property(get=get_avx512f,put=set_avx512f)) bool avx512f;
168 __declspec(property(get=get_avx512dq,put=set_avx512dq)) bool avx512dq;
169 __declspec(property(get=get_avx512bw,put=set_avx512bw)) bool avx512bw;
170 __declspec(property(get=get_avx512vl,put=set_avx512vl)) bool avx512vl;
171 __declspec(property(get=get_avx512bf16,put=set_avx512bf16)) bool avx512bf16;
172 __declspec(property(get=get_avx512fp16,put=set_avx512fp16)) bool avx512fp16;
173 __declspec(property(get=get_aes,put=set_aes)) bool aes;
174 __declspec(property(get=get_pclmul,put=set_pclmul)) bool pclmul;
175 __declspec(property(get=get_cx16,put=set_cx16)) bool cx16;
176 __declspec(property(get=get_avx512cd,put=set_avx512cd)) bool avx512cd;
177 __declspec(property(get=get_avx512ifma,put=set_avx512ifma)) bool avx512ifma;
178 __declspec(property(get=get_lzcnt,put=set_lzcnt)) bool lzcnt;
179 __declspec(property(get=get_movbe,put=set_movbe)) bool movbe;
180 __declspec(property(get=get_sahf,put=set_sahf)) bool sahf;
181 __declspec(property(get=get_mwaitx,put=set_mwaitx)) bool mwaitx;
182 __declspec(property(get=get_waitpkg,put=set_waitpkg)) bool waitpkg;
183 __declspec(property(get=get_crc32,put=set_crc32)) bool crc32;
184 __declspec(property(get=get_gfni,put=set_gfni)) bool gfni;
185 __declspec(property(get=get_vpclmulqdq,put=set_vpclmulqdq)) bool vpclmulqdq;
186 __declspec(property(get=get_avx512vpopcntdq,put=set_avx512vpopcntdq)) bool avx512vpopcntdq;
187 __declspec(property(get=get_avxvnni,put=set_avxvnni)) bool avxvnni;
188 __declspec(property(get=get_avx512vnni,put=set_avx512vnni)) bool avx512vnni;
189 __declspec(property(get=get_avxvnniint8,put=set_avxvnniint8)) bool avxvnniint8;
190 __declspec(property(get=get_avxvnniint16,put=set_avxvnniint16)) bool avxvnniint16;
191 __declspec(property(get=get_avx512bitalg,put=set_avx512bitalg)) bool avx512bitalg;
192 __declspec(property(get=get_avx512vbmi,put=set_avx512vbmi)) bool avx512vbmi;
193 __declspec(property(get=get_avx512vbmi2,put=set_avx512vbmi2)) bool avx512vbmi2;
194 __declspec(property(get=get_sha,put=set_sha)) bool sha;
195 __declspec(property(get=get_vaes,put=set_vaes)) bool vaes;
196 __declspec(property(get=get_avxifma,put=set_avxifma)) bool avxifma;
197 __declspec(property(get=get_adx,put=set_adx)) bool adx;
198 __declspec(property(get=get_sha512,put=set_sha512)) bool sha512;
199 __declspec(property(get=get_sm3,put=set_sm3)) bool sm3;
200 __declspec(property(get=get_sm4,put=set_sm4)) bool sm4;
201 __declspec(property(get=get_avxneconvert,put=set_avxneconvert)) bool avxneconvert;
202 };
203
205 template<> struct isa<arm> {
207 using feature_type=typename detail::feature_traits<arm>::type;
209 static constexpr architecture family=arm;
211 static constexpr auto feature_count=detail::feature_traits<arm>::count;
213 std::array<std::uint64_t,(feature_count+1+63)/64> flags{};
215 constexpr isa() noexcept=default;
217 constexpr isa(feature_type f) noexcept { set(f,true); }
219 constexpr bool get(feature_type f) const noexcept {
220 auto i=std::uint64_t(f);
221 return i<feature_count && ((flags[i/64]>>(i%64))&1);
222 }
223
225 constexpr void set(feature_type f,bool value) noexcept {
226 auto i=std::uint64_t(f);
227 if(i>=feature_count) {
228 if(!value) return;
230 }
231 auto mask=std::uint64_t{1}<<(i%64);
232 auto & word=flags[i/64];
233 word=(word&~mask)|(value?mask:0);
234 }
235
236 constexpr bool has(feature_type f) const noexcept { return get(f); }
238 constexpr bool has(isa other) const noexcept {
239 for(std::size_t i=0;i<flags.size();++i)
240 if((flags[i]&other.flags[i])!=other.flags[i]) return false;
241 return true;
242 }
243
244 constexpr bool valid() const noexcept {
245 constexpr auto used=feature_count%64;
246 constexpr auto mask=used ? (std::uint64_t{1}<<used)-1 : 0;
247 return (flags.back()&~mask)==0;
248 }
249
250 constexpr bool operator==(isa const &) const=default;
251 __declspec(property(get=get_neon,put=set_neon)) bool neon;
252 __declspec(property(get=get_neon_fp16,put=set_neon_fp16)) bool neon_fp16;
253 __declspec(property(get=get_neon_bf16,put=set_neon_bf16)) bool neon_bf16;
254 __declspec(property(get=get_pmull,put=set_pmull)) bool pmull;
255 __declspec(property(get=get_sha1,put=set_sha1)) bool sha1;
256 __declspec(property(get=get_sha512,put=set_sha512)) bool sha512;
257 __declspec(property(get=get_ebf16,put=set_ebf16)) bool ebf16;
260 __declspec(property(get=get_sm3,put=set_sm3)) bool sm3;
263 __declspec(property(get=get_sm4,put=set_sm4)) bool sm4;
264 __declspec(property(get=get_aes,put=set_aes)) bool aes;
265 __declspec(property(get=get_sha2,put=set_sha2)) bool sha2;
266 __declspec(property(get=get_sha3,put=set_sha3)) bool sha3;
267 __declspec(property(get=get_crc,put=set_crc)) bool crc;
268 __declspec(property(get=get_lse,put=set_lse)) bool lse;
269 __declspec(property(get=get_rdm,put=set_rdm)) bool rdm;
270 __declspec(property(get=get_fp16fml,put=set_fp16fml)) bool fp16fml;
271 __declspec(property(get=get_dotprod,put=set_dotprod)) bool dotprod;
272 __declspec(property(get=get_complxnum,put=set_complxnum)) bool complxnum;
273 __declspec(property(get=get_jsconv,put=set_jsconv)) bool jsconv;
274 __declspec(property(get=get_rcpc,put=set_rcpc)) bool rcpc;
275 __declspec(property(get=get_pauth,put=set_pauth)) bool pauth;
276 __declspec(property(get=get_i8mm,put=set_i8mm)) bool i8mm;
277 };
278
280 template<> struct isa<wasm> {
282 using feature_type=typename detail::feature_traits<wasm>::type;
284 static constexpr architecture family=wasm;
286 static constexpr auto feature_count=detail::feature_traits<wasm>::count;
288 std::array<std::uint64_t,(feature_count+1+63)/64> flags{};
290 constexpr isa() noexcept=default;
292 constexpr isa(feature_type f) noexcept { set(f,true); }
294 constexpr bool get(feature_type f) const noexcept {
295 auto i=std::uint64_t(f);
296 return i<feature_count && ((flags[i/64]>>(i%64))&1);
297 }
298
300 constexpr void set(feature_type f,bool value) noexcept {
301 auto i=std::uint64_t(f);
302 if(i>=feature_count) {
303 if(!value) return;
305 }
306 auto mask=std::uint64_t{1}<<(i%64);
307 auto & word=flags[i/64];
308 word=(word&~mask)|(value?mask:0);
309 }
310
311 constexpr bool has(feature_type f) const noexcept { return get(f); }
313 constexpr bool has(isa other) const noexcept {
314 for(std::size_t i=0;i<flags.size();++i)
315 if((flags[i]&other.flags[i])!=other.flags[i]) return false;
316 return true;
317 }
318
319 constexpr bool valid() const noexcept {
320 constexpr auto used=feature_count%64;
321 constexpr auto mask=used ? (std::uint64_t{1}<<used)-1 : 0;
322 return (flags.back()&~mask)==0;
323 }
324
325 constexpr bool operator==(isa const &) const=default;
326 __declspec(property(get=get_simd128,put=set_simd128)) bool simd128;
327 __declspec(property(get=get_relaxed_simd,put=set_relaxed_simd)) bool relaxed_simd;
328 };
329
331 template<detail::instruction_feature E> isa(E)->isa<detail::family_of<E>>;
332
333 namespace detail {
334 template<class T> inline constexpr bool is_isa=false;
335 template<architecture Family> inline constexpr bool is_isa<isa<Family>> = true;
336 template<class T> struct arch_family;
337 template<instruction_feature E> struct arch_family<E> : std::integral_constant<architecture,family_of<E>> {};
338 template<architecture Family> struct arch_family<isa<Family>> : std::integral_constant<architecture,Family> {};
339 }
341 template<class T> concept arch=detail::instruction_feature<T> || detail::is_isa<T>;
342 namespace detail {
343 template<arch T> inline constexpr architecture arch_family_v=arch_family<T>::value;
344 template<class A,class B> concept same_arch=arch<A> && arch<B> && arch_family_v<A> == arch_family_v<B>;
345 }
346
348 template<arch A,arch B> requires detail::same_arch<A,B>
349 constexpr auto operator&(A left,B right) noexcept {
350 isa<detail::arch_family_v<A>> result=left, other=right;
351 for(std::size_t i=0;i<result.flags.size();++i) result.flags[i]|=other.flags[i];
352 return result;
353 }
354 // Concrete enum overloads prevent built-in ordinal comparisons from winning.
356 constexpr bool operator<(x86_feature,x86_feature) noexcept { return false; }
358 constexpr bool operator>(x86_feature,x86_feature) noexcept { return false; }
360 constexpr bool operator<=(x86_feature a,x86_feature b) noexcept { return a==b; }
362 constexpr bool operator>=(x86_feature a,x86_feature b) noexcept { return a==b; }
364 constexpr bool operator<(arm_feature,arm_feature) noexcept { return false; }
366 constexpr bool operator>(arm_feature,arm_feature) noexcept { return false; }
368 constexpr bool operator<=(arm_feature a,arm_feature b) noexcept { return a==b; }
370 constexpr bool operator>=(arm_feature a,arm_feature b) noexcept { return a==b; }
372 constexpr bool operator<(wasm_feature,wasm_feature) noexcept { return false; }
374 constexpr bool operator>(wasm_feature,wasm_feature) noexcept { return false; }
376 constexpr bool operator<=(wasm_feature a,wasm_feature b) noexcept { return a==b; }
378 constexpr bool operator>=(wasm_feature a,wasm_feature b) noexcept { return a==b; }
380 template<arch A,arch B> requires detail::same_arch<A,B>
381 constexpr bool operator<=(A a,B b) noexcept { return isa<detail::arch_family_v<A>>(b).has(a); }
383 template<arch A,arch B> requires detail::same_arch<A,B>
384 constexpr bool operator>=(A a,B b) noexcept { return b<=a; }
386 template<arch A,arch B> requires detail::same_arch<A,B>
387 constexpr bool operator<(A a,B b) noexcept { return isa<detail::arch_family_v<A>>(a)!=isa<detail::arch_family_v<A>>(b) && a<=b; }
389 template<arch A,arch B> requires detail::same_arch<A,B>
390 constexpr bool operator>(A a,B b) noexcept { return b<a; }
391
393 // Explicit constraints let Clang merge the header with an imported declaration.
394 template<auto A,auto... Choices>
395 requires arch<decltype(A)> && ((detail::same_arch<decltype(A),decltype(Choices)>) && ...)
396 inline constexpr int target=[]() consteval {
397 using value_type=isa<detail::arch_family_v<decltype(A)>>;
398 constexpr std::array<value_type,sizeof...(Choices)> choices{value_type(Choices)...};
399 static_assert([&] {
400 for(std::size_t i=0;i<choices.size();++i)
401 for(std::size_t j=i+1;j<choices.size();++j)
402 if(choices[i]<=choices[j]) return false;
403 return true;
404 }(),"a later target is shadowed by an earlier one");
405 for(std::size_t i=0;i<choices.size();++i)
406 if(choices[i]<=value_type(A)) return int(i);
407 return -1;
408 }();
409
410 namespace detail {
411 template<architecture Family>
412 constexpr isa<Family> intersection(isa<Family> a,isa<Family> b) noexcept {
413 for(std::size_t i=0;i<a.flags.size();++i) a.flags[i]&=b.flags[i];
414 return a;
415 }
416 enum class feature_register { leaf1_ecx, leaf1_edx, leaf7_ebx, leaf7_ecx, leaf7_edx, leaf7_1_eax, leaf7_1_edx, extended1_ecx, arm, wasm };
417 template<architecture Family> struct feature_record {
418 isa<Family> value;
419 std::string_view spelling;
420 isa<Family> implies;
421 feature_register location;
422 static constexpr architecture family=Family;
423 unsigned bit;
424 std::size_t index;
425 isa<Family> target_implies;
426 bool targetable;
427 constexpr feature_record(typename feature_traits<Family>::type f,std::string_view spelling,isa<Family> implies,
428 feature_register location,unsigned bit,isa<Family> target_implies={},bool targetable=true) noexcept:
429 value(f),spelling(spelling),implies(implies),location(location),bit(bit),index(std::size_t(f)),
430 target_implies(target_implies),targetable(targetable) {}
431 };
432 // Hardware prerequisites and compiler bundles are recorded separately.
433 template<architecture Family> inline constexpr auto feature_registry=std::array<feature_record<Family>,0>{};
434 template<> inline constexpr auto feature_registry<x86> = std::to_array<feature_record<x86>>({
435 {x86_feature::mmx,"mmx",{},feature_register::leaf1_edx,23},
436 {x86_feature::sse,"sse",isa(x86_feature::mmx),feature_register::leaf1_edx,25},
437 {x86_feature::sse2,"sse2",isa(x86_feature::sse),feature_register::leaf1_edx,26},
438 {x86_feature::sse3,"sse3",isa(x86_feature::sse2),feature_register::leaf1_ecx,0},
439 {x86_feature::ssse3,"ssse3",isa(x86_feature::sse3),feature_register::leaf1_ecx,9},
440 {x86_feature::sse41,"sse4.1",isa(x86_feature::ssse3),feature_register::leaf1_ecx,19},
441 {x86_feature::sse42,"sse4.2",x86_feature::sse41&x86_feature::popcnt&x86_feature::crc32,feature_register::leaf1_ecx,20},
442 {x86_feature::popcnt,"popcnt",{},feature_register::leaf1_ecx,23},
443 {x86_feature::avx,"avx",isa(x86_feature::sse42),feature_register::leaf1_ecx,28},
444 {x86_feature::avx2,"avx2",isa(x86_feature::avx),feature_register::leaf7_ebx,5},
445 {x86_feature::fma,"fma",isa(x86_feature::avx),feature_register::leaf1_ecx,12},
446 {x86_feature::f16c,"f16c",isa(x86_feature::avx),feature_register::leaf1_ecx,29},
447 {x86_feature::bmi1,"bmi",{},feature_register::leaf7_ebx,3},
448 {x86_feature::bmi2,"bmi2",{},feature_register::leaf7_ebx,8},
449 {x86_feature::mwaitx,"mwaitx",{},feature_register::extended1_ecx,29},
450 {x86_feature::waitpkg,"waitpkg",{},feature_register::leaf7_ecx,5},
451 {x86_feature::crc32,"crc32",{},feature_register::leaf1_ecx,20},
452 {x86_feature::gfni,"gfni",isa(x86_feature::sse2),feature_register::leaf7_ecx,8},
453 {x86_feature::avx512f,"avx512f",x86_feature::avx2&x86_feature::f16c&x86_feature::fma,feature_register::leaf7_ebx,16},
454 {x86_feature::avx512dq,"avx512dq",isa(x86_feature::avx512f),feature_register::leaf7_ebx,17},
455 {x86_feature::avx512bw,"avx512bw",isa(x86_feature::avx512f),feature_register::leaf7_ebx,30},
456 {x86_feature::avx512vl,"avx512vl",isa(x86_feature::avx512f),feature_register::leaf7_ebx,31},
457 {x86_feature::avx512bf16,"avx512bf16",isa(x86_feature::avx512bw),feature_register::leaf7_1_eax,5},
458 {x86_feature::avx512fp16,"avx512fp16",isa(x86_feature::avx512bw),feature_register::leaf7_edx,23},
459 {x86_feature::avx512vbmi,"avx512vbmi",isa(x86_feature::avx512bw),feature_register::leaf7_ecx,1},
460 {x86_feature::avx512vbmi2,"avx512vbmi2",isa(x86_feature::avx512bw),feature_register::leaf7_ecx,6},
461 {x86_feature::avx512bitalg,"avx512bitalg",isa(x86_feature::avx512bw),feature_register::leaf7_ecx,12},
462 {x86_feature::avx512vpopcntdq,"avx512vpopcntdq",isa(x86_feature::avx512f),feature_register::leaf7_ecx,14},
463 {x86_feature::avxvnni,"avxvnni",isa(x86_feature::avx2),feature_register::leaf7_1_eax,4},
464 {x86_feature::avx512vnni,"avx512vnni",isa(x86_feature::avx512f),feature_register::leaf7_ecx,11},
465 {x86_feature::avxvnniint8,"avxvnniint8",isa(x86_feature::avx2),feature_register::leaf7_1_edx,4},
466 {x86_feature::avxvnniint16,"avxvnniint16",isa(x86_feature::avx2),feature_register::leaf7_1_edx,10},
467 {x86_feature::aes,"aes",isa(x86_feature::sse2),feature_register::leaf1_ecx,25},
468 {x86_feature::pclmul,"pclmul",isa(x86_feature::sse2),feature_register::leaf1_ecx,1},
469 {x86_feature::sha,"sha",isa(x86_feature::sse2),feature_register::leaf7_ebx,29},
470 {x86_feature::vaes,"vaes",isa(x86_feature::avx),feature_register::leaf7_ecx,9,
471 x86_feature::aes&x86_feature::avx2},
472 {x86_feature::vpclmulqdq,"vpclmulqdq",x86_feature::avx&x86_feature::pclmul,feature_register::leaf7_ecx,10},
473 {x86_feature::cx16,"cx16",{},feature_register::leaf1_ecx,13},
474 {x86_feature::avx512cd,"avx512cd",isa(x86_feature::avx512f),feature_register::leaf7_ebx,28},
475 {x86_feature::avx512ifma,"avx512ifma",isa(x86_feature::avx512f),feature_register::leaf7_ebx,21},
476 {x86_feature::avxifma,"avxifma",isa(x86_feature::avx),feature_register::leaf7_1_eax,23,isa(x86_feature::avx2)},
477 {x86_feature::adx,"adx",{},feature_register::leaf7_ebx,19},
478 {x86_feature::sha512,"sha512",isa(x86_feature::avx),feature_register::leaf7_1_eax,0,isa(x86_feature::avx2)},
479 {x86_feature::sm3,"sm3",isa(x86_feature::avx),feature_register::leaf7_1_eax,1},
480 {x86_feature::sm4,"sm4",isa(x86_feature::avx),feature_register::leaf7_1_eax,2,isa(x86_feature::avx2)},
481 {x86_feature::avxneconvert,"avxneconvert",isa(x86_feature::avx),feature_register::leaf7_1_edx,5,isa(x86_feature::avx2)},
482 {x86_feature::lzcnt,"lzcnt",{},feature_register::extended1_ecx,5},
483 {x86_feature::movbe,"movbe",{},feature_register::leaf1_ecx,22},
484 {x86_feature::sahf,"sahf",{},feature_register::extended1_ecx,0}
485 });
486 template<> inline constexpr auto feature_registry<arm> = std::to_array<feature_record<arm>>({
487 {arm_feature::neon,"neon",{},feature_register::arm,0},
488 {arm_feature::neon_fp16,"fullfp16",isa(arm_feature::neon),feature_register::arm,1},
489 {arm_feature::neon_bf16,"bf16",isa(arm_feature::neon),feature_register::arm,2},
490 {arm_feature::aes,"aes",isa(arm_feature::neon),feature_register::arm,3,isa(arm_feature::pmull)},
491 {arm_feature::sha2,"sha2",isa(arm_feature::neon),feature_register::arm,4,isa(arm_feature::sha1)},
492 {arm_feature::sha3,"sha3",isa(arm_feature::neon),feature_register::arm,5,arm_feature::sha1&arm_feature::sha2&arm_feature::sha512},
493 {arm_feature::crc,"crc",{},feature_register::arm,6},
494 {arm_feature::lse,"lse",isa(arm_feature::neon),feature_register::arm,7},
495 {arm_feature::rdm,"rdm",isa(arm_feature::neon),feature_register::arm,8},
496 {arm_feature::fp16fml,"fp16fml",isa(arm_feature::neon_fp16),feature_register::arm,9},
497 {arm_feature::dotprod,"dotprod",isa(arm_feature::neon),feature_register::arm,10},
498 {arm_feature::complxnum,"complxnum",isa(arm_feature::neon),feature_register::arm,11},
499 {arm_feature::jsconv,"jsconv",isa(arm_feature::neon),feature_register::arm,12},
500 {arm_feature::rcpc,"rcpc",isa(arm_feature::neon),feature_register::arm,13},
501 {arm_feature::pauth,"pauth",isa(arm_feature::neon),feature_register::arm,14},
502 {arm_feature::i8mm,"i8mm",isa(arm_feature::neon),feature_register::arm,15},
503 {arm_feature::pmull,"pmull",isa(arm_feature::neon),feature_register::arm,16,{},false},
504 {arm_feature::sha1,"sha1",isa(arm_feature::neon),feature_register::arm,17,{},false},
505 {arm_feature::sha512,"sha512",isa(arm_feature::neon),feature_register::arm,18,{},false},
506 {arm_feature::ebf16,"ebf16",isa(arm_feature::neon_bf16),feature_register::arm,19,{},false},
507 {arm_feature::sm3,"sm3",isa(arm_feature::neon),feature_register::arm,20,{},false},
508 {arm_feature::sm4,"sm4",isa(arm_feature::neon),feature_register::arm,21,isa(arm_feature::sm3)}
509 });
510 template<> inline constexpr auto feature_registry<wasm> = std::to_array<feature_record<wasm>>({
511 {wasm_feature::simd128,"simd128",{},feature_register::wasm,0},
512 {wasm_feature::relaxed_simd,"relaxed-simd",isa(wasm_feature::simd128),feature_register::wasm,1}
513 });
514 template<architecture Family> inline constexpr isa<Family> known_features=[] {
515 isa<Family> result;
516 for(auto const & entry:feature_registry<Family>) result=result&entry.value;
517 return result;
518 }();
519 template<instruction_feature E> inline constexpr auto family_features=known_features<family_of<E>>;
520 inline constexpr auto arm_features=known_features<arm>;
521 inline constexpr auto x86_features=known_features<x86>;
522 inline constexpr auto wasm_features=known_features<wasm>;
523 template<architecture Family> inline constexpr isa<Family> invalid_features=[] {
524 isa<Family> result;
525 constexpr auto index=feature_traits<Family>::count;
526 result.flags[index/64]|=std::uint64_t{1}<<(index%64);
527 return result;
528 }();
529 // Shared source constraints remain equivalent across repeated declarations.
530 template<isa<> A> inline constexpr isa<> source_isa=[]() consteval {
531 static_assert(A<=known_features<target_arch>,"source target contains an unregistered ISA feature");
532 return A;
533 }();
534 }
535
538 template<arch A> constexpr auto feature_closure(A input) noexcept {
539 constexpr auto family=detail::arch_family_v<A>;
540 isa<family> bits=input, previous;
541 do {
542 previous=bits;
543 for(auto const & entry:detail::feature_registry<family>)
544 if(bits.has(entry.value)) bits=bits&entry.implies;
545 } while(previous!=bits);
546 return bits;
547 }
548
549 inline constexpr isa<> scalar{};
550 inline constexpr auto avx2=feature_closure(x86_feature::avx2&x86_feature::fma);
551 inline constexpr auto avx512=feature_closure(avx2&x86_feature::avx512f&x86_feature::avx512dq&x86_feature::avx512bw&x86_feature::avx512vl);
552 inline constexpr auto avx512_bf16=feature_closure(avx512&x86_feature::avx512bf16);
553 inline constexpr auto avx512_fp16=feature_closure(avx512&x86_feature::avx512fp16);
554 inline constexpr auto neon=feature_closure(arm_feature::neon);
555 inline constexpr auto neon_fp16=feature_closure(arm_feature::neon_fp16);
556 inline constexpr auto neon_bf16=feature_closure(arm_feature::neon_bf16);
557
560 template<architecture Family=target_arch>
561 constexpr isa<Family> target_features(std::string_view text) noexcept {
562 if(text.empty()) return {};
563 isa<Family> bits;
564 while(!text.empty()) {
565 auto comma=text.find(',');
566 auto token=text.substr(0,comma);
567 bool found=false;
568 for(auto const & entry:detail::feature_registry<Family>) if(entry.targetable && token.compare(entry.spelling)==0) {
569 bits=bits&entry.value&entry.target_implies; found=true; break;
570 }
571 if(!found) return detail::invalid_features<Family>;
572 if(comma==std::string_view::npos) break;
573 text.remove_prefix(comma+1);
574 if(text.empty()) return detail::invalid_features<Family>;
575 }
576 return feature_closure(bits);
577 }
578
579 template<architecture Family=target_arch> struct isa_admission {
580 isa<Family> missing_features{};
581 std::uint64_t missing_xcr0=0;
582 bool invalid_features=false;
583 bool missing_xcr0_observation=false;
585 constexpr bool admitted() const noexcept {
586 return missing_features==isa<Family>{} && !missing_xcr0 && !invalid_features && !missing_xcr0_observation;
587 }
588
591 constexpr char const * reason() const noexcept {
592 if(invalid_features) return "invalid ISA features";
593 for(auto const & entry:detail::feature_registry<Family>)
594 if(missing_features.has(entry.value)) return entry.spelling.data();
595 if(missing_xcr0_observation) return "XCR0 unavailable";
596 if(missing_xcr0 & (1ull<<1)) return "XMM state unavailable";
597 if(missing_xcr0 & (1ull<<2)) return "YMM state unavailable";
598 if(missing_xcr0 & (1ull<<5)) return "opmask state unavailable";
599 if(missing_xcr0 & (1ull<<6)) return "ZMM high state unavailable";
600 if(missing_xcr0 & (1ull<<7)) return "high ZMM registers unavailable";
601 return admitted() ? "admitted" : "ISA requirements unavailable";
602 }
603 };
604
605 namespace detail {
606 template<class C> concept x86_observation=requires(C const & c) {
607 c.max_basic_leaf; c.leaf1_ecx; c.leaf1_edx; c.leaf7_ebx;
608 c.max_leaf7_subleaf; c.leaf7_1_eax; c.leaf7_edx;
609 };
610 template<class C> concept arm_observation=requires(C const & c) {
611 c.baseline_observed; c.fp; c.asimd;
612 c.fp16_observed; c.scalar_fp16; c.vector_fp16;
613 c.bf16_observed; c.bf16;
614 };
615 template<class C,architecture Family> concept normalized_features=requires(C const & c) {
616 { c.present } -> std::same_as<isa<Family> const &>;
617 { c.observed } -> std::same_as<isa<Family> const &>;
618 };
619 template<class C> concept has_feature_observation=requires(C const & c) { c.present; c.observed; };
620 template<architecture Family> struct feature_observation {
621 isa<Family> present{},observed{};
622 };
623 template<x86_observation C>
624 constexpr feature_observation<x86> decode_x86_features(C const & cpu) noexcept {
625 feature_observation<x86> result;
626 for(auto const & entry:feature_registry<x86>) {
627 std::uint32_t word=0;
628 bool observed=false;
629 switch(entry.location) {
630 case feature_register::leaf1_ecx: observed=cpu.max_basic_leaf>=1; word=cpu.leaf1_ecx; break;
631 case feature_register::leaf1_edx: observed=cpu.max_basic_leaf>=1; word=cpu.leaf1_edx; break;
632 case feature_register::leaf7_ebx: observed=cpu.max_basic_leaf>=7; word=cpu.leaf7_ebx; break;
633 case feature_register::leaf7_ecx:
634 if constexpr(requires { cpu.leaf7_ecx; }) {
635 observed=cpu.max_basic_leaf>=7; word=cpu.leaf7_ecx;
636 }
637 break;
638 case feature_register::leaf7_edx: observed=cpu.max_basic_leaf>=7; word=cpu.leaf7_edx; break;
639 case feature_register::leaf7_1_eax:
640 observed=cpu.max_basic_leaf>=7 && cpu.max_leaf7_subleaf>=1; word=cpu.leaf7_1_eax; break;
641 case feature_register::leaf7_1_edx:
642 if constexpr(requires { cpu.leaf7_1_edx; }) {
643 observed=cpu.max_basic_leaf>=7 && cpu.max_leaf7_subleaf>=1; word=cpu.leaf7_1_edx;
644 }
645 break;
646 case feature_register::extended1_ecx:
647 if constexpr(requires { cpu.max_extended_leaf; cpu.extended1_ecx; }) {
648 observed=cpu.max_extended_leaf>=0x80000001u; word=cpu.extended1_ecx;
649 }
650 break;
651 case feature_register::arm: case feature_register::wasm: continue;
652 }
653 auto f=static_cast<x86_feature>(entry.index);
654 result.observed.set(f,observed);
655 result.present.set(f,observed && (word&(std::uint32_t{1}<<entry.bit)));
656 }
657 return result;
658 }
659 template<arm_observation C>
660 constexpr feature_observation<arm> decode_arm_features(C const & cpu) noexcept {
661 feature_observation<arm> result;
662 result.observed.set(arm_feature::neon,cpu.baseline_observed);
663 result.present.set(arm_feature::neon,cpu.baseline_observed && cpu.fp && cpu.asimd);
664 result.observed.set(arm_feature::neon_fp16,cpu.fp16_observed);
665 result.present.set(arm_feature::neon_fp16,cpu.fp16_observed && cpu.scalar_fp16 && cpu.vector_fp16);
666 result.observed.set(arm_feature::neon_bf16,cpu.bf16_observed);
667 result.present.set(arm_feature::neon_bf16,cpu.bf16_observed && cpu.bf16);
668 if constexpr(requires { cpu.ebf16_observed; cpu.ebf16; }) {
669 result.observed.set(arm_feature::ebf16,cpu.ebf16_observed);
670 result.present.set(arm_feature::ebf16,cpu.ebf16_observed && cpu.ebf16);
671 }
672 constexpr auto baseline=arm_feature::neon&arm_feature::neon_fp16&arm_feature::neon_bf16&arm_feature::ebf16;
673 if constexpr(requires { cpu.extra_observed; cpu.extra_features; })
674 for(auto const & entry:feature_registry<arm>) {
675 if(baseline.has(entry.value)) continue;
676 auto f=static_cast<arm_feature>(entry.index);
677 auto observed=cpu.extra_observed.has(f);
678 result.observed.set(f,observed);
679 result.present.set(f,observed && cpu.extra_features.has(f));
680 }
681 return result;
682 }
683 template<architecture Family>
684 constexpr isa_admission<Family> classify_features(isa<Family> present,isa<Family> observed,isa<Family> bits) noexcept {
685 isa_admission<Family> result;
686 auto known=known_features<Family>;
687 result.invalid_features=!present.valid() || !observed.valid() || !(bits<=known);
688 auto available=intersection(present,observed);
689 result.missing_features=intersection(bits,known);
690 for(std::size_t i=0;i<available.flags.size();++i)
691 result.missing_features.flags[i]&=~available.flags[i];
692 return result;
693 }
694 constexpr isa_admission<x86> classify_x86_features(isa<x86> present,
695 isa<x86> observed,std::uint64_t xcr0,bool readable,isa<x86> bits) noexcept {
696 auto result=classify_features(present,observed,bits);
697 if(bits.has(x86_feature::avx)) {
698 result.missing_xcr0_observation=!readable;
699 result.missing_xcr0=(bits.has(x86_feature::avx512f)?0xe6ull:0x6ull)&~(readable?xcr0:0ull);
700 }
701 return result;
702 }
703 }
704
708 template<class C> requires detail::normalized_features<C,x86> && requires(C const & c) { c.xcr0; c.xcr0_observed; }
709 constexpr isa_admission<x86> classify_isa(C const & cpu,isa<x86> requested,isa<x86> minimum={}) noexcept {
710 return detail::classify_x86_features(cpu.present,cpu.observed,cpu.xcr0,cpu.xcr0_observed,
711 feature_closure(requested&minimum));
712 }
713
716 template<class C> requires detail::normalized_features<C,arm>
717 constexpr isa_admission<arm> classify_isa(C const & cpu,isa<arm> requested,isa<arm> minimum={}) noexcept {
718 return detail::classify_features(cpu.present,cpu.observed,feature_closure(requested&minimum));
719 }
720
723 template<class C> requires detail::normalized_features<C,wasm>
724 constexpr isa_admission<wasm> classify_isa(C const & runtime,isa<wasm> requested,isa<wasm> minimum={}) noexcept {
725 return detail::classify_features(runtime.present,runtime.observed,feature_closure(requested&minimum));
726 }
727
730 template<detail::x86_observation C> requires (!detail::has_feature_observation<C>) && requires(C const & c) { c.xcr0; c.xcr0_observed; }
731 constexpr isa_admission<x86> classify_isa(C const & cpu,isa<x86> requested,isa<x86> minimum={}) noexcept {
732 auto features=detail::decode_x86_features(cpu);
733 bool readable=cpu.max_basic_leaf>=1 && (cpu.leaf1_ecx&(1u<<26)) &&
734 (cpu.leaf1_ecx&(1u<<27)) && cpu.xcr0_observed;
735 return detail::classify_x86_features(features.present,features.observed,cpu.xcr0,readable,
736 feature_closure(requested&minimum));
737 }
738
741 template<detail::arm_observation C> requires (!detail::has_feature_observation<C>)
742 constexpr isa_admission<arm> classify_isa(C const & cpu,isa<arm> requested,isa<arm> minimum={}) noexcept {
743 auto features=detail::decode_arm_features(cpu);
744 return detail::classify_features(features.present,features.observed,feature_closure(requested&minimum));
745 }
746
748 template<architecture Family=target_arch> struct target_entry {
749 isa<Family> architecture;
750 isa<Family> minimum{};
752 constexpr bool operator==(target_entry const &) const = default;
753 };
754
755 template<architecture Family> target_entry(isa<Family>,isa<Family> = {})->target_entry<Family>;
757 template<detail::instruction_feature E> target_entry(E)->target_entry<detail::family_of<E>>;
759 template<arch A,arch B> requires detail::same_arch<A,B>
760 target_entry(A,B)->target_entry<detail::arch_family_v<A>>;
761 template<auto... Entries> struct isa_list {};
763 template<auto... A,auto... B>
764 constexpr isa_list<A...,B...> operator+(isa_list<A...>,isa_list<B...>) noexcept { return {}; }
765
766 namespace detail {
767 template<auto E,int I> struct abi_match {
768 static constexpr auto entry=[] {
769 if constexpr(arch<std::remove_cv_t<decltype(E)>>) return target_entry<arch_family_v<std::remove_cv_t<decltype(E)>>>{E};
770 else return E;
771 }();
772 static constexpr auto architecture=entry.architecture;
773 static constexpr auto minimum=entry.minimum;
774 static_assert(architecture<=known_features<decltype(architecture)::family>,"ABI policy contains an unregistered ISA feature");
775 static_assert(minimum<=known_features<decltype(minimum)::family>,"ABI policy minimum contains an unregistered ISA feature");
776 static constexpr auto required_features=feature_closure(architecture&minimum);
777 static constexpr bool matched=true;
778 static constexpr int index=I;
779 };
780 template<isa A,int I,auto... Entries> struct abi_lookup_impl {
781 static constexpr bool matched=false;
782 static constexpr int index=-1;
783 static constexpr decltype(A) architecture{},minimum{},required_features{};
784 };
785 template<isa A,int I,auto E,auto... Rest>
786 struct abi_lookup_impl<A,I,E,Rest...> : std::conditional_t<
787 abi_match<E,I>::required_features<=A,
788 abi_match<E,I>,abi_lookup_impl<A,I+1,Rest...>> {};
789 }
792 template<isa A,class List> struct abi_lookup;
793 template<isa A,auto... Entries>
794 requires ((decltype(detail::abi_match<Entries,0>::architecture)::family==decltype(A)::family) && ...)
795 struct abi_lookup<A,isa_list<Entries...>> : detail::abi_lookup_impl<A,0,Entries...> {};
796
797 namespace detail {
798 template<class C> concept capability_observation=
799 normalized_features<C,x86> || normalized_features<C,arm> || normalized_features<C,wasm> ||
800 x86_observation<C> || arm_observation<C>;
801 template<capability_observation C> inline constexpr architecture observation_family=[] {
802 if constexpr(normalized_features<C,x86>) return x86;
803 else if constexpr(normalized_features<C,arm>) return arm;
804 else if constexpr(normalized_features<C,wasm>) return wasm;
805 else if constexpr(x86_observation<C>) return x86;
806 else return arm;
807 }();
808 }
810 template<auto... Entries,detail::capability_observation C,class F>
811 requires ((decltype(detail::abi_match<Entries,0>::architecture)::family==detail::observation_family<C>) && ...)
812 constexpr bool with_isa(isa_list<Entries...>,C const & cpu,F && callback,isa<detail::observation_family<C>> minimum={}) {
813 bool selected=false;
814 auto try_entry=[&]<auto E>() {
815 using entry=detail::abi_match<E,0>;
816 if(!selected && classify_isa(cpu,entry::architecture,minimum&entry::minimum).admitted()) {
817 selected=true;
818 std::forward<F>(callback).template operator()<entry::architecture>();
819 }
820 };
821 (try_entry.template operator()<Entries>(),...);
822 return selected;
823 }
824}
A feature enum or an ISA value from one architecture family.
Definition isa.h:341
constexpr std::uint32_t crc32(std::uint32_t accumulator, std::uint8_t value) noexcept
Update the CRC32 accumulator with exactly 8 input bits.
Definition crc.h:28
constexpr simd< std::uint64_t, 2, Arch > pmull(std::uint64_t a, std::uint64_t b) noexcept
std::string_view const type
typename mask_traits< std::remove_cvref_t< T > >::type mask
Definition mask_traits.h:22
constexpr std::uint16_t lzcnt(std::uint16_t value) noexcept
Definition lzcnt.h:24
constexpr std::uint16_t popcnt(std::uint16_t value) noexcept
Definition popcnt.h:24
constexpr simd< std::uint64_t, 2, Arch > vpclmulqdq(simd< std::uint64_t, 2, Arch > a, simd< std::uint64_t, 2, Arch > b) noexcept
Multiply selected halves of one 128-bit lane using PCLMUL and AVX.
Architecture-tagged vectors, register packs and supporting value types. Native arithmetic follows its...
constexpr std::size_t arm_feature_count
Number of named ARM feature values.
Definition isa.h:36
constexpr architecture arm
Select ARM feature metadata independently of the compilation target.
Definition config.h:28
constexpr architecture x86
Select x86 feature metadata independently of the compilation target.
Definition config.h:26
void operator>=(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator>(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
x86_feature
Architecture-specific instruction features, represented by local bit indices.
Definition isa.h:15
architecture
Instruction-set families; an ISA value belongs to exactly one family.
Definition config.h:24
target_entry(isa< Family >, isa< Family >={}) -> target_entry< Family >
Deduce a source record from same-family ISA values.
constexpr auto feature_closure(A input) noexcept
Definition isa.h:538
constexpr architecture wasm
Select WebAssembly feature metadata independently of the compilation target.
Definition config.h:30
constexpr simd< fp16, 32, Arch > fma(simd< fp16, 32, Arch > a, simd< fp16, 32, Arch > b, simd< fp16, 32, Arch > c) noexcept
void operator<=(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
constexpr std::size_t x86_feature_count
Number of named x86 feature values.
Definition isa.h:34
constexpr isa_admission< x86 > classify_isa(C const &cpu, isa< x86 > requested, isa< x86 > minimum={}) noexcept
Definition isa.h:709
@ unknown
Any other vendor string.
constexpr int target
First matching requirement, with every later choice checked for shadowing.
Definition isa.h:396
void operator&(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator+(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
constexpr isa< Family > target_features(std::string_view text) noexcept
Definition isa.h:561
wasm_feature
WebAssembly validation capabilities, using local bit indices.
Definition isa.h:30
void operator<(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
constexpr std::size_t wasm_feature_count
Number of named Wasm feature values.
Definition isa.h:32
arm_feature
Independently observable ARM instruction features, using local bit indices.
Definition isa.h:24
isa(E) -> isa< detail::family_of< E > >
Deduce the family from a feature enum; explicit isa<> always names the host family.
bool neon
Read or update the neon feature bit through flags.
Definition isa.h:251
constexpr bool has(isa other) const noexcept
True when every bit in a same-family requirement is present.
Definition isa.h:238
typename detail::feature_traits< arm >::type feature_type
Feature enum accepted by this ISA family.
Definition isa.h:207
static constexpr auto feature_count
Number of registered features in this family.
Definition isa.h:211
bool lse
Read or update the lse feature bit through flags.
Definition isa.h:268
bool i8mm
Read or update the i8mm feature bit through flags.
Definition isa.h:276
bool fp16fml
Read or update the fp16fml feature bit through flags.
Definition isa.h:270
std::array< std::uint64_t,(feature_count+1+63)/64 > flags
Public structural bits; invalid enum values and padding fail validation.
Definition isa.h:213
constexpr bool valid() const noexcept
True when no invalid marker or unregistered padding bit is set.
Definition isa.h:244
static constexpr architecture family
Architecture family, independent of the compiler target.
Definition isa.h:209
bool neon_bf16
Read or update the neon_bf16 feature bit through flags.
Definition isa.h:253
bool sha1
Read or update the sha1 feature bit through flags.
Definition isa.h:255
constexpr bool get(feature_type f) const noexcept
Read one feature; out-of-range values are absent.
Definition isa.h:219
bool pauth
Read or update the pauth feature bit through flags.
Definition isa.h:275
constexpr bool has(feature_type f) const noexcept
True when the feature is present.
Definition isa.h:236
bool aes
Read or update the aes feature bit through flags.
Definition isa.h:264
constexpr void set(feature_type f, bool value) noexcept
Definition isa.h:225
bool sha3
Read or update the sha3 feature bit through flags.
Definition isa.h:266
bool jsconv
Read or update the jsconv feature bit through flags.
Definition isa.h:273
constexpr isa() noexcept=default
Construct the empty requirement set.
bool crc
Read or update the crc feature bit through flags.
Definition isa.h:267
bool sha512
Read or update the sha512 feature bit through flags.
Definition isa.h:256
bool rcpc
Read or update the rcpc feature bit through flags.
Definition isa.h:274
bool sm4
Read or update the sm4 feature bit through flags.
Definition isa.h:263
bool sha2
Read or update the sha2 feature bit through flags.
Definition isa.h:265
bool neon_fp16
Read or update the neon_fp16 feature bit through flags.
Definition isa.h:252
bool complxnum
Read or update the complxnum feature bit through flags.
Definition isa.h:272
bool pmull
Read or update the pmull feature bit through flags.
Definition isa.h:254
bool dotprod
Read or update the dotprod feature bit through flags.
Definition isa.h:271
constexpr bool operator==(isa const &) const =default
Compare every stored bit, including invalid requirements.
bool rdm
Read or update the rdm feature bit through flags.
Definition isa.h:269
constexpr void set(feature_type f, bool value) noexcept
Definition isa.h:300
constexpr isa() noexcept=default
Construct the empty requirement set.
bool simd128
Read or update the simd128 feature bit through flags.
Definition isa.h:326
constexpr bool has(feature_type f) const noexcept
True when the feature is present.
Definition isa.h:311
constexpr bool operator==(isa const &) const =default
Compare every stored bit, including invalid requirements.
std::array< std::uint64_t,(feature_count+1+63)/64 > flags
Public structural bits; invalid enum values and padding fail validation.
Definition isa.h:288
constexpr bool valid() const noexcept
True when no invalid marker or unregistered padding bit is set.
Definition isa.h:319
static constexpr architecture family
Architecture family, independent of the compiler target.
Definition isa.h:284
typename detail::feature_traits< wasm >::type feature_type
Feature enum accepted by this ISA family.
Definition isa.h:282
static constexpr auto feature_count
Number of registered features in this family.
Definition isa.h:286
constexpr bool get(feature_type f) const noexcept
Read one feature; out-of-range values are absent.
Definition isa.h:294
bool relaxed_simd
Read or update the relaxed_simd feature bit through flags.
Definition isa.h:327
constexpr bool has(isa other) const noexcept
True when every bit in a same-family requirement is present.
Definition isa.h:313
bool lzcnt
Read or update the lzcnt feature bit through flags.
Definition isa.h:178
bool sse42
Read or update the sse42 feature bit through flags.
Definition isa.h:159
bool sha512
Read or update the sha512 feature bit through flags.
Definition isa.h:198
bool avx512bw
Read or update the avx512bw feature bit through flags.
Definition isa.h:169
bool bmi1
Read or update the bmi1 feature bit through flags.
Definition isa.h:165
bool avx512dq
Read or update the avx512dq feature bit through flags.
Definition isa.h:168
typename detail::feature_traits< x86 >::type feature_type
Feature enum accepted by this ISA family.
Definition isa.h:109
bool crc32
Read or update the crc32 feature bit through flags.
Definition isa.h:183
bool sse2
Read or update the sse2 feature bit through flags.
Definition isa.h:155
bool avx512f
Read or update the avx512f feature bit through flags.
Definition isa.h:167
bool sse
Read or update the sse feature bit through flags.
Definition isa.h:154
bool f16c
Read or update the f16c feature bit through flags.
Definition isa.h:164
static constexpr auto feature_count
Number of registered features in this family.
Definition isa.h:113
bool avx512bitalg
Read or update the avx512bitalg feature bit through flags.
Definition isa.h:191
bool ssse3
Read or update the ssse3 feature bit through flags.
Definition isa.h:157
bool sm3
Read or update the sm3 feature bit through flags.
Definition isa.h:199
bool avxifma
Read or update the avxifma feature bit through flags.
Definition isa.h:196
bool avx512fp16
Read or update the avx512fp16 feature bit through flags.
Definition isa.h:172
bool popcnt
Read or update the popcnt feature bit through flags.
Definition isa.h:160
bool avxneconvert
Read or update the avxneconvert feature bit through flags.
Definition isa.h:201
bool adx
Read or update the adx feature bit through flags.
Definition isa.h:197
bool avx
Read or update the avx feature bit through flags.
Definition isa.h:161
bool sha
Read or update the sha feature bit through flags.
Definition isa.h:194
bool avx512vl
Read or update the avx512vl feature bit through flags.
Definition isa.h:170
bool avx512bf16
Read or update the avx512bf16 feature bit through flags.
Definition isa.h:171
bool avxvnniint8
Read or update the avxvnniint8 feature bit through flags.
Definition isa.h:189
bool avx512ifma
Read or update the avx512ifma feature bit through flags.
Definition isa.h:177
bool fma
Read or update the fma feature bit through flags.
Definition isa.h:163
bool avx512vbmi2
Read or update the avx512vbmi2 feature bit through flags.
Definition isa.h:193
bool avx2
Read or update the avx2 feature bit through flags.
Definition isa.h:162
constexpr bool operator==(isa const &) const =default
Compare every stored bit, including invalid requirements.
constexpr isa() noexcept=default
Construct the empty requirement set.
bool aes
Read or update the aes feature bit through flags.
Definition isa.h:173
constexpr bool valid() const noexcept
True when no invalid marker or unregistered padding bit is set.
Definition isa.h:146
bool avxvnniint16
Read or update the avxvnniint16 feature bit through flags.
Definition isa.h:190
bool cx16
Read or update the cx16 feature bit through flags.
Definition isa.h:175
bool sm4
Read or update the sm4 feature bit through flags.
Definition isa.h:200
bool mmx
Read or update the mmx feature bit through flags.
Definition isa.h:153
constexpr bool has(feature_type f) const noexcept
True when the feature is present.
Definition isa.h:138
bool vpclmulqdq
Read or update the vpclmulqdq feature bit through flags.
Definition isa.h:185
constexpr bool has(isa other) const noexcept
True when every bit in a same-family requirement is present.
Definition isa.h:140
bool sse41
Read or update the sse41 feature bit through flags.
Definition isa.h:158
std::array< std::uint64_t,(feature_count+1+63)/64 > flags
Public structural bits; invalid enum values and padding fail validation.
Definition isa.h:115
bool avx512vnni
Read or update the avx512vnni feature bit through flags.
Definition isa.h:188
bool gfni
Read or update the gfni feature bit through flags.
Definition isa.h:184
static constexpr architecture family
Architecture family, independent of the compiler target.
Definition isa.h:111
bool mwaitx
Read or update the mwaitx feature bit through flags.
Definition isa.h:181
bool sahf
Read or update the sahf feature bit through flags.
Definition isa.h:180
constexpr bool get(feature_type f) const noexcept
Read one feature; out-of-range values are absent.
Definition isa.h:121
bool avx512vbmi
Read or update the avx512vbmi feature bit through flags.
Definition isa.h:192
bool avx512vpopcntdq
Read or update the avx512vpopcntdq feature bit through flags.
Definition isa.h:186
constexpr void set(feature_type f, bool value) noexcept
Definition isa.h:127
bool waitpkg
Read or update the waitpkg feature bit through flags.
Definition isa.h:182
bool pclmul
Read or update the pclmul feature bit through flags.
Definition isa.h:174
bool vaes
Read or update the vaes feature bit through flags.
Definition isa.h:195
bool avx512cd
Read or update the avx512cd feature bit through flags.
Definition isa.h:176
bool sse3
Read or update the sse3 feature bit through flags.
Definition isa.h:156
bool avxvnni
Read or update the avxvnni feature bit through flags.
Definition isa.h:187
bool movbe
Read or update the movbe feature bit through flags.
Definition isa.h:179
bool bmi2
Read or update the bmi2 feature bit through flags.
Definition isa.h:166
Admission result for requirements from one architecture family.
Definition isa.h:579
constexpr char const * reason() const noexcept
Definition isa.h:591
constexpr bool admitted() const noexcept
True only when every requested feature and OS state component is present.
Definition isa.h:585
A structural set of one family's features, without prerequisite closure.
Definition isa.h:58
static constexpr auto feature_count
Definition isa.h:64
constexpr bool has(feature_type f) const noexcept
True when the feature is present.
Definition isa.h:89
constexpr isa() noexcept=default
Construct the empty requirement set.
static constexpr architecture family
Definition isa.h:62
constexpr bool operator==(isa const &) const =default
Compare every stored bit, including invalid requirements.
std::array< std::uint64_t,(feature_count+1+63)/64 > flags
Definition isa.h:66
constexpr void set(feature_type f, bool value) noexcept
Definition isa.h:78
typename detail::feature_traits< Family >::type feature_type
Definition isa.h:60
constexpr bool has(isa other) const noexcept
True when every bit in a same-family requirement is present.
Definition isa.h:91
constexpr bool get(feature_type f) const noexcept
Read one feature; out-of-range values are absent.
Definition isa.h:72
constexpr bool valid() const noexcept
True when no invalid marker or unregistered padding bit is set.
Definition isa.h:97
waiter using the MONITORX/MWAITX instruction feature
A source variant retains its requested ISA and inherited compiler minimum.
Definition isa.h:748
constexpr bool operator==(target_entry const &) const =default
Compare the requested ISA and inherited compiler minimum exactly.