From 89d06f7db53e41cbc7cb7771d7c03b2f5d219b68 Mon Sep 17 00:00:00 2001 From: Rhys Perry Date: Mon, 1 Dec 2025 15:52:06 +0000 Subject: [PATCH] aco: add RA validation for p_call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rhys Perry Reviewed-by: Daniel Schürmann Part-of: --- src/amd/compiler/aco_validate.cpp | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/amd/compiler/aco_validate.cpp b/src/amd/compiler/aco_validate.cpp index 9a6bd76b1cf..63fe8e7b156 100644 --- a/src/amd/compiler/aco_validate.cpp +++ b/src/amd/compiler/aco_validate.cpp @@ -1545,6 +1545,53 @@ validate_instr_defs(Program* program, std::array& regs, return err; } +bool +validate_call(Program* program, std::array& regs, + const std::vector& assignments, const Location& loc, + aco_ptr& instr) +{ + bool err = false; + + RegisterDemand limit = get_addr_regs_from_waves(program, program->min_waves); + BITSET_DECLARE(preserved_regs, 512); + instr->call().abi.preservedRegisters(preserved_regs, limit); + + /* TODO: This is a hack. I think the return address should not be precolored to a preserved + * register. */ + BITSET_CLEAR(preserved_regs, instr->definitions[0].physReg().reg()); + BITSET_CLEAR(preserved_regs, instr->definitions[0].physReg().reg() + 1); + + for (unsigned i = 0; i < regs.size(); i++) { + unsigned temp = regs[i]; + bool is_preserved = BITSET_TEST(preserved_regs, i / 4); + if (!temp || is_preserved) + continue; + + bool can_use_clobbered = + program->temp_rc[temp].is_linear_vgpr() || + std::any_of( + instr->operands.begin(), instr->operands.end(), [&](const Operand& op) + { return op.tempId() == temp && (op.isKillBeforeDef() || !op.isClobbered()); }); + if (!can_use_clobbered) { + err |= ra_fail(program, loc, assignments[temp].defloc, + "Assignment of %%%d in clobbered register at call instruction", temp); + } + } + + for (Definition def : instr->definitions) { + for (unsigned i = 0; i < def.bytes(); i++) { + bool is_preserved = BITSET_TEST(preserved_regs, (def.physReg().reg_b + i) / 4); + if (is_preserved) { + err |= ra_fail(program, loc, Location(), + "Assignment of %%%d in callee-preserved register of call instruction", + def.tempId()); + } + } + } + + return err; +} + } /* end namespace */ bool @@ -1681,6 +1728,9 @@ validate_ra(Program* program) } } + if (instr->isCall()) + err |= validate_call(program, regs, assignments, loc, instr); + if (instr->opcode != aco_opcode::p_phi && instr->opcode != aco_opcode::p_linear_phi) { for (const Operand& op : instr->operands) { if (!op.isTemp())