blob: 4552bc52f1a2a2480c3ed8f8c0a97a50a8dd3ce8 [file] [edit]
#!/usr/bin/env python3
# Copyright 2025 Google LLC
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
from gemm_compiler import avx512f_template
class Avx512Bf16(avx512f_template.Avx512F):
"""All SIMD features for avx512f."""
def __init__(self, m: int, n: int):
super().__init__(m, n, c=2)
def isa(self):
return 'avx512bf16'
def n_step(self):
return 16
def compute_asm(self):
c_asm = {
'loop': ['vdpbf16ps z{ACC}, {A}, {W}\n'],
'loop_tail': ["""vpslld {A}, {A}, 16
vpsrld {A}, {A}, 16
vdpbf16ps z{ACC}, {A}, {W}\n
"""],
}
return c_asm
def function_name(self):
return (
f'xnn_bf16_f32_gemm_minmax_ukernel_{self.m}x{self.n * self.n_step()}'
+ f'c2__asm_amd64_{self.isa()}_broadcast'
)
def init_accumulators(self):
super().init_accumulators()
self.asm_string += """
# Are there at least 4 bytes?
cmp rdx, 4
js .Linner_loop_tail\n"""
def outer_loop_prepare(self):
k_register = self.k_register()
kc_register = self.kc_register()
offset = self.m * 16 + self.c_ptr_stack_offset()
kmask = self.k_mask()
self.asm_string += f"""
# Copy k and flip bit.
mov {k_register}, rdx
and {k_register}, 0x2
and {kc_register}, {kmask}
mov [rsp + {offset}], {k_register}\n"""
def inner_loop_tail(self):
nc_register = self.nc_register()
offset = self.m * 16 + self.c_ptr_stack_offset()
nc_offset = offset + 8
self.asm_string += f"""
# Store nc_register.
mov [rsp + {nc_offset}], {nc_register}
# Load odd k bit.
mov {nc_register}, [rsp + {offset}]
# Check if channels are odd.
test {nc_register}, {nc_register}
mov {nc_register}, [rsp + {nc_offset}]
jz .Linner_loop_end
.Linner_loop_tail:\n"""
if self.m > self.max_m_before_spilling():
self.inner_loop_spill_gp(tail=True)
else:
self.inner_loop_small_M_N(tail=True)
def element_size(self):
return 2
def k_mask(self):
return '0xFFFFFFFFFFFFFFFD'