4#include "native/config.h"
7#include "native/arm/detail/register_order.h"
11#if NATIVE_HOST_NEON || defined(NATIVE_DOXYGEN)
12namespace native::detail::arm_bf16 {
21 template<isa<arm> Arch>
22 requires(Arch.has(arm_feature::neon_bf16))
24 float32x2_t bfdot(float32x2_t acc, bfloat16x4_t a, bfloat16x4_t b) noexcept {
25 acc = ::native::detail::arm_register_order(acc);
26 a = ::native::detail::arm_register_order(a);
27 auto source = ::native::detail::arm_register_order(b);
28 asm volatile(
"bfdot %0.2s, %1.4h, %2.4h"
29 :
"+w"(acc) :
"w"(a),
"w"(source) :
"memory");
30 return ::native::detail::arm_register_order(acc);
33 template<isa<arm> Arch,
unsigned Lane>
34 requires(Arch.has(arm_feature::neon_bf16) && Lane < 2)
36 float32x2_t bfdot_lane(float32x2_t acc, bfloat16x4_t a, bfloat16x4_t b) noexcept {
37 acc = ::native::detail::arm_register_order(acc);
38 a = ::native::detail::arm_register_order(a);
39 auto source = ::native::detail::arm_register_order(__builtin_shufflevector(b, b, 0, 1, 2, 3, -1, -1, -1, -1));
40 asm volatile(
"bfdot %0.2s, %1.4h, %2.2h[%3]"
41 :
"+w"(acc) :
"w"(a),
"w"(source),
"i"(Lane) :
"memory");
42 return ::native::detail::arm_register_order(acc);
45 template<isa<arm> Arch,
unsigned Lane>
46 requires(Arch.has(arm_feature::neon_bf16) && Lane < 4)
48 float32x2_t bfdot_lane(float32x2_t acc, bfloat16x4_t a, bfloat16x8_t b) noexcept {
49 acc = ::native::detail::arm_register_order(acc);
50 a = ::native::detail::arm_register_order(a);
51 auto source = ::native::detail::arm_register_order(b);
52 asm volatile(
"bfdot %0.2s, %1.4h, %2.2h[%3]"
53 :
"+w"(acc) :
"w"(a),
"w"(source),
"i"(Lane) :
"memory");
54 return ::native::detail::arm_register_order(acc);
57 template<isa<arm> Arch>
58 requires(Arch.has(arm_feature::neon_bf16))
60 float32x4_t bfdot(float32x4_t acc, bfloat16x8_t a, bfloat16x8_t b) noexcept {
61 acc = ::native::detail::arm_register_order(acc);
62 a = ::native::detail::arm_register_order(a);
63 auto source = ::native::detail::arm_register_order(b);
64 asm volatile(
"bfdot %0.4s, %1.8h, %2.8h"
65 :
"+w"(acc) :
"w"(a),
"w"(source) :
"memory");
66 return ::native::detail::arm_register_order(acc);
69 template<isa<arm> Arch,
unsigned Lane>
70 requires(Arch.has(arm_feature::neon_bf16) && Lane < 2)
72 float32x4_t bfdot_lane(float32x4_t acc, bfloat16x8_t a, bfloat16x4_t b) noexcept {
73 acc = ::native::detail::arm_register_order(acc);
74 a = ::native::detail::arm_register_order(a);
75 auto source = ::native::detail::arm_register_order(__builtin_shufflevector(b, b, 0, 1, 2, 3, -1, -1, -1, -1));
76 asm volatile(
"bfdot %0.4s, %1.8h, %2.2h[%3]"
77 :
"+w"(acc) :
"w"(a),
"w"(source),
"i"(Lane) :
"memory");
78 return ::native::detail::arm_register_order(acc);
81 template<isa<arm> Arch,
unsigned Lane>
82 requires(Arch.has(arm_feature::neon_bf16) && Lane < 4)
84 float32x4_t bfdot_lane(float32x4_t acc, bfloat16x8_t a, bfloat16x8_t b) noexcept {
85 acc = ::native::detail::arm_register_order(acc);
86 a = ::native::detail::arm_register_order(a);
87 auto source = ::native::detail::arm_register_order(b);
88 asm volatile(
"bfdot %0.4s, %1.8h, %2.2h[%3]"
89 :
"+w"(acc) :
"w"(a),
"w"(source),
"i"(Lane) :
"memory");
90 return ::native::detail::arm_register_order(acc);
93 template<isa<arm> Arch>
94 requires(Arch.has(arm_feature::neon_bf16))
96 float32x4_t bfmmla(float32x4_t acc, bfloat16x8_t a, bfloat16x8_t b) noexcept {
97 acc = ::native::detail::arm_register_order(acc);
98 a = ::native::detail::arm_register_order(a);
99 auto source = ::native::detail::arm_register_order(b);
100 asm volatile(
"bfmmla %0.4s, %1.8h, %2.8h"
101 :
"+w"(acc) :
"w"(a),
"w"(source) :
"memory");
102 return ::native::detail::arm_register_order(acc);
105 template<isa<arm> Arch>
106 requires(Arch.has(arm_feature::neon_bf16))
108 float32x4_t bfmlalb(float32x4_t acc, bfloat16x8_t a, bfloat16x8_t b) noexcept {
109 acc = ::native::detail::arm_register_order(acc);
110 a = ::native::detail::arm_register_order(a);
111 auto source = ::native::detail::arm_register_order(b);
112 asm volatile(
"bfmlalb %0.4s, %1.8h, %2.8h"
113 :
"+w"(acc) :
"w"(a),
"w"(source) :
"memory");
114 return ::native::detail::arm_register_order(acc);
117 template<isa<arm> Arch,
unsigned Lane>
118 requires(Arch.has(arm_feature::neon_bf16) && Lane < 4)
120 float32x4_t bfmlalb_lane(float32x4_t acc, bfloat16x8_t a, bfloat16x4_t b) noexcept {
121 acc = ::native::detail::arm_register_order(acc);
122 a = ::native::detail::arm_register_order(a);
123 auto source = ::native::detail::arm_register_order(__builtin_shufflevector(b, b, 0, 1, 2, 3, -1, -1, -1, -1));
124 asm volatile(
"bfmlalb %0.4s, %1.8h, %2.h[%3]"
125 :
"+w"(acc) :
"w"(a),
"x"(source),
"i"(Lane) :
"memory");
126 return ::native::detail::arm_register_order(acc);
129 template<isa<arm> Arch,
unsigned Lane>
130 requires(Arch.has(arm_feature::neon_bf16) && Lane < 8)
132 float32x4_t bfmlalb_lane(float32x4_t acc, bfloat16x8_t a, bfloat16x8_t b) noexcept {
133 acc = ::native::detail::arm_register_order(acc);
134 a = ::native::detail::arm_register_order(a);
135 auto source = ::native::detail::arm_register_order(b);
136 asm volatile(
"bfmlalb %0.4s, %1.8h, %2.h[%3]"
137 :
"+w"(acc) :
"w"(a),
"x"(source),
"i"(Lane) :
"memory");
138 return ::native::detail::arm_register_order(acc);
141 template<isa<arm> Arch>
142 requires(Arch.has(arm_feature::neon_bf16))
144 float32x4_t bfmlalt(float32x4_t acc, bfloat16x8_t a, bfloat16x8_t b) noexcept {
145 acc = ::native::detail::arm_register_order(acc);
146 a = ::native::detail::arm_register_order(a);
147 auto source = ::native::detail::arm_register_order(b);
148 asm volatile(
"bfmlalt %0.4s, %1.8h, %2.8h"
149 :
"+w"(acc) :
"w"(a),
"w"(source) :
"memory");
150 return ::native::detail::arm_register_order(acc);
153 template<isa<arm> Arch,
unsigned Lane>
154 requires(Arch.has(arm_feature::neon_bf16) && Lane < 4)
156 float32x4_t bfmlalt_lane(float32x4_t acc, bfloat16x8_t a, bfloat16x4_t b) noexcept {
157 acc = ::native::detail::arm_register_order(acc);
158 a = ::native::detail::arm_register_order(a);
159 auto source = ::native::detail::arm_register_order(__builtin_shufflevector(b, b, 0, 1, 2, 3, -1, -1, -1, -1));
160 asm volatile(
"bfmlalt %0.4s, %1.8h, %2.h[%3]"
161 :
"+w"(acc) :
"w"(a),
"x"(source),
"i"(Lane) :
"memory");
162 return ::native::detail::arm_register_order(acc);
165 template<isa<arm> Arch,
unsigned Lane>
166 requires(Arch.has(arm_feature::neon_bf16) && Lane < 8)
168 float32x4_t bfmlalt_lane(float32x4_t acc, bfloat16x8_t a, bfloat16x8_t b) noexcept {
169 acc = ::native::detail::arm_register_order(acc);
170 a = ::native::detail::arm_register_order(a);
171 auto source = ::native::detail::arm_register_order(b);
172 asm volatile(
"bfmlalt %0.4s, %1.8h, %2.h[%3]"
173 :
"+w"(acc) :
"w"(a),
"x"(source),
"i"(Lane) :
"memory");
174 return ::native::detail::arm_register_order(acc);
179 template<isa<arm> Arch,
class R,
class A,
class B>
void bfdot(R, A, B) =
delete;
180 template<isa<arm> Arch,
class R,
class A,
class B>
void bfmmla(R, A, B) =
delete;
181 template<isa<arm> Arch,
class R,
class A,
class B>
void bfmlalb(R, A, B) =
delete;
182 template<isa<arm> Arch,
class R,
class A,
class B>
void bfmlalt(R, A, B) =
delete;
183 template<isa<arm> Arch,
unsigned Lane,
class R,
class A,
class B>
void bfdot_lane(R, A, B) =
delete;
184 template<isa<arm> Arch,
unsigned Lane,
class R,
class A,
class B>
void bfmlalb_lane(R, A, B) =
delete;
185 template<isa<arm> Arch,
unsigned Lane,
class R,
class A,
class B>
void bfmlalt_lane(R, A, B) =
delete;
Compiler attributes for host code, with shader-safe shared modifiers.
constexpr simd< float, 4, Arch > bfmlalt_lane(simd< float, 4, Arch > acc, simd< bf16, 8, Arch > a, simd< bf16, 4, Arch > b) noexcept
Fused multiply-add of the odd lanes of a with b[Lane] shared by all output lanes.
constexpr simd< float, 2, Arch > bfdot_lane(simd< float, 2, Arch > acc, simd< bf16, 4, Arch > a, simd< bf16, 4, Arch > b) noexcept
BFDOT with the BF16 pair b[2*Lane], b[2*Lane+1] shared by all output lanes.
constexpr simd< float, 4, Arch > bfmlalb(simd< float, 4, Arch > acc, simd< bf16, 8, Arch > a, simd< bf16, 8, Arch > b) noexcept
Fused multiply-add of the even BF16 lanes into the corresponding FP32 lanes.
constexpr simd< float, 4, Arch > bfmlalb_lane(simd< float, 4, Arch > acc, simd< bf16, 8, Arch > a, simd< bf16, 4, Arch > b) noexcept
Fused multiply-add of the even lanes of a with b[Lane] shared by all output lanes.
constexpr simd< float, 4, Arch > bfmmla(simd< float, 4, Arch > acc, simd< bf16, 8, Arch > a, simd< bf16, 8, Arch > b) noexcept
Accumulate a row-major 2x4 matrix times a column-major 4x2 matrix, two BFDOT steps per result.
constexpr simd< float, 4, Arch > bfmlalt(simd< float, 4, Arch > acc, simd< bf16, 8, Arch > a, simd< bf16, 8, Arch > b) noexcept
Fused multiply-add of the odd BF16 lanes into the corresponding FP32 lanes.
constexpr simd< float, 2, Arch > bfdot(simd< float, 2, Arch > acc, simd< bf16, 4, Arch > a, simd< bf16, 4, Arch > b) noexcept
Accumulate each adjacent pair of BF16 products into the corresponding FP32 lane.
#define native_inline
inline [[always_inline]]
#define native_nodiscard
C++17 [[nodiscard]].
constexpr int target
First matching requirement, with every later choice checked for shadowing.