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.h"
|
||||||
#include "brw_ir_allocator.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 {
|
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 ®)
|
|
||||||
{
|
|
||||||
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
|
||||||
|
@@ -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 ®, 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
|
#endif
|
||||||
|
Reference in New Issue
Block a user