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:
@@ -28,207 +28,6 @@
|
||||
#include "brw_ir.h"
|
||||
#include "brw_ir_allocator.h"
|
||||
|
||||
static inline brw_reg
|
||||
horiz_offset(const brw_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 ®, 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 ®)
|
||||
{
|
||||
return is_periodic(reg, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified 8-component quarter of a register.
|
||||
*/
|
||||
static inline brw_reg
|
||||
quarter(const brw_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 {
|
||||
private:
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 ®)
|
||||
{
|
||||
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
|
||||
* instruction. From the Cherryview PRM Vol 7. "Register Region
|
||||
|
@@ -1281,8 +1281,250 @@ element_sz(struct brw_reg reg)
|
||||
int brw_float_to_vf(float f);
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
static inline brw_reg
|
||||
horiz_offset(const brw_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 ®, 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 ®)
|
||||
{
|
||||
return is_periodic(reg, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified 8-component quarter of a register.
|
||||
*/
|
||||
static inline brw_reg
|
||||
quarter(const brw_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 ®)
|
||||
{
|
||||
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
|
||||
|
Reference in New Issue
Block a user