broadcom/compiler: make spills of conditional writes also conditional

A spill of a conditional write generates code like this:

mov.ifa t5000, 0
mov tmud, t5000
nop t5001; ldunif (0x00008100 / 0.000000)
add tmua, t11, t5001

Here, we are spilling t5000, which has a conditional write, and we
produce an inconditional spill for it. This implicitly means that
our spill requires a correct value for all channels of t5000.

If we do a conditional spill, then we emit:

mov.ifa t5000, 0
mov tmud.ifa, t5000
nop t5001; ldunif (0x00008100 / 0.000000)
add tmua.ifa, t11, t5001

Which only uses channels of t5000 that have been written by the
instruction being spilled.

By doing the latter, we can then narrow down the liveness for t5000
more effectively, as we can use this to detect that the block only reads
(in the tmud instruction) the values that have been written previously
in the same block (in the mov instruction). This means that values in
other channels are not used, and therefore, we don't need them to be
alive at the start of the block. This means that if this is the only
write of t5000 in this block, we can consider that the block
completely defines t5000.

Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12278>
This commit is contained in:
Iago Toral Quiroga
2021-08-09 08:29:49 +02:00
committed by Marge Bot
parent 314eb97dcb
commit c335c03ae2

View File

@@ -214,13 +214,11 @@ v3d_setup_spill_base(struct v3d_compile *c)
c->cursor = vir_after_block(c->cur_block);
}
static void
static struct qinst *
v3d_emit_spill_tmua(struct v3d_compile *c, uint32_t spill_offset)
{
vir_ADD_dest(c, vir_reg(QFILE_MAGIC,
V3D_QPU_WADDR_TMUA),
c->spill_base,
vir_uniform_ui(c, spill_offset));
return vir_ADD_dest(c, vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_TMUA),
c->spill_base, vir_uniform_ui(c, spill_offset));
}
@@ -228,12 +226,17 @@ static void
v3d_emit_tmu_spill(struct v3d_compile *c, struct qinst *inst,
struct qinst *position, uint32_t spill_offset)
{
assert(inst->qpu.type == V3D_QPU_INSTR_TYPE_ALU);
c->cursor = vir_after_inst(position);
inst->dst = vir_get_temp(c);
vir_MOV_dest(c, vir_reg(QFILE_MAGIC,
V3D_QPU_WADDR_TMUD),
inst->dst);
v3d_emit_spill_tmua(c, spill_offset);
enum v3d_qpu_cond cond = vir_get_cond(inst);
struct qinst *tmp =
vir_MOV_dest(c, vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_TMUD),
inst->dst);
tmp->qpu.flags.mc = cond;
tmp = v3d_emit_spill_tmua(c, spill_offset);
tmp->qpu.flags.ac = cond;
vir_emit_thrsw(c);
vir_TMUWT(c);
c->spills++;