#include <cassert>
#include "common/c_types_map.hpp"
#include "common/dnnl_thread.hpp"
#include "common/memory_desc_wrapper.hpp"
#include "common/nstl.hpp"
#include "common/primitive.hpp"
#include "common/type_helpers.hpp"
#include "common/utils.hpp"
#include "cpu/aarch64/jit_generator.hpp"
#include "cpu/aarch64/reorder/jit_blk_reorder.hpp"
#if defined(DNNL_DEV_MODE)
#define DEBUg(...) \
do { \
if (get_verbose(verbose_t::debuginfo) > 1) { __VA_ARGS__ } \
} while (0)
#else
#define DEBUg(...)
#endif
#define DEBUG(...) DEBUg(__VA_ARGS__)
using namespace Xbyak_aarch64;
using namespace dnnl::impl::types;
namespace dnnl {
namespace impl {
namespace cpu {
namespace aarch64 {
status_t jit_blk_reorder_t::pd_t::create(reorder_pd_t **reorder_pd,
engine_t *engine, const primitive_attr_t *attr, engine_t *src_engine,
const memory_desc_t *src_md, engine_t *dst_engine,
const memory_desc_t *dst_md) {
if (!impl::is_dense_format_kind({src_md, dst_md}))
return status::unimplemented;
auto prb = tr::prb_t();
auto upper_thres = 1920 * 4096;
auto src_d = memory_desc_wrapper(src_md);
auto prd = 1;
for (int d = 0; d < src_d.ndims(); ++d) {
const auto dim = src_d.dims()[d];
prd *= dim;
if (prd > upper_thres) return status::unimplemented;
}
auto lower_thres = 128 * 128;
if (get_max_cpu_isa() == sve_128 && prd < lower_thres) {
return status::unimplemented;
}
status_t prb_init_status = prb_init(prb, *src_md, *dst_md, attr);
if (prb_init_status != status::success) return prb_init_status;
if (prb.is_tail_present) return status::unimplemented;
prb_tile_normalize(prb);
DEBUG({
verbose_printf(
verbose_t::debuginfo, "tile : %s\n", prb_dump(prb).c_str());
});
if (!tr::jit_single_blk_kernel_t::applicable(prb)) {
return status::unimplemented;
}
auto _pd = make_unique_pd<pd_t>(
attr, src_engine->kind(), src_md, dst_engine->kind(), dst_md);
if (_pd == nullptr) return status::out_of_memory;
_pd->prb_ = prb;
CHECK(_pd->init(engine, src_engine, dst_engine));
CHECK(_pd->init_scratchpad_md());
return safe_ptr_assign(*reorder_pd, _pd.release());
}
void jit_blk_reorder_t::pd_t::prb_tile_normalize(tr::prb_t &p) {
if (!utils::one_of(p.nodes[0].n, 4ul, 8ul, 16ul, 32ul, 64ul)
&& utils::one_of(p.nodes[1].n, 4ul, 8ul, 16ul, 32ul, 64ul)) {
nstl::swap(p.nodes[0], p.nodes[1]);
}
}
jit_blk_reorder_t::jit_blk_reorder_t(const pd_t *apd) : primitive_t(apd) {}
jit_blk_reorder_t::~jit_blk_reorder_t() = default;
status_t jit_blk_reorder_t::init(engine_t *engine) {
kernel_ = utils::make_unique<tr::jit_single_blk_kernel_t>(pd()->prb_);
return kernel_->create_kernel();
}
status_t jit_blk_reorder_t::execute(const exec_ctx_t &ctx) const {
const auto in = CTX_IN_MEM(const char *, DNNL_ARG_FROM);
auto out = CTX_OUT_MEM(char *, DNNL_ARG_TO);
auto &prb = this->pd()->prb_;
ptrdiff_t BH = 1;
for (int i = 2; i < prb.ndims; ++i) {
BH *= prb.nodes[i].n;
}
auto block_sz = prb.n(0);
auto n1 = prb.n(1);
auto i1 = prb.is(1);
auto o1 = prb.os(1);
auto FL = (n1 + block_sz - 1) / block_sz;
auto bh_stride = BH == 1 ? 0 : prb.is(2);
auto itype_sz_ = data_type_size(pd()->prb_.itype);
auto otype_sz_ = data_type_size(pd()->prb_.otype);
parallel_nd(BH, FL, [&](dim_t bh, dim_t fl) {
auto fl_b = fl * block_sz;
auto bh_b = bh_stride * bh;
auto *i = in + (bh_b + fl_b * i1) * itype_sz_;
auto *o = out + (bh_b + fl_b * o1) * otype_sz_;
(*kernel_)(i, o, n1 - fl_b < block_sz);
});
return status::success;
}
} } } }