intel/brw: Move brw_reg helpers into brw_reg.h

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29791>
This commit is contained in:
Caio Oliveira
2024-06-19 10:22:04 -07:00
committed by Marge Bot
parent 71ccf8e4cd
commit 260a5fc7b3
2 changed files with 242 additions and 238 deletions

View File

@@ -28,207 +28,6 @@
#include "brw_ir.h" #include "brw_ir.h"
#include "brw_ir_allocator.h" #include "brw_ir_allocator.h"
static inline brw_reg
horiz_offset(const brw_reg &reg, unsigned delta)
{
switch (reg.file) {
case BAD_FILE:
case UNIFORM:
case IMM:
/* These only have a single component that is implicitly splatted. A
* horizontal offset should be a harmless no-op.
* XXX - Handle vector immediates correctly.
*/
return reg;
case VGRF:
case ATTR:
return byte_offset(reg, delta * reg.stride * brw_type_size_bytes(reg.type));
case ARF:
case FIXED_GRF:
if (reg.is_null()) {
return reg;
} else {
const unsigned hstride = reg.hstride ? 1 << (reg.hstride - 1) : 0;
const unsigned vstride = reg.vstride ? 1 << (reg.vstride - 1) : 0;
const unsigned width = 1 << reg.width;
if (delta % width == 0) {
return byte_offset(reg, delta / width * vstride * brw_type_size_bytes(reg.type));
} else {
assert(vstride == hstride * width);
return byte_offset(reg, delta * hstride * brw_type_size_bytes(reg.type));
}
}
}
unreachable("Invalid register file");
}
static inline brw_reg
offset(brw_reg reg, unsigned width, unsigned delta)
{
switch (reg.file) {
case BAD_FILE:
break;
case ARF:
case FIXED_GRF:
case VGRF:
case ATTR:
case UNIFORM:
return byte_offset(reg, delta * reg.component_size(width));
case IMM:
assert(delta == 0);
}
return reg;
}
/**
* Get the scalar channel of \p reg given by \p idx and replicate it to all
* channels of the result.
*/
static inline brw_reg
component(brw_reg reg, unsigned idx)
{
reg = horiz_offset(reg, idx);
reg.stride = 0;
if (reg.file == ARF || reg.file == FIXED_GRF) {
reg.vstride = BRW_VERTICAL_STRIDE_0;
reg.width = BRW_WIDTH_1;
reg.hstride = BRW_HORIZONTAL_STRIDE_0;
}
return reg;
}
/**
* Return an integer identifying the discrete address space a register is
* contained in. A register is by definition fully contained in the single
* reg_space it belongs to, so two registers with different reg_space ids are
* guaranteed not to overlap. Most register files are a single reg_space of
* its own, only the VGRF and ATTR files are composed of multiple discrete
* address spaces, one for each allocation and input attribute respectively.
*/
static inline uint32_t
reg_space(const brw_reg &r)
{
return r.file << 16 | (r.file == VGRF || r.file == ATTR ? r.nr : 0);
}
/**
* Return the base offset in bytes of a register relative to the start of its
* reg_space().
*/
static inline unsigned
reg_offset(const brw_reg &r)
{
return (r.file == VGRF || r.file == IMM || r.file == ATTR ? 0 : r.nr) *
(r.file == UNIFORM ? 4 : REG_SIZE) + r.offset +
(r.file == ARF || r.file == FIXED_GRF ? r.subnr : 0);
}
/**
* Return the amount of padding in bytes left unused between individual
* components of register \p r due to a (horizontal) stride value greater than
* one, or zero if components are tightly packed in the register file.
*/
static inline unsigned
reg_padding(const brw_reg &r)
{
const unsigned stride = ((r.file != ARF && r.file != FIXED_GRF) ? r.stride :
r.hstride == 0 ? 0 :
1 << (r.hstride - 1));
return (MAX2(1, stride) - 1) * brw_type_size_bytes(r.type);
}
/**
* Return whether the register region starting at \p r and spanning \p dr
* bytes could potentially overlap the register region starting at \p s and
* spanning \p ds bytes.
*/
static inline bool
regions_overlap(const brw_reg &r, unsigned dr, const brw_reg &s, unsigned ds)
{
if (r.file != s.file)
return false;
if (r.file == VGRF) {
return r.nr == s.nr &&
!(r.offset + dr <= s.offset || s.offset + ds <= r.offset);
} else {
return !(reg_offset(r) + dr <= reg_offset(s) ||
reg_offset(s) + ds <= reg_offset(r));
}
}
/**
* Check that the register region given by r [r.offset, r.offset + dr[
* is fully contained inside the register region given by s
* [s.offset, s.offset + ds[.
*/
static inline bool
region_contained_in(const brw_reg &r, unsigned dr, const brw_reg &s, unsigned ds)
{
return reg_space(r) == reg_space(s) &&
reg_offset(r) >= reg_offset(s) &&
reg_offset(r) + dr <= reg_offset(s) + ds;
}
/**
* Return whether the given register region is n-periodic, i.e. whether the
* original region remains invariant after shifting it by \p n scalar
* channels.
*/
static inline bool
is_periodic(const brw_reg &reg, unsigned n)
{
if (reg.file == BAD_FILE || reg.is_null()) {
return true;
} else if (reg.file == IMM) {
const unsigned period = (reg.type == BRW_TYPE_UV ||
reg.type == BRW_TYPE_V ? 8 :
reg.type == BRW_TYPE_VF ? 4 :
1);
return n % period == 0;
} else if (reg.file == ARF || reg.file == FIXED_GRF) {
const unsigned period = (reg.hstride == 0 && reg.vstride == 0 ? 1 :
reg.vstride == 0 ? 1 << reg.width :
~0);
return n % period == 0;
} else {
return reg.stride == 0;
}
}
static inline bool
is_uniform(const brw_reg &reg)
{
return is_periodic(reg, 1);
}
/**
* Get the specified 8-component quarter of a register.
*/
static inline brw_reg
quarter(const brw_reg &reg, unsigned idx)
{
assert(idx < 4);
return horiz_offset(reg, 8 * idx);
}
static inline brw_reg
horiz_stride(brw_reg reg, unsigned s)
{
reg.stride *= s;
return reg;
}
bool brw_reg_saturate_immediate(brw_reg *reg);
bool brw_reg_negate_immediate(brw_reg *reg);
bool brw_reg_abs_immediate(brw_reg *reg);
static const brw_reg reg_undef;
struct fs_inst : public exec_node { struct fs_inst : public exec_node {
private: private:
fs_inst &operator=(const fs_inst &); fs_inst &operator=(const fs_inst &);
@@ -579,43 +378,6 @@ is_unordered(const intel_device_info *devinfo, const fs_inst *inst)
inst->dst.type == BRW_TYPE_DF)); inst->dst.type == BRW_TYPE_DF));
} }
/*
* Return the stride between channels of the specified register in
* byte units, or ~0u if the region cannot be represented with a
* single one-dimensional stride.
*/
static inline unsigned
byte_stride(const brw_reg &reg)
{
switch (reg.file) {
case BAD_FILE:
case UNIFORM:
case IMM:
case VGRF:
case ATTR:
return reg.stride * brw_type_size_bytes(reg.type);
case ARF:
case FIXED_GRF:
if (reg.is_null()) {
return 0;
} else {
const unsigned hstride = reg.hstride ? 1 << (reg.hstride - 1) : 0;
const unsigned vstride = reg.vstride ? 1 << (reg.vstride - 1) : 0;
const unsigned width = 1 << reg.width;
if (width == 1) {
return vstride * brw_type_size_bytes(reg.type);
} else if (hstride * width == vstride) {
return hstride * brw_type_size_bytes(reg.type);
} else {
return ~0u;
}
}
default:
unreachable("Invalid register file");
}
}
/** /**
* Return whether the following regioning restriction applies to the specified * Return whether the following regioning restriction applies to the specified
* instruction. From the Cherryview PRM Vol 7. "Register Region * instruction. From the Cherryview PRM Vol 7. "Register Region

View File

@@ -1281,8 +1281,250 @@ element_sz(struct brw_reg reg)
int brw_float_to_vf(float f); int brw_float_to_vf(float f);
float brw_vf_to_float(unsigned char vf); float brw_vf_to_float(unsigned char vf);
bool brw_reg_saturate_immediate(brw_reg *reg);
bool brw_reg_negate_immediate(brw_reg *reg);
bool brw_reg_abs_immediate(brw_reg *reg);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#ifdef __cplusplus
static inline brw_reg
horiz_offset(const brw_reg &reg, unsigned delta)
{
switch (reg.file) {
case BAD_FILE:
case UNIFORM:
case IMM:
/* These only have a single component that is implicitly splatted. A
* horizontal offset should be a harmless no-op.
* XXX - Handle vector immediates correctly.
*/
return reg;
case VGRF:
case ATTR:
return byte_offset(reg, delta * reg.stride * brw_type_size_bytes(reg.type));
case ARF:
case FIXED_GRF:
if (reg.is_null()) {
return reg;
} else {
const unsigned hstride = reg.hstride ? 1 << (reg.hstride - 1) : 0;
const unsigned vstride = reg.vstride ? 1 << (reg.vstride - 1) : 0;
const unsigned width = 1 << reg.width;
if (delta % width == 0) {
return byte_offset(reg, delta / width * vstride * brw_type_size_bytes(reg.type));
} else {
assert(vstride == hstride * width);
return byte_offset(reg, delta * hstride * brw_type_size_bytes(reg.type));
}
}
}
unreachable("Invalid register file");
}
static inline brw_reg
offset(brw_reg reg, unsigned width, unsigned delta)
{
switch (reg.file) {
case BAD_FILE:
break;
case ARF:
case FIXED_GRF:
case VGRF:
case ATTR:
case UNIFORM:
return byte_offset(reg, delta * reg.component_size(width));
case IMM:
assert(delta == 0);
}
return reg;
}
/**
* Get the scalar channel of \p reg given by \p idx and replicate it to all
* channels of the result.
*/
static inline brw_reg
component(brw_reg reg, unsigned idx)
{
reg = horiz_offset(reg, idx);
reg.stride = 0;
if (reg.file == ARF || reg.file == FIXED_GRF) {
reg.vstride = BRW_VERTICAL_STRIDE_0;
reg.width = BRW_WIDTH_1;
reg.hstride = BRW_HORIZONTAL_STRIDE_0;
}
return reg;
}
/**
* Return an integer identifying the discrete address space a register is
* contained in. A register is by definition fully contained in the single
* reg_space it belongs to, so two registers with different reg_space ids are
* guaranteed not to overlap. Most register files are a single reg_space of
* its own, only the VGRF and ATTR files are composed of multiple discrete
* address spaces, one for each allocation and input attribute respectively.
*/
static inline uint32_t
reg_space(const brw_reg &r)
{
return r.file << 16 | (r.file == VGRF || r.file == ATTR ? r.nr : 0);
}
/**
* Return the base offset in bytes of a register relative to the start of its
* reg_space().
*/
static inline unsigned
reg_offset(const brw_reg &r)
{
return (r.file == VGRF || r.file == IMM || r.file == ATTR ? 0 : r.nr) *
(r.file == UNIFORM ? 4 : REG_SIZE) + r.offset +
(r.file == ARF || r.file == FIXED_GRF ? r.subnr : 0);
}
/**
* Return the amount of padding in bytes left unused between individual
* components of register \p r due to a (horizontal) stride value greater than
* one, or zero if components are tightly packed in the register file.
*/
static inline unsigned
reg_padding(const brw_reg &r)
{
const unsigned stride = ((r.file != ARF && r.file != FIXED_GRF) ? r.stride :
r.hstride == 0 ? 0 :
1 << (r.hstride - 1));
return (MAX2(1, stride) - 1) * brw_type_size_bytes(r.type);
}
/**
* Return whether the register region starting at \p r and spanning \p dr
* bytes could potentially overlap the register region starting at \p s and
* spanning \p ds bytes.
*/
static inline bool
regions_overlap(const brw_reg &r, unsigned dr, const brw_reg &s, unsigned ds)
{
if (r.file != s.file)
return false;
if (r.file == VGRF) {
return r.nr == s.nr &&
!(r.offset + dr <= s.offset || s.offset + ds <= r.offset);
} else {
return !(reg_offset(r) + dr <= reg_offset(s) ||
reg_offset(s) + ds <= reg_offset(r));
}
}
/**
* Check that the register region given by r [r.offset, r.offset + dr[
* is fully contained inside the register region given by s
* [s.offset, s.offset + ds[.
*/
static inline bool
region_contained_in(const brw_reg &r, unsigned dr, const brw_reg &s, unsigned ds)
{
return reg_space(r) == reg_space(s) &&
reg_offset(r) >= reg_offset(s) &&
reg_offset(r) + dr <= reg_offset(s) + ds;
}
/**
* Return whether the given register region is n-periodic, i.e. whether the
* original region remains invariant after shifting it by \p n scalar
* channels.
*/
static inline bool
is_periodic(const brw_reg &reg, unsigned n)
{
if (reg.file == BAD_FILE || reg.is_null()) {
return true;
} else if (reg.file == IMM) {
const unsigned period = (reg.type == BRW_TYPE_UV ||
reg.type == BRW_TYPE_V ? 8 :
reg.type == BRW_TYPE_VF ? 4 :
1);
return n % period == 0;
} else if (reg.file == ARF || reg.file == FIXED_GRF) {
const unsigned period = (reg.hstride == 0 && reg.vstride == 0 ? 1 :
reg.vstride == 0 ? 1 << reg.width :
~0);
return n % period == 0;
} else {
return reg.stride == 0;
}
}
static inline bool
is_uniform(const brw_reg &reg)
{
return is_periodic(reg, 1);
}
/**
* Get the specified 8-component quarter of a register.
*/
static inline brw_reg
quarter(const brw_reg &reg, unsigned idx)
{
assert(idx < 4);
return horiz_offset(reg, 8 * idx);
}
static inline brw_reg
horiz_stride(brw_reg reg, unsigned s)
{
reg.stride *= s;
return reg;
}
static const brw_reg reg_undef;
/*
* Return the stride between channels of the specified register in
* byte units, or ~0u if the region cannot be represented with a
* single one-dimensional stride.
*/
static inline unsigned
byte_stride(const brw_reg &reg)
{
switch (reg.file) {
case BAD_FILE:
case UNIFORM:
case IMM:
case VGRF:
case ATTR:
return reg.stride * brw_type_size_bytes(reg.type);
case ARF:
case FIXED_GRF:
if (reg.is_null()) {
return 0;
} else {
const unsigned hstride = reg.hstride ? 1 << (reg.hstride - 1) : 0;
const unsigned vstride = reg.vstride ? 1 << (reg.vstride - 1) : 0;
const unsigned width = 1 << reg.width;
if (width == 1) {
return vstride * brw_type_size_bytes(reg.type);
} else if (hstride * width == vstride) {
return hstride * brw_type_size_bytes(reg.type);
} else {
return ~0u;
}
}
default:
unreachable("Invalid register file");
}
}
#endif /* __cplusplus */
#endif #endif