panfrost/panvk: Reduce fills from LCRA

Currently when LCRA spills it also fills on every single usage of the
spilled value. This leads to a lot of cases where a spill is immediately
followed by a fill.

This patch reduces fills by LCRA by simply not filling until reaching
either the index that caused LCRA to fail allocating registers, or the
end of a block.

Reviewed-by: Eric R. Smith <eric.smith@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37299>
This commit is contained in:
Ludvig Lindau
2025-09-24 11:14:08 +00:00
committed by Marge Bot
parent a26e46980e
commit ba293ebbc8
+38 -25
View File
@@ -737,7 +737,8 @@ bi_compute_reg_alignment(bi_context *ctx)
/* Once we've chosen a spill node, spill it and return new (aligned) offset */
static unsigned
bi_spill_register(bi_context *ctx, bi_index index, uint32_t offset)
bi_spill_register(bi_context *ctx, bi_index index, uint32_t offset,
bi_index spill_point)
{
bi_builder b = {.shader = ctx};
unsigned alignment = 4;
@@ -755,34 +756,45 @@ bi_spill_register(bi_context *ctx, bi_index index, uint32_t offset)
offset = ALIGN_POT(offset, alignment);
/* Spill after every store, fill before every load */
bi_foreach_instr_global_safe(ctx, I) {
bi_foreach_dest(I, d) {
if (!bi_is_equiv(I->dest[d], index))
continue;
bi_foreach_block(ctx, block) {
bool fill = true;
bool found_spill_point = false;
bi_foreach_instr_in_block_safe(block, I) {
bi_foreach_dest(I, d) {
if (bi_is_equiv(I->dest[d], spill_point)) {
found_spill_point = true;
fill = true;
}
if (!bi_is_equiv(I->dest[d], index))
continue;
unsigned count = bi_count_write_registers(I, d);
unsigned extra = I->dest[d].offset;
unsigned count = bi_count_write_registers(I, d);
unsigned extra = I->dest[d].offset;
channels = MAX2(channels, extra + count);
I->no_spill = true;
channels = MAX2(channels, extra + count);
I->no_spill = true;
if (channels == extra + count) {
b.cursor = bi_after_instr(I);
bi_store_tl(&b, channels * 32, index, offset);
ctx->spills++;
if (channels == extra + count) {
b.cursor = bi_after_instr(I);
bi_store_tl(&b, channels * 32, index, offset);
ctx->spills++;
/* Don't disable filling if spill_point is before index. */
fill = found_spill_point;
}
}
}
if (bi_has_arg(I, index)) {
b.cursor = bi_before_instr(I);
bi_index tmp = bi_temp(ctx);
if (bi_has_arg(I, index) && fill) {
b.cursor = bi_before_instr(I);
bi_index tmp = bi_temp(ctx);
unsigned bits = bi_count_read_index(I, index) * 32;
bi_rewrite_index_src_single(I, index, tmp);
unsigned bits = bi_count_read_index(I, index) * 32;
bi_rewrite_index_src_single(I, index, tmp);
bi_instr *ld = bi_load_tl(&b, bits, tmp, offset);
ld->no_spill = true;
ctx->fills++;
bi_instr *ld = bi_load_tl(&b, bits, tmp, offset);
ld->no_spill = true;
ctx->fills++;
}
}
}
@@ -1182,8 +1194,6 @@ bi_register_allocate(bi_context *ctx)
ctx->info.work_reg_count = BI_MAX_REGS;
} else {
signed spill_node = bi_choose_spill_node(ctx, l);
lcra_free(l);
l = NULL;
if (spill_node == -1)
UNREACHABLE("Failed to choose spill node\n");
@@ -1192,8 +1202,11 @@ bi_register_allocate(bi_context *ctx)
UNREACHABLE("Blend shaders may not spill");
spill_count =
bi_spill_register(ctx, bi_get_index(spill_node), spill_count);
bi_spill_register(ctx, bi_get_index(spill_node), spill_count,
bi_get_index(l->spill_node));
lcra_free(l);
l = NULL;
/* In case the spill affected an instruction with tied
* operands, we need to fix up.
*/