From 4760c763e4f33d3bc4ebedcbd4de8e8ef47a324d Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Wed, 5 Oct 2022 11:20:00 +0200 Subject: [PATCH] r600/sfn: Always start a new CF after a KILL instruction Docu says: Ensure that the KILL* instruction is the last instruction in an ALU clause, because the remaining instructions executed in the clause do not reflect the updated valid state after the kill operation. Fixes: 79ca456b4837b3bc21cf9ef3c03c505c4b4909f6 r600/sfn: rewrite NIR backend Signed-off-by: Gert Wollny Part-of: (cherry picked from commit 99b7a12ec12d5d76826051772fe474a547582e5e) --- .pick_status.json | 2 +- .../drivers/r600/sfn/sfn_instr_alugroup.cpp | 28 ++++++++++++++++++- .../drivers/r600/sfn/sfn_instr_alugroup.h | 2 ++ .../drivers/r600/sfn/sfn_scheduler.cpp | 8 +++++- .../drivers/r600/sfn/sfn_shader_fs.cpp | 1 + 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index fa040059416..40c9a1a5c3d 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -1021,7 +1021,7 @@ "description": "r600/sfn: Always start a new CF after a KILL instruction", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "79ca456b4837b3bc21cf9ef3c03c505c4b4909f6" }, diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp b/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp index 379919422bc..93a74ea0ea4 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp @@ -35,6 +35,25 @@ AluGroup::AluGroup() std::fill(m_slots.begin(), m_slots.end(), nullptr); } +static bool is_kill(EAluOp op) +{ + switch (op) { + case op2_kille: + case op2_kille_int: + case op2_killne: + case op2_killne_int: + case op2_killge: + case op2_killge_int: + case op2_killge_uint: + case op2_killgt: + case op2_killgt_int: + case op2_killgt_uint: + return true; + default: + return false; + } +} + bool AluGroup::add_instruction(AluInstr *instr) { /* we can only schedule one op that accesses LDS or @@ -45,12 +64,17 @@ bool AluGroup::add_instruction(AluInstr *instr) if (instr->has_alu_flag(alu_is_trans)) { auto opinfo = alu_ops.find(instr->opcode()); assert(opinfo->second.can_channel(AluOp::t, s_chip_class)); - if (add_trans_instructions(instr)) + if (add_trans_instructions(instr)) { + if (is_kill(instr->opcode())) + m_has_kill_op = true; return true; + } } if (add_vec_instructions(instr) && !instr->has_alu_flag(alu_is_trans)) { instr->set_parent_group(this); + if (!instr->has_alu_flag(alu_is_lds) && is_kill(instr->opcode())) + m_has_kill_op = true; return true; } @@ -61,6 +85,8 @@ bool AluGroup::add_instruction(AluInstr *instr) opinfo->second.can_channel(AluOp::t, s_chip_class) && add_trans_instructions(instr)) { instr->set_parent_group(this); + if (is_kill(instr->opcode())) + m_has_kill_op = true; return true; } diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.h b/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.h index df58df8204a..2ff31628c2c 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.h +++ b/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.h @@ -87,6 +87,7 @@ public: static bool has_t() { return s_max_slots == 5;} bool addr_for_src() const { return m_addr_for_src;} + bool has_kill_op() const {return m_has_kill_op;} private: void forward_set_blockid(int id, int index) override; @@ -111,6 +112,7 @@ private: bool m_has_lds_op{false}; bool m_addr_is_index{false}; bool m_addr_for_src{false}; + bool m_has_kill_op{false}; }; diff --git a/src/gallium/drivers/r600/sfn/sfn_scheduler.cpp b/src/gallium/drivers/r600/sfn/sfn_scheduler.cpp index abeac5615da..b4fab307923 100644 --- a/src/gallium/drivers/r600/sfn/sfn_scheduler.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_scheduler.cpp @@ -294,7 +294,6 @@ void BlockSheduler::schedule_block(Block& in_block, Shader::ShaderBlocks& out_bl bool have_instr = collect_ready(cir); m_current_block = new Block(in_block.nesting_depth(), in_block.id()); - assert(m_current_block->id() >= 0); while (have_instr) { @@ -569,6 +568,13 @@ bool BlockSheduler::schedule_alu(Shader::ShaderBlocks& out_blocks) if (group->has_lds_group_end()) m_current_block->lds_group_end(); + if (group->has_kill_op()) { + assert(!group->has_lds_group_start()); + start_new_block(out_blocks, Block::alu); + m_current_block->set_instr_flag(Instr::force_cf); + } + + return success; } diff --git a/src/gallium/drivers/r600/sfn/sfn_shader_fs.cpp b/src/gallium/drivers/r600/sfn/sfn_shader_fs.cpp index 09f2e6d876b..0251e1c8ede 100644 --- a/src/gallium/drivers/r600/sfn/sfn_shader_fs.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_shader_fs.cpp @@ -178,6 +178,7 @@ bool FragmentShader::process_stage_intrinsic(nir_intrinsic_instr *intr) value_factory().zero(), value_factory().zero(), {AluInstr::last})); + start_new_block(0); return true; case nir_intrinsic_load_sample_mask_in: if (m_apply_sample_mask) {