pan/midg: Add intra-bundle interferences

The register allocator assumes instructions are executed sequentially
and allows one instruction to overwrite a portion of a register written
by a previous instruction if this portion is never used. But scalar and
vector ALUs might be executed in parallel if they are part of the same
bundle, and when such instructions write to the same portion of the
register file, the result is undefined.

Let's add intra-bundle interferences to avoid this situation.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14885>
This commit is contained in:
Boris Brezillon
2021-09-06 11:49:10 +02:00
committed by Alyssa Rosenzweig
parent 183bc15bdb
commit 967eb4988e
+38
View File
@@ -350,6 +350,44 @@ mir_compute_interference(
mir_foreach_block(ctx, _blk) {
midgard_block *blk = (midgard_block *) _blk;
/* The scalar and vector units run in parallel. We need to make
* sure they don't write to same portion of the register file
* otherwise the result is undefined. Add interferences to
* avoid this situation.
*/
util_dynarray_foreach(&blk->bundles, midgard_bundle, bundle) {
midgard_instruction *instrs[2][3];
unsigned instr_count[2] = { 0, 0 };
for (unsigned i = 0; i < bundle->instruction_count; i++) {
if (bundle->instructions[i]->unit == UNIT_VMUL ||
bundle->instructions[i]->unit == UNIT_SADD)
instrs[0][instr_count[0]++] = bundle->instructions[i];
else
instrs[1][instr_count[1]++] = bundle->instructions[i];
}
for (unsigned i = 0; i < ARRAY_SIZE(instr_count); i++) {
for (unsigned j = 0; j < instr_count[i]; j++) {
midgard_instruction *ins_a = instrs[i][j];
if (ins_a->dest >= ctx->temp_count) continue;
for (unsigned k = j + 1; k < instr_count[i]; k++) {
midgard_instruction *ins_b = instrs[i][k];
if (ins_b->dest >= ctx->temp_count) continue;
lcra_add_node_interference(l, ins_b->dest,
mir_bytemask(ins_b),
ins_a->dest,
mir_bytemask(ins_a));
}
}
}
}
uint16_t *live = mem_dup(_blk->live_out, ctx->temp_count * sizeof(uint16_t));
mir_foreach_instr_in_block_rev(blk, ins) {