#ifndef GEMMSTONE_GENERATOR_PIECES_MAP_HPP
#define GEMMSTONE_GENERATOR_PIECES_MAP_HPP
#include "internal/ngen_includes.hpp"
#include "gemmstone/type.hpp"
#include "gemmstone/strategy.hpp"
#include "grf_multirange.hpp"
#include "hw_utils.hpp"
#include "register_layout.hpp"
GEMMSTONE_NAMESPACE_START
static inline bool canDualGRF(ngen::HW hw, ngen::DataType dt, const CommonStrategy &strategy);
template <typename F>
static inline void map(ngen::HW hw, ngen::DataType dt, const GRFMultirange &r1, const GRFMultirange &r2, const CommonStrategy &strategy, F f)
{
int ne = elementsPerGRF(hw, dt);
int rstride = canDualGRF(hw, dt, strategy) ? 2 : 1;
int len = r1.getLen();
for (int rr = 0; rr < len;) {
int nr = std::min<int>(len - rr, rstride);
if (!r1.contiguous(rr, nr) || !r2.contiguous(rr, nr))
nr = 1;
f(nr * ne, r1[rr].retype(dt), r2[rr].retype(dt));
rr += nr;
}
}
template <typename F>
static inline void map(ngen::HW hw, ngen::DataType dt, const GRFMultirange &r1, const GRFMultirange &r2, const GRFMultirange &r3, const CommonStrategy &strategy, F f)
{
int ne = elementsPerGRF(hw, dt);
int rstride = canDualGRF(hw, dt, strategy) ? 2 : 1;
int len = r1.getLen();
for (int rr = 0; rr < len;) {
int nr = std::min<int>(len - rr, rstride);
if (!r1.contiguous(rr, nr) || !r2.contiguous(rr, nr) || !r3.contiguous(rr, nr))
nr = 1;
f(nr * ne, r1[rr].retype(dt), r2[rr].retype(dt), r3[rr].retype(dt));
rr += nr;
}
}
template <typename F>
static inline void map(ngen::HW hw, ngen::DataType dt, const GRFMultirange &r1, const GRFMultirange &r2, const GRFMultirange &r3, const GRFMultirange &r4, const CommonStrategy &strategy, F f)
{
int ne = elementsPerGRF(hw, dt);
int rstride = canDualGRF(hw, dt, strategy) ? 2 : 1;
int len = r1.getLen();
for (int rr = 0; rr < len;) {
int nr = std::min<int>(len - rr, rstride);
if (!r1.contiguous(rr, nr) || !r2.contiguous(rr, nr) || !r3.contiguous(rr, nr) || !r4.contiguous(rr, nr))
nr = 1;
f(nr * ne, r1[rr].retype(dt), r2[rr].retype(dt), r3[rr].retype(dt), r4[rr].retype(dt));
rr += nr;
}
}
template <typename F>
static inline void map(ngen::HW hw, ngen::DataType dt, const GRFMultirange ®s,
const RegisterLayout &layout, const CommonStrategy &strategy, F f,
int cxComponent = -1)
{
using namespace ngen;
int curReg = 0, curOff = 0, curBytes = 0;
auto ebytes = getBytes(dt);
auto map1 = [&]() {
curOff &= -ebytes;
curBytes &= -ebytes;
while (curBytes) {
int maxBytes;
int regOff = curOff & (GRF::bytes(hw) - 1);
if (regOff != 0)
maxBytes = GRF::bytes(hw) - regOff;
else {
int nr = 1;
if (canDualGRF(hw, dt, strategy) && regs.contiguous(curOff >> GRF::log2Bytes(hw), 2))
nr = 2;
maxBytes = nr * GRF::bytes(hw);
}
auto nbytes = ngen::utils::rounddown_pow2(std::min(maxBytes, curBytes));
auto ne = std::min<int>(32, nbytes / ebytes);
nbytes = ne * ebytes;
auto reg = regs[curOff >> GRF::log2Bytes(hw)].sub((curOff & (GRF::bytes(hw) - 1)) / ebytes, dt)(1);
f(ne, reg);
curBytes -= nbytes;
curOff += nbytes;
}
};
for (auto &block : layout) {
int endReg = (curOff + curBytes + block.bytes - 1) >> GRF::log2Bytes(hw);
if ((block.offsetBytes == curOff + curBytes) && regs.contiguous(curReg, endReg - curReg + 1))
curBytes += block.bytes;
else {
map1();
curOff = block.offsetBytes;
curReg = curOff >> GRF::log2Bytes(hw);
curBytes = block.bytes;
}
}
map1();
}
template <typename T, typename F>
static inline void map(ngen::HW hw, const GRFMultirange &r1, const GRFMultirange &r2,
const CommonStrategy &strategy, F f) {
map(hw, ngen::getDataType<T>(), r1, r2, strategy, f);
}
template <typename T, typename F>
static inline void map(ngen::HW hw, const GRFMultirange &r1, const GRFMultirange &r2, const GRFMultirange &r3,
const CommonStrategy &strategy, F f) {
map(hw, ngen::getDataType<T>(), r1, r2, r3, strategy, f);
}
template <typename T, typename F>
static inline void map(ngen::HW hw, const GRFMultirange ®s, const RegisterLayout &layout,
const CommonStrategy &strategy, F f) {
map(hw, ngen::getDataType<T>(), regs, layout, strategy, f);
}
template <typename... Targs>
static inline void map(ngen::HW hw, Type T, Targs &&...args) {
map(hw, T.ngen(), std::forward<Targs>(args)...);
}
static inline bool canDualGRF(ngen::HW hw, ngen::DataType dt, const CommonStrategy &strategy)
{
return (strategy.dualGRF && (elementsPerGRF(hw, dt) < 32));
}
GEMMSTONE_NAMESPACE_END
#endif