aco: improve VcmpxPermlaneHazard workaround

According to LLVM, we only need to care about VOPC which writes exec.

No fossil-db changes.

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17697>
This commit is contained in:
Rhys Perry
2022-07-13 19:37:27 +01:00
committed by Marge Bot
parent 5912c7d3fa
commit bf0af80045
2 changed files with 15 additions and 14 deletions
+1 -2
View File
@@ -257,8 +257,7 @@ ACO doesn't use FLAT load/store on GFX10, so is unaffected.
### VcmpxPermlaneHazard
Triggered by:
Any permlane instruction that follows any VOPC instruction.
Confirmed by AMD devs that despite the name, this doesn't only affect v_cmpx.
Any permlane instruction that follows any VOPC instruction which writes exec.
Mitigated by: any VALU instruction except `v_nop`.
+14 -12
View File
@@ -150,7 +150,7 @@ struct NOP_ctx_gfx6 {
};
struct NOP_ctx_gfx10 {
bool has_VOPC = false;
bool has_VOPC_write_exec = false;
bool has_nonVALU_exec_read = false;
bool has_VMEM = false;
bool has_branch_after_VMEM = false;
@@ -163,7 +163,7 @@ struct NOP_ctx_gfx10 {
void join(const NOP_ctx_gfx10& other)
{
has_VOPC |= other.has_VOPC;
has_VOPC_write_exec |= other.has_VOPC_write_exec;
has_nonVALU_exec_read |= other.has_nonVALU_exec_read;
has_VMEM |= other.has_VMEM;
has_branch_after_VMEM |= other.has_branch_after_VMEM;
@@ -177,9 +177,10 @@ struct NOP_ctx_gfx10 {
bool operator==(const NOP_ctx_gfx10& other)
{
return has_VOPC == other.has_VOPC && has_nonVALU_exec_read == other.has_nonVALU_exec_read &&
has_VMEM == other.has_VMEM && has_branch_after_VMEM == other.has_branch_after_VMEM &&
has_DS == other.has_DS && has_branch_after_DS == other.has_branch_after_DS &&
return has_VOPC_write_exec == other.has_VOPC_write_exec &&
has_nonVALU_exec_read == other.has_nonVALU_exec_read && has_VMEM == other.has_VMEM &&
has_branch_after_VMEM == other.has_branch_after_VMEM && has_DS == other.has_DS &&
has_branch_after_DS == other.has_branch_after_DS &&
has_NSA_MIMG == other.has_NSA_MIMG && has_writelane == other.has_writelane &&
sgprs_read_by_VMEM == other.sgprs_read_by_VMEM &&
sgprs_read_by_SMEM == other.sgprs_read_by_SMEM;
@@ -679,13 +680,14 @@ handle_instruction_gfx10(State& state, NOP_ctx_gfx10& ctx, aco_ptr<Instruction>&
}
/* VcmpxPermlaneHazard
* Handle any permlane following a VOPC instruction, insert v_mov between them.
* Handle any permlane following a VOPC instruction writing exec, insert v_mov between them.
*/
if (instr->isVOPC()) {
ctx.has_VOPC = true;
} else if (ctx.has_VOPC && (instr->opcode == aco_opcode::v_permlane16_b32 ||
instr->opcode == aco_opcode::v_permlanex16_b32)) {
ctx.has_VOPC = false;
if (instr->isVOPC() && instr->definitions[0].physReg() == exec) {
/* we only need to check definitions[0] because since GFX10 v_cmpx only writes one dest */
ctx.has_VOPC_write_exec = true;
} else if (ctx.has_VOPC_write_exec && (instr->opcode == aco_opcode::v_permlane16_b32 ||
instr->opcode == aco_opcode::v_permlanex16_b32)) {
ctx.has_VOPC_write_exec = false;
/* v_nop would be discarded by SQ, so use v_mov with the first operand of the permlane */
aco_ptr<VOP1_instruction> v_mov{
@@ -694,7 +696,7 @@ handle_instruction_gfx10(State& state, NOP_ctx_gfx10& ctx, aco_ptr<Instruction>&
v_mov->operands[0] = Operand(instr->operands[0].physReg(), v1);
new_instructions.emplace_back(std::move(v_mov));
} else if (instr->isVALU() && instr->opcode != aco_opcode::v_nop) {
ctx.has_VOPC = false;
ctx.has_VOPC_write_exec = false;
}
/* VcmpxExecWARHazard