From eba3d3a17e4cb9f53d627119179f9f29bd6c443b Mon Sep 17 00:00:00 2001 From: Christoph Pillmayer Date: Mon, 20 Oct 2025 10:11:16 +0000 Subject: [PATCH] pan: Enable rematerialization for more ops IADD_IMM and uniform loads should not be spilled. Make them rematerializable. Restrict to loads that write at most one register for simplicity for now. Reviewed-by: Lars-Ivar Hesselberg Simonsen Reviewed-by: Eric R. Smith Part-of: --- src/panfrost/compiler/bi_spill_ssa.c | 42 ++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/panfrost/compiler/bi_spill_ssa.c b/src/panfrost/compiler/bi_spill_ssa.c index 99424c5decb..c04d40e9f59 100644 --- a/src/panfrost/compiler/bi_spill_ssa.c +++ b/src/panfrost/compiler/bi_spill_ssa.c @@ -2,6 +2,7 @@ * Copyright 2023-2024 Alyssa Rosenzweig * Copyright 2023-2024 Valve Corporation * Copyright 2022,2025 Collabora Ltd. + * Copyright 2025 Arm Ltd. * SPDX-License-Identifier: MIT */ @@ -306,15 +307,37 @@ reconstruct_index(struct spill_ctx *ctx, unsigned node) return r; } +static bool +only_const_sources(bi_instr *I) +{ + bool res = true; + for (uint32_t s = 0; s < I->nr_srcs && res; ++s) { + bi_index src = I->src[s]; + enum bi_index_type t = src.type; + res &= t == BI_INDEX_CONSTANT || t == BI_INDEX_FAU; + } + return res; +} + static bool can_remat(bi_instr *I) { switch (I->op) { + case BI_OPCODE_IADD_IMM_I32: + case BI_OPCODE_IADD_IMM_V2I16: + return only_const_sources(I); + case BI_OPCODE_LD_BUFFER_I8: + case BI_OPCODE_LD_BUFFER_I16: + case BI_OPCODE_LD_BUFFER_I24: + case BI_OPCODE_LD_BUFFER_I32: + /* TODO: Allow loads that write >1 reg. */ + return only_const_sources(I); case BI_OPCODE_MOV_I32: assert(!I->src[0].memory); assert(!I->dest[0].memory); assert(I->dest[0].type == BI_INDEX_NORMAL); - return (I->src[0].type == BI_INDEX_CONSTANT); // || (I->src[0].type == BI_INDEX_REGISTER); + enum bi_index_type t = I->src[0].type; + return t == BI_INDEX_CONSTANT || t == BI_INDEX_FAU; default: return false; } @@ -323,14 +346,27 @@ can_remat(bi_instr *I) static bi_instr * remat_to(bi_builder *b, bi_index dst, struct spill_ctx *ctx, unsigned node) { + assert(dst.type == BI_INDEX_NORMAL); assert(node < ctx->spill_max); bi_instr *I = ctx->remat[node]; assert(can_remat(I)); switch (I->op) { + case BI_OPCODE_IADD_IMM_I32: + return bi_iadd_imm_i32_to(b, dst, I->src[0], I->index); + case BI_OPCODE_IADD_IMM_V2I16: + return bi_iadd_imm_v2i16_to(b, dst, I->src[0], I->index); + case BI_OPCODE_LD_BUFFER_I8: + return bi_ld_buffer_i8_to(b, dst, I->src[0], I->src[1]); + case BI_OPCODE_LD_BUFFER_I16: + return bi_ld_buffer_i16_to(b, dst, I->src[0], I->src[1]); + case BI_OPCODE_LD_BUFFER_I24: + return bi_ld_buffer_i24_to(b, dst, I->src[0], I->src[1]); + case BI_OPCODE_LD_BUFFER_I32: + return bi_ld_buffer_i32_to(b, dst, I->src[0], I->src[1]); case BI_OPCODE_MOV_I32: - assert(I->src[0].type == BI_INDEX_CONSTANT /*|| I->src[0].type == BI_INDEX_REGISTER*/); - assert(dst.type == BI_INDEX_NORMAL); + assert(I->src[0].type == BI_INDEX_CONSTANT || + I->src[0].type == BI_INDEX_FAU); return bi_mov_i32_to(b, dst, I->src[0]); default: UNREACHABLE("invalid remat");