#ifndef CPU_X64_JIT_BRGEMM_POST_OPS_HPP
#define CPU_X64_JIT_BRGEMM_POST_OPS_HPP
#include <memory>
#include "common/c_types_map.hpp"
#include "common/memory_tracking.hpp"
#include "cpu/cpu_engine.hpp"
#include "cpu/x64/injectors/jit_uni_postops_injector.hpp"
#include "cpu/x64/jit_avx512_core_bf16cvt.hpp"
#include "cpu/x64/jit_avx512_core_fp8cvt.hpp"
#include "cpu/x64/jit_brgemm_primitive_conf.hpp"
#include "cpu/x64/jit_generator.hpp"
#include "cpu/x64/matmul/brgemm_matmul_utils.hpp"
#include "cpu/x64/utils/jit_regops.hpp"
namespace dnnl {
namespace impl {
namespace cpu {
namespace x64 {
struct brgemm_kernel_diff_bias_t {
brgemm_kernel_diff_bias_t()
: ptr_diff_dst(nullptr)
, ptr_diff_bias_acc(nullptr)
, ptr_diff_bias(nullptr)
, flags(0) {};
void *ptr_diff_dst;
void *ptr_diff_bias_acc;
void *ptr_diff_bias;
int flags;
};
template <typename Vmm>
struct jit_brgemm_kernel_diff_bias_t : public jit_generator_t {
jit_brgemm_kernel_diff_bias_t(const jit_brgemm_primitive_conf_t &ajbgp,
const brgemm_desc_t &abrg);
jit_brgemm_kernel_diff_bias_t(const matmul::brgemm_matmul_conf_t &bgmmc,
const brgemm_desc_t &abrg);
DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_brgemm_kernel_diff_bias_t)
private:
brgemm_desc_t brg_;
matmul_reduce_kind_t reduce_kind_;
data_type_t ddst_dt_;
data_type_t bia_dt_;
data_type_t acc_dt_;
int ddst_typesize_;
int bia_typesize_;
int acc_typesize_;
int mult_;
using Vmm_lower_t = typename vreg_traits_t<Vmm>::Vmm_lower_t;
using reg64_t = const Xbyak::Reg64;
const reg64_t param1 = abi_param1;
const reg64_t reg_ddst = r15;
const reg64_t reg_bias = r14;
const reg64_t reg_bias_acc = r13;
const reg64_t aux_reg_ddst = r12;
const reg64_t reg_k_iter = r11;
const reg64_t reg_flag = r10;
const reg64_t reg_mask = rax;
Xbyak::Label f16_perm_table_;
Xbyak::Label mask_label_;
Xbyak::Opmask k_full_mask = Xbyak::Opmask(2);
Xbyak::Opmask k_tail_mask = Xbyak::Opmask(3);
Xbyak::Opmask k_f16_perm_mask = Xbyak::Opmask(4);
Xbyak::Opmask k_store_mask = Xbyak::Opmask(5);
Vmm vreg_unit = Vmm(31);
Vmm vreg_perm = Vmm(30);
Vmm vmm_tail_mask = Vmm(15);
const int n_max_regs_ = 4;
Vmm vmm_mask(const Vmm vmm_in, bool mask_flag, bool store,
Xbyak::Opmask ktail_mask);
Vmm get_bias_reg(int n) const { return Vmm(n); }
Vmm_lower_t get_bias_reg_lower(int n) const { return Vmm_lower_t(n); }
Vmm get_ddst_reg(int n) const { return Vmm(n + n_max_regs_); }
Vmm get_workspace_reg() const {
assert(reduce_kind_ == matmul_reduce_kind::src);
return Vmm(1);
}
void accumulate_bias(int idx, bool mask_flag);
void accumulate_bias(bool mask_flag);
void store(int idx, bool mask_flag);
void loop_by_N(int n_loop, int nb_tail);
void loop_by_K();
void init_masks(int tail_length);
void generate() override;
void generate_for_a();
void generate_for_b();
};
struct brgemm_kernel_post_ops_args_t {
void *ptr_in;
void *ptr_out;
void *ptr_bias;
const void *ptr_binary_post_ops_rhs;
size_t apply_comp = 0;
int32_t a_comp_val = 1;
int32_t *a_zp_compensation;
const int32_t *c_zp_values;
int32_t *s8s8_compensation;
const void *dst_orig;
const void *ptr_src_scales = nullptr;
const void *ptr_wei_scales = nullptr;
const void *ptr_dst_scales = nullptr;
};
struct jit_brgemm_kernel_post_ops_base_t {
static jit_brgemm_kernel_post_ops_base_t *create(cpu_isa_t isa,
const brgemm_desc_t &abrg, const primitive_attr_t &aattr);
virtual ~jit_brgemm_kernel_post_ops_base_t() = default;
virtual status_t generate_kernel() = 0;
virtual void operator()(brgemm_kernel_post_ops_args_t *args) const = 0;
virtual int get_bcast_dim() const = 0;
};
template <typename Vmm>
struct jit_brgemm_kernel_post_ops_t : public jit_brgemm_kernel_post_ops_base_t,
public jit_generator_t {
jit_brgemm_kernel_post_ops_t(
const brgemm_desc_t &abrg, const primitive_attr_t &aattr);
status_t generate_kernel() override {
return jit_generator_t::create_kernel();
}
void operator()(brgemm_kernel_post_ops_args_t *args) const override {
return jit_generator_t::operator()(args);
}
~jit_brgemm_kernel_post_ops_t() override = default;
DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_brgemm_kernel_post_ops_t)
int get_bcast_dim() const override { return brg_.bcast_dim; }
private:
brgemm_desc_t brg_;
const primitive_attr_t &attr_;
data_type_t inp_dt_;
data_type_t out_dt_;
data_type_t bia_dt_;
using Vmm_lower_t = typename vreg_traits_t<Vmm>::Vmm_lower_t;
using Vmm_lower2_t = typename vreg_traits_t<Vmm_lower_t>::Vmm_lower_t;
using po_injector_t = injector::jit_uni_postops_injector_base_t<Vmm>;
std::unique_ptr<po_injector_t> postops_injector_;
std::unique_ptr<bf16_emulation_t> bf16_emu_;
std::unique_ptr<fp8_conversion_e5m2_t> f8_e5m2_cvt_;
std::unique_ptr<fp8_conversion_e4m3_t> f8_e4m3_cvt_;
int max_vregs_;
const bool with_binary_non_scalar_bcast_;
int inp_typesize_;
int out_typesize_;
int bia_typesize_;
using reg64_t = const Xbyak::Reg64;
const reg64_t reg_reserved_eltwise = rax;
const reg64_t param1 = abi_param1;
const reg64_t reg_in = r15;
const reg64_t reg_out = r14;
const reg64_t aux_reg_in = r13;
const reg64_t aux_reg_out = r12;
const reg64_t reg_bias = r11;
const reg64_t aux_reg_bias = r10;
const reg64_t reg_wei_scales = r9;
const reg64_t aux_reg_wei_scales = r8;
const reg64_t reg_ptr_sum_scale = rdx;
const reg64_t reg_ptr_sum_zp = rsi;
const reg64_t reg_zp_c_values = rbx;
const reg64_t aux_reg_zp_c_values = rbx;
const reg64_t reg_zp_a_comp = rbx;
const reg64_t aux_reg_zp_a_comp = rbx;
const reg64_t reg_s8s8_comp = rbx;
const reg64_t aux_reg_s8s8_comp = rbx;
const reg64_t reg_zp_a_val = rbx;
const reg64_t reg_apply_comp = rbx;
const reg64_t reg_src_scales = rbx;
const reg64_t aux_reg_src_scales = rbx;
const reg64_t reg_dst_scales = rbx;
const reg64_t aux_reg_dst_scales = rbx;
const reg64_t aux_reg_scale_adjust = rbx;
const reg64_t reg_tmp = abi_not_param1;
constexpr static int reg_zp_c_values_offs_ = 0;
constexpr static int aux_reg_zp_c_values_offs_ = 8;
constexpr static int reg_zp_a_comp_offs_ = 16;
constexpr static int aux_reg_zp_a_comp_offs_ = 24;
constexpr static int reg_s8s8_comp_offs_ = 32;
constexpr static int aux_reg_s8s8_comp_offs_ = 40;
constexpr static int reg_zp_a_val_offs_ = 48;
constexpr static int reg_apply_comp_offs_ = 56;
constexpr static int reg_src_scales_offs_ = 64;
constexpr static int reg_dst_scales_offs_ = 72;
constexpr static int stack_space_needed_ = 80;
Xbyak::Zmm emu_reserv_1 = Xbyak::Zmm(27);
Xbyak::Zmm emu_reserv_2 = Xbyak::Zmm(26);
Xbyak::Zmm emu_reserv_3 = Xbyak::Zmm(25);
Xbyak::Zmm emu_reserv_4 = Xbyak::Zmm(24);
Xbyak::Zmm emu_reserv_5 = Xbyak::Zmm(23);
reg64_t emu_scratch = reg_tmp;
Xbyak::Opmask emu_mask = Xbyak::Opmask(4);
Xbyak::Opmask k_full_mask = Xbyak::Opmask(2);
Xbyak::Opmask k_tail_mask = Xbyak::Opmask(3);
const int n_block2_ = 4;
Vmm vmm_tmp(int i) const { return Vmm(max_vregs_ - 1 - i); }
int zp_c_values_offset(int n, bool is_tail = false) const noexcept;
int zp_comp_a_vpad_offset(
int n, int m, bool is_tail = false) const noexcept;
int mb_zp_comp_a_offset(int m_block) const noexcept;
int compensation_vpad_offset(
int n, int m, bool is_tail = false) const noexcept;
int mb_compensation_offset(int m_block) const noexcept {
return sizeof(int32_t) * m_block * brg_.LDB;
}
template <typename T>
T maybe_mask(const T vmm_in, bool mask_flag, bool store,
Xbyak::Opmask ktail_mask) {
assert(IMPLICATION(mask_flag, isa_has_masks(brg_.isa_impl)));
return mask_flag
? (store ? vmm_in | ktail_mask : vmm_in | ktail_mask | T_z)
: vmm_in;
}
void cvt2ps(data_type_t type_in, const Vmm vmm_in, const Xbyak::Operand &op,
int tail_size, bool store, Xbyak::Opmask ktail_mask,
bool skip_cvt2ps = false);
Vmm vector(int m, int n, int n_block) { return Vmm(m * n_block + n); }
void inject_attr_postops(int m_block, int n_block, int tail = 0);
void apply_comp(int m_block, int n_block, int tail = 0);
void maybe_apply_comp(int m_block, int n_block, int tail = 0);
void apply_post_ops(int m_block, int n_block, int tail = 0);
void loop_by_N(int m_block, int nb2, int nb2_tail, int nb_tail);
void generate() override;
};
} } } }
#endif