From a9f00a9e535019747d041f4121c56404057465a3 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 26 May 2016 23:20:19 -0700 Subject: [PATCH] i965/fs: Generalize regions_overlap() from copy propagation to handle non-VGRF files. This will be useful in several places. The only externally visible difference (other than non-VGRF files being supported now) is that the region sizes are now passed in byte units instead of in GRF units because the loss of precision would have become a problem in the SIMD lowering pass. Reviewed-by: Jason Ekstrand --- .../dri/i965/brw_fs_copy_propagation.cpp | 16 ++------ src/mesa/drivers/dri/i965/brw_ir_fs.h | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp b/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp index 38103af566b..d88d62ba685 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp @@ -757,14 +757,6 @@ can_propagate_from(fs_inst *inst) !inst->is_partial_write()); } -inline bool -regions_overlap(const fs_reg &r, unsigned n, const fs_reg &s, unsigned m) -{ - return r.file == s.file && r.nr == s.nr && - !(r.reg_offset + n <= s.reg_offset || - s.reg_offset + m <= r.reg_offset); -} - /* Walks a basic block and does copy propagation on it using the acp * list. */ @@ -791,8 +783,8 @@ fs_visitor::opt_copy_propagate_local(void *copy_prop_ctx, bblock_t *block, /* kill the destination from the ACP */ if (inst->dst.file == VGRF) { foreach_in_list_safe(acp_entry, entry, &acp[inst->dst.nr % ACP_HASH_SIZE]) { - if (regions_overlap(entry->dst, entry->regs_written, - inst->dst, inst->regs_written)) + if (regions_overlap(entry->dst, entry->regs_written * REG_SIZE, + inst->dst, inst->regs_written * REG_SIZE)) entry->remove(); } @@ -804,8 +796,8 @@ fs_visitor::opt_copy_propagate_local(void *copy_prop_ctx, bblock_t *block, /* Make sure we kill the entry if this instruction overwrites * _any_ of the registers that it reads */ - if (regions_overlap(entry->src, entry->regs_read, - inst->dst, inst->regs_written)) + if (regions_overlap(entry->src, entry->regs_read * REG_SIZE, + inst->dst, inst->regs_written * REG_SIZE)) entry->remove(); } } diff --git a/src/mesa/drivers/dri/i965/brw_ir_fs.h b/src/mesa/drivers/dri/i965/brw_ir_fs.h index 35169f8464f..7b1ec68e683 100644 --- a/src/mesa/drivers/dri/i965/brw_ir_fs.h +++ b/src/mesa/drivers/dri/i965/brw_ir_fs.h @@ -171,6 +171,44 @@ component(fs_reg reg, unsigned idx) 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 file is composed of multiple discrete address + * spaces, one for each VGRF allocation. + */ +static inline uint32_t +reg_space(const fs_reg &r) +{ + return r.file << 16 | (r.file == VGRF ? 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 fs_reg &r) +{ + return ((r.file == VGRF || r.file == IMM ? 0 : r.nr) + r.reg_offset) * + (r.file == UNIFORM ? 4 : REG_SIZE) + r.subreg_offset; +} + +/** + * 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 fs_reg &r, unsigned dr, const fs_reg &s, unsigned ds) +{ + return reg_space(r) == reg_space(s) && + !(reg_offset(r) + dr <= reg_offset(s) || + reg_offset(s) + ds <= reg_offset(r)); +} + /** * Return whether the given register region is n-periodic, i.e. whether the * original region remains invariant after shifting it by \p n scalar -- 2.30.2