4#include "native/config.h"
12namespace native::detail {
14 constexpr U bmi1_extract(U value,
unsigned start,
unsigned length)
noexcept {
15 constexpr unsigned width =
sizeof(U) * 8;
18 if (start >= width)
return 0;
19 auto shifted = U(value >> start);
20 return length >= width - start ? shifted : U(shifted & ((U{1} << length) - U{1}));
32 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
34 constexpr
std::uint32_t
andn(
std::uint32_t first,
std::uint32_t second) noexcept {
35 if (__builtin_is_constant_evaluated()) {
36 return (~first) & second;
38 return _andn_u32(first, second);
42 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
44 constexpr std::uint64_t
andn(std::uint64_t first, std::uint64_t second)
noexcept {
45 if (__builtin_is_constant_evaluated()) {
46 return (~first) & second;
48 return _andn_u64(first, second);
54 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
56 constexpr std::uint32_t
bextr(std::uint32_t value, std::uint32_t control)
noexcept {
57 if (__builtin_is_constant_evaluated()) {
58 return detail::bmi1_extract(value, control & 255u, (control >> 8) & 255u);
60 return _bextr2_u32(value, control);
64 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
66 constexpr std::uint64_t
bextr(std::uint64_t value, std::uint32_t control)
noexcept {
67 if (__builtin_is_constant_evaluated()) {
68 return detail::bmi1_extract(value, control & 255u, (control >> 8) & 255u);
70 return _bextr2_u64(value, control);
74 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
76 constexpr std::uint32_t
bextr(std::uint32_t value,
unsigned start,
unsigned length)
noexcept {
77 if (__builtin_is_constant_evaluated()) {
78 return detail::bmi1_extract(value, start, length);
80 return _bextr_u32(value, start, length);
84 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
86 constexpr std::uint64_t
bextr(std::uint64_t value,
unsigned start,
unsigned length)
noexcept {
87 if (__builtin_is_constant_evaluated()) {
88 return detail::bmi1_extract(value, start, length);
90 return _bextr_u64(value, start, length);
95 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
97 constexpr std::uint32_t
blsi(std::uint32_t value)
noexcept {
98 if (__builtin_is_constant_evaluated()) {
99 return value & (std::uint32_t{0} - value);
101 return _blsi_u32(value);
105 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
107 constexpr std::uint64_t
blsi(std::uint64_t value)
noexcept {
108 if (__builtin_is_constant_evaluated()) {
109 return value & (std::uint64_t{0} - value);
111 return _blsi_u64(value);
116 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
118 constexpr std::uint32_t
blsmsk(std::uint32_t value)
noexcept {
119 if (__builtin_is_constant_evaluated()) {
120 return value ^ (value - std::uint32_t{1});
122 return _blsmsk_u32(value);
126 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
128 constexpr std::uint64_t
blsmsk(std::uint64_t value)
noexcept {
129 if (__builtin_is_constant_evaluated()) {
130 return value ^ (value - std::uint64_t{1});
132 return _blsmsk_u64(value);
137 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
139 constexpr std::uint32_t
blsr(std::uint32_t value)
noexcept {
140 if (__builtin_is_constant_evaluated()) {
141 return value & (value - std::uint32_t{1});
143 return _blsr_u32(value);
147 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
149 constexpr std::uint64_t
blsr(std::uint64_t value)
noexcept {
150 if (__builtin_is_constant_evaluated()) {
151 return value & (value - std::uint64_t{1});
153 return _blsr_u64(value);
158 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
160 constexpr std::uint16_t
tzcnt(std::uint16_t value)
noexcept {
161 if (__builtin_is_constant_evaluated()) {
162 return static_cast<std::uint16_t
>(std::countr_zero(value));
164 return _tzcnt_u16(value);
168 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
170 constexpr std::uint32_t
tzcnt(std::uint32_t value)
noexcept {
171 if (__builtin_is_constant_evaluated()) {
172 return static_cast<std::uint32_t
>(std::countr_zero(value));
174 return _tzcnt_u32(value);
178 template<isa<x86> Arch>
requires(Arch.has(x86_feature::bmi1))
180 constexpr std::uint64_t
tzcnt(std::uint64_t value)
noexcept {
181 if (__builtin_is_constant_evaluated()) {
182 return static_cast<std::uint64_t
>(std::countr_zero(value));
184 return _tzcnt_u64(value);
189 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
191 consteval std::uint32_t
andn(std::uint32_t first, std::uint32_t second)
noexcept {
196 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
198 consteval std::uint64_t
andn(std::uint64_t first, std::uint64_t second)
noexcept {
203 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
205 consteval std::uint32_t
bextr(std::uint32_t value, std::uint32_t control)
noexcept {
210 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
212 consteval std::uint64_t
bextr(std::uint64_t value, std::uint32_t control)
noexcept {
217 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
219 consteval std::uint32_t
bextr(std::uint32_t value,
unsigned start,
unsigned length)
noexcept {
224 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
226 consteval std::uint64_t
bextr(std::uint64_t value,
unsigned start,
unsigned length)
noexcept {
231 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
233 consteval std::uint32_t
blsi(std::uint32_t value)
noexcept {
238 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
240 consteval std::uint64_t
blsi(std::uint64_t value)
noexcept {
245 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
247 consteval std::uint32_t
blsmsk(std::uint32_t value)
noexcept {
252 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
254 consteval std::uint64_t
blsmsk(std::uint64_t value)
noexcept {
259 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
261 consteval std::uint32_t
blsr(std::uint32_t value)
noexcept {
266 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
268 consteval std::uint64_t
blsr(std::uint64_t value)
noexcept {
273 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
275 consteval std::uint16_t
tzcnt(std::uint16_t value)
noexcept {
280 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
282 consteval std::uint32_t
tzcnt(std::uint32_t value)
noexcept {
287 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::bmi1))
289 consteval std::uint64_t
tzcnt(std::uint64_t value)
noexcept {
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
constexpr std::uint32_t andn(std::uint32_t first, std::uint32_t second) noexcept
ANDN: complement the first operand, then AND with the second.
constexpr std::uint32_t bextr(std::uint32_t value, std::uint32_t control) noexcept
constexpr std::uint16_t tzcnt(std::uint16_t value) noexcept
TZCNT: count low zero bits; zero returns the operand width, including 16-bit operands.
constexpr std::uint32_t blsmsk(std::uint32_t value) noexcept
BLSMSK: set every bit through the lowest set bit; zero produces all ones.
constexpr std::uint32_t blsr(std::uint32_t value) noexcept
BLSR: clear the lowest set bit; zero remains zero.
constexpr std::uint32_t blsi(std::uint32_t value) noexcept
BLSI: retain only the lowest set bit; zero remains zero.
Architecture-tagged vectors, register packs and supporting value types. Native arithmetic follows its...
constexpr int target
First matching requirement, with every later choice checked for shadowing.
Standard-library adaptations documented here for SIMD value types.