From 3427b20b7191eb8eafa9a1861e1b3c4c7b8a4b77 Mon Sep 17 00:00:00 2001 From: Christoph Pillmayer Date: Mon, 23 Feb 2026 14:10:59 +0100 Subject: [PATCH] pan/bi: Fix MEMMOV size calculation Doing stores first, loads second doesn't work because there can be chains of store, load, store... . Use a fixed point approach instead to calculate sizes for all destinations. Fixes: 2fd5b8a391a ("pan/bi: Account for MEMMOV in bi_record_sizes") Reviewed-by: Faith Ekstrand Part-of: --- src/panfrost/compiler/bifrost/bi_spill_ssa.c | 88 +++++++++----------- 1 file changed, 41 insertions(+), 47 deletions(-) diff --git a/src/panfrost/compiler/bifrost/bi_spill_ssa.c b/src/panfrost/compiler/bifrost/bi_spill_ssa.c index 2e1bf023a64..201483f076f 100644 --- a/src/panfrost/compiler/bifrost/bi_spill_ssa.c +++ b/src/panfrost/compiler/bifrost/bi_spill_ssa.c @@ -1398,58 +1398,52 @@ min_algorithm(struct spill_ctx *ctx) void bi_record_sizes(bi_context *ctx, uint32_t *sizes) { - bi_foreach_instr_global(ctx, I) { - if (I->nr_dests == 0 || I->dest[0].type != BI_INDEX_NORMAL) - continue; - unsigned idx = I->dest[0].value; - bi_foreach_ssa_dest(I, d) { - idx = I->dest[d].value; - assert(sizes[idx] == 0 && "SSA broken"); - switch (I->op) { - case BI_OPCODE_PHI: - case BI_OPCODE_MEMMOV: - break; - default: - sizes[idx] = bi_count_write_registers(I, d); - break; - } - } - } + memset(sizes, 0, ctx->ssa_alloc); - /* now that we know the rest of the sizes, find the sizes for PHI nodes */ - bi_foreach_block(ctx, block) { - bi_foreach_phi_in_block(block, I) { - if (I->dest[0].type != BI_INDEX_NORMAL) + bool progress = true; + + while (progress) { + progress = false; + + bi_foreach_instr_global(ctx, I) { + if (I->nr_dests == 0 || I->dest[0].type != BI_INDEX_NORMAL) continue; - unsigned idx = I->dest[0].value; - sizes[idx] = 1; - bi_foreach_ssa_src(I, s) { - sizes[idx] = MAX2(sizes[idx], sizes[I->src[s].value]); + + bi_foreach_ssa_dest(I, d) { + const uint32_t old_size = sizes[I->dest[d].value]; + uint32_t new_size = old_size; + + switch (I->op) { + case BI_OPCODE_PHI: + case BI_OPCODE_MEMMOV: + /* Output size determined by the inputs. */ + bi_foreach_src(I, s) { + switch (I->src[s].type) { + case BI_INDEX_NORMAL: + new_size = MAX2(new_size, sizes[I->src[s].value]); + break; + case BI_INDEX_CONSTANT: + case BI_INDEX_FAU: + new_size = 1; + break; + default: + UNREACHABLE("invalid index type for size calculation\n"); + } + } + break; + default: + /* Output size independent of the inputs. */ + new_size = bi_count_write_registers(I, d); + break; + } + + /* Need to continue if there was a change or the dst is not yet + * defined. */ + progress |= new_size == 0 || old_size != new_size; + sizes[I->dest[d].value] = new_size; } } } - - /* After we know PHI sizes, determine MEMMOV sizes. */ - - bi_foreach_instr_global(ctx, I) { - if (I->op != BI_OPCODE_MEMMOV || I->dest[0].type != BI_INDEX_NORMAL) - continue; - - if (I->dest[0].memory) { - assert(!I->src[0].memory); - sizes[I->dest[0].value] = sizes[I->src[0].value]; - } - } - - bi_foreach_instr_global(ctx, I) { - if (I->op != BI_OPCODE_MEMMOV || I->dest[0].type != BI_INDEX_NORMAL) - continue; - - if (!I->dest[0].memory) { - assert(I->src[0].memory); - sizes[I->dest[0].value] = sizes[I->src[0].value]; - } - } } static void