[Mesa-dev] [PATCH 4/5] i965/vec4: Don't emit scratch reads for a spilled register we have just written
Iago Toral Quiroga
itoral at igalia.com
Fri Jul 24 04:31:51 PDT 2015
When we have code such as this:
mov vgrf1.0.x:F, vgrf2.xxxx:F
mov vgrf3.0.x:F, vgrf1.xxxx:F
...
mov vgrf3.0.x:F, vgrf1.xxxx:F
And vgrf1 is chosen for spilling, we can emit this:
mov vgrf1.0.x:F, vgrf2.xxxx:F
gen4_scratch_write hw_reg0:F, vgrf1.xxxx:D, 22D
mov vgrf3.0.x:F, vgrf1.xxxx:F
...
gen4_scratch_read vgrf4.0.x:F, 22D
mov vgrf3.0.x:F, vgrf4.xxxx:F
Instead of this:
mov vgrf1.0.x:F, vgrf2.xxxx:F
gen4_scratch_write hw_reg0:F, vgrf1.xxxx:D, 22D
gen4_scratch_read vgrf4.0.x:F, 22D
mov vgrf3.0.x:F, vgrf4.xxxx:F
...
gen4_scratch_read vgrf5.0.x:F, 22D
mov vgrf3.0.x:F, vgrf5.xxxx:F
And save one scratch read while still preserving the benefits of
spilling the register.
---
.../drivers/dri/i965/brw_vec4_reg_allocate.cpp | 39 +++++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp
index 80ab813..5fed2f9 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp
@@ -334,6 +334,18 @@ vec4_visitor::choose_spill_reg(struct ra_graph *g)
return ra_get_best_spill_node(g);
}
+static bool
+writemask_matches_swizzle(unsigned writemask, unsigned swizzle)
+{
+ for (int i = 0; i < 4; i++) {
+ unsigned channel = 1 << BRW_GET_SWZ(swizzle, i);
+ if (!(writemask & channel))
+ return false;
+ }
+
+ return true;
+}
+
void
vec4_visitor::spill_reg(int spill_reg_nr)
{
@@ -341,11 +353,33 @@ vec4_visitor::spill_reg(int spill_reg_nr)
unsigned int spill_offset = last_scratch++;
/* Generate spill/unspill instructions for the objects being spilled. */
+ vec4_instruction *spill_write_inst = NULL;
foreach_block_and_inst(block, vec4_instruction, inst, cfg) {
+ /* We don't spill registers used for scratch */
+ if (inst->opcode == SHADER_OPCODE_GEN4_SCRATCH_READ ||
+ inst->opcode == SHADER_OPCODE_GEN4_SCRATCH_WRITE)
+ continue;
+
int scratch_reg = -1;
for (unsigned int i = 0; i < 3; i++) {
if (inst->src[i].file == GRF && inst->src[i].reg == spill_reg_nr) {
- if (scratch_reg == -1) {
+ /* If we are reading the spilled register right after writing
+ * to it we can skip the scratch read and use directly the
+ * register we used as source for the scratch write. For this
+ * to work we must check that:
+ *
+ * 1) The write is inconditional, that is, it is not predicated or
+ it is a SEL.
+ * 2) All the channels that we read have been written in that
+ * last write instruction.
+ */
+ if (spill_write_inst &&
+ (!spill_write_inst->predicate ||
+ spill_write_inst->opcode == BRW_OPCODE_SEL) &&
+ writemask_matches_swizzle(spill_write_inst->dst.writemask,
+ inst->src[i].swizzle)) {
+ scratch_reg = spill_write_inst->dst.reg;
+ } else if (scratch_reg == -1) {
scratch_reg = alloc.allocate(1);
src_reg temp = inst->src[i];
temp.reg = scratch_reg;
@@ -358,6 +392,9 @@ vec4_visitor::spill_reg(int spill_reg_nr)
if (inst->dst.file == GRF && inst->dst.reg == spill_reg_nr) {
emit_scratch_write(block, inst, spill_offset);
+ spill_write_inst = inst;
+ } else {
+ spill_write_inst = NULL;
}
}
--
1.9.1
More information about the mesa-dev
mailing list