From 260a5fc7b31ba814fd52ea6c30a135b1b3d7b9d2 Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Wed, 19 Jun 2024 10:22:04 -0700 Subject: [PATCH] intel/brw: Move brw_reg helpers into brw_reg.h Reviewed-by: Kenneth Graunke Part-of: --- src/intel/compiler/brw_ir_fs.h | 238 -------------------------------- src/intel/compiler/brw_reg.h | 242 +++++++++++++++++++++++++++++++++ 2 files changed, 242 insertions(+), 238 deletions(-) diff --git a/src/intel/compiler/brw_ir_fs.h b/src/intel/compiler/brw_ir_fs.h index c2ce0227fca..2e134e662fa 100644 --- a/src/intel/compiler/brw_ir_fs.h +++ b/src/intel/compiler/brw_ir_fs.h @@ -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 diff --git a/src/intel/compiler/brw_reg.h b/src/intel/compiler/brw_reg.h index 32e2adc0297..2003dd92b80 100644 --- a/src/intel/compiler/brw_reg.h +++ b/src/intel/compiler/brw_reg.h @@ -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