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: 79ca456b48
    r600/sfn: rewrite NIR backend

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18983>
(cherry picked from commit 99b7a12ec1)
This commit is contained in:
Gert Wollny
2022-10-05 11:20:00 +02:00
committed by Dylan Baker
parent 52eac47f75
commit 4760c763e4
5 changed files with 38 additions and 3 deletions

View File

@@ -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"
},

View File

@@ -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;
}

View File

@@ -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};
};

View File

@@ -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;
}

View File

@@ -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) {