aco: add validate_instr_defs()
Signed-off-by: Rhys Perry <pendingchaos02@gmail.com> Reviewed-by: Daniel Schürmann <daniel@schuermann.dev> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13432>
This commit is contained in:
@@ -902,6 +902,54 @@ get_subdword_bytes_written(Program* program, const aco_ptr<Instruction>& instr,
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
validate_instr_defs(Program* program, std::array<unsigned, 2048>& regs,
|
||||
const std::vector<Assignment>& assignments, const Location& loc,
|
||||
aco_ptr<Instruction>& 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;
|
||||
|
||||
Reference in New Issue
Block a user