Module: Mesa Branch: main Commit: b12d7f10d45cc59df79bdd30cc23dda21c6e3d44 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=b12d7f10d45cc59df79bdd30cc23dda21c6e3d44
Author: Georg Lehmann <[email protected]> Date: Fri Nov 10 14:17:44 2023 +0100 aco: validate ALU operands and defs Reviewed-by: Rhys Perry <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26163> --- src/amd/compiler/aco_validate.cpp | 93 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/src/amd/compiler/aco_validate.cpp b/src/amd/compiler/aco_validate.cpp index fd70b343e9c..2823bb26d97 100644 --- a/src/amd/compiler/aco_validate.cpp +++ b/src/amd/compiler/aco_validate.cpp @@ -105,6 +105,99 @@ validate_ir(Program* program) for (Block& block : program->blocks) { for (aco_ptr<Instruction>& instr : block.instructions) { + unsigned pck_defs = instr_info.definitions[(int)instr->opcode]; + unsigned pck_ops = instr_info.operands[(int)instr->opcode]; + + if (pck_defs != 0) { + /* Before GFX10 v_cmpx also writes VCC. */ + if (instr->isVOPC() && program->gfx_level < GFX10 && pck_defs == exec_hi) + pck_defs = vcc | (exec_hi << 8); + + for (unsigned i = 0; i < 4; i++) { + uint32_t def = (pck_defs >> (i * 8)) & 0xff; + if (def == 0) { + check(i == instr->definitions.size(), "Too many definitions", instr.get()); + break; + } else { + check(i < instr->definitions.size(), "Too few definitions", instr.get()); + if (i >= instr->definitions.size()) + break; + } + + if (def == m0) { + check(instr->definitions[i].isFixed() && instr->definitions[i].physReg() == m0, + "Definition needs m0", instr.get()); + } else if (def == scc) { + check(instr->definitions[i].isFixed() && instr->definitions[i].physReg() == scc, + "Definition needs scc", instr.get()); + } else if (def == exec_hi) { + RegClass rc = instr->isSALU() ? s2 : program->lane_mask; + check(instr->definitions[i].isFixed() && + instr->definitions[i].physReg() == exec && + instr->definitions[i].regClass() == rc, + "Definition needs exec", instr.get()); + } else if (def == exec_lo) { + check(instr->definitions[i].isFixed() && + instr->definitions[i].physReg() == exec_lo && + instr->definitions[i].regClass() == s1, + "Definition needs exec_lo", instr.get()); + } else if (def == vcc) { + check(instr->definitions[i].regClass() == program->lane_mask, + "Definition has to be lane mask", instr.get()); + check(!instr->definitions[i].isFixed() || + instr->definitions[i].physReg() == vcc || instr->isVOP3() || + instr->isSDWA(), + "Definition has to be vcc", instr.get()); + } else { + check(instr->definitions[i].size() == def, "Definition has wrong size", + instr.get()); + } + } + } + + if (pck_ops != 0) { + for (unsigned i = 0; i < 4; i++) { + uint32_t op = (pck_ops >> (i * 8)) & 0xff; + if (op == 0) { + check(i == instr->operands.size(), "Too many operands", instr.get()); + break; + } else { + check(i < instr->operands.size(), "Too few operands", instr.get()); + if (i >= instr->operands.size()) + break; + } + + if (op == m0) { + check(instr->operands[i].isFixed() && instr->operands[i].physReg() == m0, + "Operand needs m0", instr.get()); + } else if (op == scc) { + check(instr->operands[i].isFixed() && instr->operands[i].physReg() == scc, + "Operand needs scc", instr.get()); + } else if (op == exec_hi) { + RegClass rc = instr->isSALU() ? s2 : program->lane_mask; + check(instr->operands[i].isFixed() && instr->operands[i].physReg() == exec && + instr->operands[i].hasRegClass() && instr->operands[i].regClass() == rc, + "Operand needs exec", instr.get()); + } else if (op == exec_lo) { + check(instr->operands[i].isFixed() && instr->operands[i].physReg() == exec_lo && + instr->operands[i].hasRegClass() && instr->operands[i].regClass() == s1, + "Operand needs exec_lo", instr.get()); + } else if (op == vcc) { + check(instr->operands[i].hasRegClass() && + instr->operands[i].regClass() == program->lane_mask, + "Operand has to be lane mask", instr.get()); + check(!instr->operands[i].isFixed() || instr->operands[i].physReg() == vcc || + instr->isVOP3(), + "Operand has to be vcc", instr.get()); + } else { + check(instr->operands[i].size() == op || + (instr->operands[i].isFixed() && instr->operands[i].physReg() >= 128 && + instr->operands[i].physReg() < 256), + "Operand has wrong size", instr.get()); + } + } + } + /* check base format */ Format base_format = instr->format; base_format = (Format)((uint32_t)base_format & ~(uint32_t)Format::SDWA);
