4#include "native/config.h"
10namespace native::detail::x86_ifma {
12 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avxifma) && Arch.has(x86_feature::avx))
14 __m128i madd52lo(__m128i accumulator, __m128i a, __m128i b) noexcept {
15 return _mm_madd52lo_avx_epu64(accumulator, a, b);
18 template<isa<x86> Arch>
requires(!(Arch.has(x86_feature::avxifma) && Arch.has(x86_feature::avx)) &&
19 Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
20 Arch.has(x86_feature::avx512vl))
22 __m128i madd52lo(__m128i accumulator, __m128i a, __m128i b) noexcept {
23 return _mm_madd52lo_epu64(accumulator, a, b);
26 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avxifma) && Arch.has(x86_feature::avx))
28 __m256i madd52lo(__m256i accumulator, __m256i a, __m256i b) noexcept {
29 return _mm256_madd52lo_avx_epu64(accumulator, a, b);
32 template<isa<x86> Arch>
requires(!(Arch.has(x86_feature::avxifma) && Arch.has(x86_feature::avx)) &&
33 Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
34 Arch.has(x86_feature::avx512vl))
36 __m256i madd52lo(__m256i accumulator, __m256i a, __m256i b) noexcept {
37 return _mm256_madd52lo_epu64(accumulator, a, b);
40 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma))
42 __m512i madd52lo(__m512i accumulator, __m512i a, __m512i b) noexcept {
43 return _mm512_madd52lo_epu64(accumulator, a, b);
46 template<isa<x86> Arch,
class... Args>
47 void madd52lo(Args...) =
delete;
49 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
50 Arch.has(x86_feature::avx512vl))
52 __m128i mask_madd52lo(__m128i accumulator, __mmask8
mask, __m128i a, __m128i b) noexcept {
53 return _mm_mask_madd52lo_epu64(accumulator,
mask, a, b);
56 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
57 Arch.has(x86_feature::avx512vl))
59 __m256i mask_madd52lo(__m256i accumulator, __mmask8
mask, __m256i a, __m256i b) noexcept {
60 return _mm256_mask_madd52lo_epu64(accumulator,
mask, a, b);
63 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma))
65 __m512i mask_madd52lo(__m512i accumulator, __mmask8
mask, __m512i a, __m512i b) noexcept {
66 return _mm512_mask_madd52lo_epu64(accumulator,
mask, a, b);
69 template<isa<x86> Arch,
class... Args>
70 void mask_madd52lo(Args...) =
delete;
72 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
73 Arch.has(x86_feature::avx512vl))
75 __m128i maskz_madd52lo(__mmask8
mask, __m128i accumulator, __m128i a, __m128i b) noexcept {
76 return _mm_maskz_madd52lo_epu64(
mask, accumulator, a, b);
79 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
80 Arch.has(x86_feature::avx512vl))
82 __m256i maskz_madd52lo(__mmask8
mask, __m256i accumulator, __m256i a, __m256i b) noexcept {
83 return _mm256_maskz_madd52lo_epu64(
mask, accumulator, a, b);
86 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma))
88 __m512i maskz_madd52lo(__mmask8
mask, __m512i accumulator, __m512i a, __m512i b) noexcept {
89 return _mm512_maskz_madd52lo_epu64(
mask, accumulator, a, b);
92 template<isa<x86> Arch,
class... Args>
93 void maskz_madd52lo(Args...) =
delete;
95 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avxifma) && Arch.has(x86_feature::avx))
97 __m128i madd52hi(__m128i accumulator, __m128i a, __m128i b) noexcept {
98 return _mm_madd52hi_avx_epu64(accumulator, a, b);
101 template<isa<x86> Arch>
requires(!(Arch.has(x86_feature::avxifma) && Arch.has(x86_feature::avx)) &&
102 Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
103 Arch.has(x86_feature::avx512vl))
105 __m128i madd52hi(__m128i accumulator, __m128i a, __m128i b) noexcept {
106 return _mm_madd52hi_epu64(accumulator, a, b);
109 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avxifma) && Arch.has(x86_feature::avx))
111 __m256i madd52hi(__m256i accumulator, __m256i a, __m256i b) noexcept {
112 return _mm256_madd52hi_avx_epu64(accumulator, a, b);
115 template<isa<x86> Arch>
requires(!(Arch.has(x86_feature::avxifma) && Arch.has(x86_feature::avx)) &&
116 Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
117 Arch.has(x86_feature::avx512vl))
119 __m256i madd52hi(__m256i accumulator, __m256i a, __m256i b) noexcept {
120 return _mm256_madd52hi_epu64(accumulator, a, b);
123 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma))
125 __m512i madd52hi(__m512i accumulator, __m512i a, __m512i b) noexcept {
126 return _mm512_madd52hi_epu64(accumulator, a, b);
129 template<isa<x86> Arch,
class... Args>
130 void madd52hi(Args...) =
delete;
132 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
133 Arch.has(x86_feature::avx512vl))
135 __m128i mask_madd52hi(__m128i accumulator, __mmask8
mask, __m128i a, __m128i b) noexcept {
136 return _mm_mask_madd52hi_epu64(accumulator,
mask, a, b);
139 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
140 Arch.has(x86_feature::avx512vl))
142 __m256i mask_madd52hi(__m256i accumulator, __mmask8
mask, __m256i a, __m256i b) noexcept {
143 return _mm256_mask_madd52hi_epu64(accumulator,
mask, a, b);
146 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma))
148 __m512i mask_madd52hi(__m512i accumulator, __mmask8
mask, __m512i a, __m512i b) noexcept {
149 return _mm512_mask_madd52hi_epu64(accumulator,
mask, a, b);
152 template<isa<x86> Arch,
class... Args>
153 void mask_madd52hi(Args...) =
delete;
155 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
156 Arch.has(x86_feature::avx512vl))
158 __m128i maskz_madd52hi(__mmask8
mask, __m128i accumulator, __m128i a, __m128i b) noexcept {
159 return _mm_maskz_madd52hi_epu64(
mask, accumulator, a, b);
162 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
163 Arch.has(x86_feature::avx512vl))
165 __m256i maskz_madd52hi(__mmask8
mask, __m256i accumulator, __m256i a, __m256i b) noexcept {
166 return _mm256_maskz_madd52hi_epu64(
mask, accumulator, a, b);
169 template<isa<x86> Arch>
requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma))
171 __m512i maskz_madd52hi(__mmask8
mask, __m512i accumulator, __m512i a, __m512i b) noexcept {
172 return _mm512_maskz_madd52hi_epu64(
mask, accumulator, a, b);
175 template<isa<x86> Arch,
class... Args>
176 void maskz_madd52hi(Args...) =
delete;
180#include "native/x86/integer_constant.h"
182namespace native::detail::x86_ifma_constant {
184 constexpr std::uint64_t product(std::uint64_t a, std::uint64_t b)
noexcept {
185 constexpr std::uint64_t mask26 = (std::uint64_t{1} << 26) - 1;
186 constexpr std::uint64_t mask52 = (std::uint64_t{1} << 52) - 1;
189 auto low = (a & mask26) * (b & mask26);
190 auto middle = (a >> 26) * (b & mask26) + (a & mask26) * (b >> 26);
191 low += (middle & mask26) << 26;
192 if constexpr (High) {
193 return (a >> 26) * (b >> 26) + (middle >> 26) + (low >> 52);
199 template<
bool High,
class V>
200 constexpr V accumulate(V accumulator, V a, V b, std::uint64_t
mask,
bool zero)
noexcept {
201 auto result = x86_instruction_constant::lanes(accumulator);
202 auto left = x86_instruction_constant::lanes(a);
203 auto right = x86_instruction_constant::lanes(b);
204 for (
unsigned lane = 0; lane < V::lanes; ++lane) {
205 if ((
mask >> lane) & 1) {
206 result[lane] += product<High>(left[lane], right[lane]);
211 return V::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