native 0.0.1
Vectors, masks and wide register packs for C++26
Loading...
Searching...
No Matches
ifma.h
1// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0
2#pragma once
3
4#include "native/config.h"
5#include "native/attributes.h"
6#include "native/isa.h"
7#if NATIVE_HOST_X86
8#include <immintrin.h>
9
10namespace native::detail::x86_ifma {
11
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);
16 }
17
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))
21 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
22 __m128i madd52lo(__m128i accumulator, __m128i a, __m128i b) noexcept {
23 return _mm_madd52lo_epu64(accumulator, a, b);
24 }
25
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);
30 }
31
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))
35 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
36 __m256i madd52lo(__m256i accumulator, __m256i a, __m256i b) noexcept {
37 return _mm256_madd52lo_epu64(accumulator, a, b);
38 }
39
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);
44 }
45
46 template<isa<x86> Arch, class... Args>
47 void madd52lo(Args...) = delete;
48
49 template<isa<x86> Arch> requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
50 Arch.has(x86_feature::avx512vl))
51 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
52 __m128i mask_madd52lo(__m128i accumulator, __mmask8 mask, __m128i a, __m128i b) noexcept {
53 return _mm_mask_madd52lo_epu64(accumulator, mask, a, b);
54 }
55
56 template<isa<x86> Arch> requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
57 Arch.has(x86_feature::avx512vl))
58 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
59 __m256i mask_madd52lo(__m256i accumulator, __mmask8 mask, __m256i a, __m256i b) noexcept {
60 return _mm256_mask_madd52lo_epu64(accumulator, mask, a, b);
61 }
62
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);
67 }
68
69 template<isa<x86> Arch, class... Args>
70 void mask_madd52lo(Args...) = delete;
71
72 template<isa<x86> Arch> requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
73 Arch.has(x86_feature::avx512vl))
74 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
75 __m128i maskz_madd52lo(__mmask8 mask, __m128i accumulator, __m128i a, __m128i b) noexcept {
76 return _mm_maskz_madd52lo_epu64(mask, accumulator, a, b);
77 }
78
79 template<isa<x86> Arch> requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
80 Arch.has(x86_feature::avx512vl))
81 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
82 __m256i maskz_madd52lo(__mmask8 mask, __m256i accumulator, __m256i a, __m256i b) noexcept {
83 return _mm256_maskz_madd52lo_epu64(mask, accumulator, a, b);
84 }
85
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);
90 }
91
92 template<isa<x86> Arch, class... Args>
93 void maskz_madd52lo(Args...) = delete;
94
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);
99 }
100
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))
104 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
105 __m128i madd52hi(__m128i accumulator, __m128i a, __m128i b) noexcept {
106 return _mm_madd52hi_epu64(accumulator, a, b);
107 }
108
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);
113 }
114
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))
118 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
119 __m256i madd52hi(__m256i accumulator, __m256i a, __m256i b) noexcept {
120 return _mm256_madd52hi_epu64(accumulator, a, b);
121 }
122
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);
127 }
128
129 template<isa<x86> Arch, class... Args>
130 void madd52hi(Args...) = delete;
131
132 template<isa<x86> Arch> requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
133 Arch.has(x86_feature::avx512vl))
134 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
135 __m128i mask_madd52hi(__m128i accumulator, __mmask8 mask, __m128i a, __m128i b) noexcept {
136 return _mm_mask_madd52hi_epu64(accumulator, mask, a, b);
137 }
138
139 template<isa<x86> Arch> requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
140 Arch.has(x86_feature::avx512vl))
141 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
142 __m256i mask_madd52hi(__m256i accumulator, __mmask8 mask, __m256i a, __m256i b) noexcept {
143 return _mm256_mask_madd52hi_epu64(accumulator, mask, a, b);
144 }
145
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);
150 }
151
152 template<isa<x86> Arch, class... Args>
153 void mask_madd52hi(Args...) = delete;
154
155 template<isa<x86> Arch> requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
156 Arch.has(x86_feature::avx512vl))
157 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
158 __m128i maskz_madd52hi(__mmask8 mask, __m128i accumulator, __m128i a, __m128i b) noexcept {
159 return _mm_maskz_madd52hi_epu64(mask, accumulator, a, b);
160 }
161
162 template<isa<x86> Arch> requires(Arch.has(x86_feature::avx512f) && Arch.has(x86_feature::avx512ifma) &&
163 Arch.has(x86_feature::avx512vl))
164 native_nodiscard native_inline native_const native_target("avx512f,avx512ifma,avx512vl")
165 __m256i maskz_madd52hi(__mmask8 mask, __m256i accumulator, __m256i a, __m256i b) noexcept {
166 return _mm256_maskz_madd52hi_epu64(mask, accumulator, a, b);
167 }
168
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);
173 }
174
175 template<isa<x86> Arch, class... Args>
176 void maskz_madd52hi(Args...) = delete;
177}
178#endif
179
180#include "native/x86/integer_constant.h"
181
182namespace native::detail::x86_ifma_constant {
183 template<bool High>
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;
187 a &= mask52;
188 b &= mask52;
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);
194 } else {
195 return low & mask52;
196 }
197 }
198
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]);
207 } else if (zero) {
208 result[lane] = 0;
209 }
210 }
211 return V::load(result.data());
212 }
213}
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