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 <jason@jlekstrand.net>
This commit is contained in:
parent
4db93592de
commit
a9f00a9e53
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue