From bed5a310053f576503bc9c3300e2c7ec7db08e74 Mon Sep 17 00:00:00 2001 From: Rhys Perry Date: Wed, 20 Oct 2021 09:11:51 +0100 Subject: [PATCH] aco: add validate_instr_defs() 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 | 88 ++++++++++++++++++------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/src/amd/compiler/aco_validate.cpp b/src/amd/compiler/aco_validate.cpp index da6dc183de6..7df92a5da39 100644 --- a/src/amd/compiler/aco_validate.cpp +++ b/src/amd/compiler/aco_validate.cpp @@ -902,6 +902,54 @@ get_subdword_bytes_written(Program* program, const aco_ptr& instr, } } +bool +validate_instr_defs(Program* program, std::array& regs, + const std::vector& assignments, const Location& loc, + aco_ptr& instr) +{ + bool err = false; + + for (unsigned i = 0; i < instr->definitions.size(); i++) { + Definition& def = instr->definitions[i]; + if (!def.isTemp()) + continue; + Temp tmp = def.getTemp(); + PhysReg reg = assignments[tmp.id()].reg; + for (unsigned j = 0; j < tmp.bytes(); j++) { + if (regs[reg.reg_b + j]) + err |= + ra_fail(program, loc, assignments[regs[reg.reg_b + j]].defloc, + "Assignment of element %d of %%%d already taken by %%%d from instruction", i, + tmp.id(), regs[reg.reg_b + j]); + regs[reg.reg_b + j] = tmp.id(); + } + if (def.regClass().is_subdword() && def.bytes() < 4) { + unsigned written = get_subdword_bytes_written(program, instr, i); + /* If written=4, the instruction still might write the upper half. In that case, it's + * the lower half that isn't preserved */ + for (unsigned j = reg.byte() & ~(written - 1); j < written; j++) { + unsigned written_reg = reg.reg() * 4u + j; + if (regs[written_reg] && regs[written_reg] != def.tempId()) + err |= ra_fail(program, loc, assignments[regs[written_reg]].defloc, + "Assignment of element %d of %%%d overwrites the full register " + "taken by %%%d from instruction", + i, tmp.id(), regs[written_reg]); + } + } + } + + for (const Definition& def : instr->definitions) { + if (!def.isTemp()) + continue; + if (def.isKill()) { + for (unsigned j = 0; j < def.getTemp().bytes(); j++) + regs[def.physReg().reg_b + j] = 0; + } + } + + return err; +} + } /* end namespace */ bool @@ -1085,45 +1133,9 @@ validate_ra(Program* program) } } - for (unsigned i = 0; i < instr->definitions.size(); i++) { - Definition& def = instr->definitions[i]; - if (!def.isTemp()) - continue; - Temp tmp = def.getTemp(); - PhysReg reg = assignments[tmp.id()].reg; - for (unsigned j = 0; j < tmp.bytes(); j++) { - if (regs[reg.reg_b + j]) - err |= ra_fail( - program, loc, assignments[regs[reg.reg_b + j]].defloc, - "Assignment of element %d of %%%d already taken by %%%d from instruction", i, - tmp.id(), regs[reg.reg_b + j]); - regs[reg.reg_b + j] = tmp.id(); - } - if (def.regClass().is_subdword() && def.bytes() < 4) { - unsigned written = get_subdword_bytes_written(program, instr, i); - /* If written=4, the instruction still might write the upper half. In that case, it's - * the lower half that isn't preserved */ - for (unsigned j = reg.byte() & ~(written - 1); j < written; j++) { - unsigned written_reg = reg.reg() * 4u + j; - if (regs[written_reg] && regs[written_reg] != def.tempId()) - err |= ra_fail(program, loc, assignments[regs[written_reg]].defloc, - "Assignment of element %d of %%%d overwrites the full register " - "taken by %%%d from instruction", - i, tmp.id(), regs[written_reg]); - } - } - } + err |= validate_instr_defs(program, regs, assignments, loc, instr); - for (const Definition& def : instr->definitions) { - if (!def.isTemp()) - continue; - if (def.isKill()) { - for (unsigned j = 0; j < def.getTemp().bytes(); j++) - regs[def.physReg().reg_b + j] = 0; - } - } - - if (instr->opcode != aco_opcode::p_phi && instr->opcode != aco_opcode::p_linear_phi) { + if (!is_phi(instr)) { for (const Operand& op : instr->operands) { if (!op.isTemp()) continue;