#ifndef GPU_INTEL_JIT_IR_TENSOR_CONFIG_HPP
#define GPU_INTEL_JIT_IR_TENSOR_CONFIG_HPP
#include <vector>
#include "gpu/intel/jit/ir/post_ops.hpp"
#include "gpu/intel/jit/ir/tensor.hpp"
#include "gpu/intel/jit/utils/utils.hpp"
namespace dnnl {
namespace impl {
namespace gpu {
namespace intel {
namespace jit {
struct tensor_info_t {
std::string name;
int arg_key;
bool is_input;
bool is_output;
layout_t compute_layout;
layout_t user_layout;
bool needs_reorder;
bool needs_zero_out;
};
class tensor_config_t {
public:
const std::vector<tensor_info_t> &tensors() const { return tensors_; }
void add_tensor(const std::string &name, int arg_key, bool is_input,
bool is_output, const layout_t &user_layout) {
tensors_.emplace_back();
auto &t = tensors_.back();
t.name = name;
t.arg_key = arg_key;
t.is_input = is_input;
t.is_output = is_output;
t.compute_layout = user_layout;
t.user_layout = user_layout;
t.needs_reorder = false;
t.needs_zero_out = false;
}
void add_tensor(const std::string &name, int arg_key, bool is_input,
bool is_output, const layout_t &compute_layout,
const layout_t &user_layout) {
tensors_.emplace_back();
auto &t = tensors_.back();
t.name = name;
t.arg_key = arg_key;
t.is_input = is_input;
t.is_output = is_output;
t.compute_layout = compute_layout;
t.user_layout = user_layout;
t.needs_reorder = !t.compute_layout.is_equal_normalized(t.user_layout);
t.needs_zero_out = false;
}
void set_compute_layout(
const std::string &name, const layout_t &compute_layout) {
auto &t = find_tensor(name);
t.compute_layout = compute_layout;
t.needs_reorder = !t.compute_layout.is_equal_normalized(t.user_layout);
}
const layout_t &compute_layout(const std::string &name) const {
return find_tensor(name).compute_layout;
}
const layout_t &user_layout(const std::string &name) const {
return find_tensor(name).user_layout;
}
void require_zero_out(const std::string &name) {
auto &t = find_tensor(name);
t.needs_zero_out = true;
}
private:
const tensor_info_t &find_tensor(const std::string &name) const {
for (auto &t : tensors_) {
if (t.name == name) return t;
}
gpu_error_not_expected() << "Can't find tensor " << name;
return tensors_.front();
}
tensor_info_t &find_tensor(const std::string &name) {
auto *const_this = const_cast<const tensor_config_t *>(this);
return const_cast<tensor_info_t &>(const_this->find_tensor(name));
}
std::vector<tensor_info_t> tensors_;
};
std::vector<layout_block_t> parse_format(
const std::string &format, int ndims_hint);
std::vector<std::pair<char, dim_t>> parse_letter_blocks(
const std::string &format);
inline layout_t make_layout(const dsl::type_t &type, const expr_t &offset,
const std::string &format, const tile_t &dims = {}) {
auto blocks = parse_format(format, into<dim_idx_t>(dims.size()));
tile_t def;
for (auto &b : blocks) {
if (b.size == 0) b.size = utils::div_up(dims[b.idx], def[b.idx]);
def[b.idx] *= b.size;
}
return layout_t(type, blocks, offset, into<dim_idx_t>(dims.size()),
false);
}
inline layout_t make_layout(
const dsl::type_t &type, const tile_t &dims, const std::string &tag) {
return make_layout(type, 0, tag, dims);
}
inline layout_t make_layout(
const memory_desc_t &md, bool do_normalize = false) {
if (md.format_kind == format_kind::any) return layout_t();
auto mdw = memory_desc_wrapper(md);
block_layout_t layout(
mdw, false, false);
std::vector<layout_block_t> blocks;
for (const auto &block : layout) {
blocks.emplace_back(block.dim_idx, block.block, block.stride);
}
return layout_t(to_ir(mdw.data_type()), blocks, mdw.offset0(), mdw.ndims(),
do_normalize);
}
inline layout_t make_layout(const memory_desc_t &md, const std::string &tag) {
if (tag == "user") return make_layout(md);
auto mdw = memory_desc_wrapper(md);
return make_layout(to_ir(mdw.data_type()), mdw.offset0(), tag,
std::vector<dim_t>(mdw.dims(), mdw.dims() + mdw.ndims()));
}
bool matches_tag(
const layout_t &layout, const std::string &tag, const tile_t &dims);
inline bool matches_tag(const layout_t &layout, const std::string &tag) {
return matches_tag(layout, tag, layout.tile());
}
inline bool matches_tag(const memory_desc_t &md, const std::string &tag) {
if (md.format_kind == format_kind::any) return false;
std::vector<dim_t> dims(md.dims, md.dims + md.ndims);
return matches_tag(make_layout(md), tag, dims);
}
inline void set_default_format(memory_desc_t &md, const std::string &tag) {
if (md.format_kind != format_kind::any) return;
md = to_md(make_layout(md, tag), md);
}
inline std::vector<std::pair<const char *, int>> get_scale_args() {
std::vector<std::pair<const char *, int>> ret = {
{"src_scales", DNNL_ARG_SRC},
{"wei_scales", DNNL_ARG_WEIGHTS},
{"dst_scales", DNNL_ARG_DST},
};
return ret;
}
inline std::vector<dim_t> get_prelu_weights_dims(
uint32_t mask, const memory_desc_t &md) {
std::vector<dim_t> dims(md.dims, md.dims + md.ndims);
for (int i = 0; i < md.ndims; ++i)
dims[i] = (mask & (1 << i)) ? dims[i] : 1;
return dims;
}
void init_extra_tensors(const zero_points_config_t &zp_cfg,
const primitive_attr_t &attr, const memory_desc_t *zp_src,
const memory_desc_t &dst_md, dim_t ic, dim_t oc,
tensor_config_t &tensor_cfg);
} } } } }
#endif