diff --git a/src/amd/compiler/aco_insert_exec_mask.cpp b/src/amd/compiler/aco_insert_exec_mask.cpp index 56e7045b852..55f9accb0bb 100644 --- a/src/amd/compiler/aco_insert_exec_mask.cpp +++ b/src/amd/compiler/aco_insert_exec_mask.cpp @@ -718,18 +718,27 @@ process_instructions(exec_ctx& ctx, Block* block, std::vectorindex); ctx.info[block->index].exec.back().second &= ~mask_type_global; } - int num = ctx.info[block->index].exec.size(); - assert(num); - /* discard from current exec */ - const Operand cond = instr->operands[0]; - Temp exit_cond = bld.sop2(Builder::s_andn2, Definition(exec, bld.lm), bld.def(s1, scc), - Operand(exec, bld.lm), cond) - .def(1) - .getTemp(); + Temp cond, exit_cond; + if (instr->operands[0].isConstant()) { + assert(instr->operands[0].constantValue() == -1u); + /* save condition and set exec to zero */ + exit_cond = bld.tmp(s1); + cond = + bld.sop1(Builder::s_and_saveexec, bld.def(bld.lm), bld.scc(Definition(exit_cond)), + Definition(exec, bld.lm), Operand::zero(), Operand(exec, bld.lm)); + } else { + cond = instr->operands[0].getTemp(); + /* discard from current exec */ + exit_cond = bld.sop2(Builder::s_andn2, Definition(exec, bld.lm), bld.def(s1, scc), + Operand(exec, bld.lm), cond) + .def(1) + .getTemp(); + } /* discard from inner to outer exec mask on stack */ - for (int i = num - 2; i >= 0; i--) { + int num = ctx.info[block->index].exec.size() - 2; + for (int i = num; i >= 0; i--) { Instruction* andn2 = bld.sop2(Builder::s_andn2, bld.def(bld.lm), bld.def(s1, scc), ctx.info[block->index].exec[i].first, cond); ctx.info[block->index].exec[i].first = Operand(andn2->definitions[0].getTemp()); diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index d8af3d9e76b..bf202bebc1e 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -5754,39 +5754,10 @@ visit_discard(isel_context* ctx, nir_intrinsic_instr* instr) return; } - /* it can currently happen that NIR doesn't remove the unreachable code */ - if (!nir_instr_is_last(&instr->instr)) { - ctx->program->needs_exact = true; - /* save exec somewhere temporarily so that it doesn't get - * overwritten before the discard from outer exec masks */ - Temp cond = bld.sop2(Builder::s_and, bld.def(bld.lm), bld.def(s1, scc), - Operand::c32(0xFFFFFFFF), Operand(exec, bld.lm)); - bld.pseudo(aco_opcode::p_discard_if, cond); - ctx->block->kind |= block_kind_uses_discard_if; - return; - } - - /* This condition is incorrect for uniformly branched discards in a loop - * predicated by a divergent condition, but the above code catches that case - * and the discard would end up turning into a discard_if. - * For example: - * if (divergent) { - * while (...) { - * if (uniform) { - * discard; - * } - * } - * } - */ - if (!ctx->cf_info.parent_if.is_divergent) { - /* program just ends here */ - ctx->block->kind |= block_kind_uses_discard_if; - bld.pseudo(aco_opcode::p_discard_if, Operand::c32(0xFFFFFFFFu)); - // TODO: it will potentially be followed by a branch which is dead code to sanitize NIR phis - } else { - ctx->block->kind |= block_kind_discard; - /* branch and linear edge is added by visit_if() */ - } + ctx->program->needs_exact = true; + bld.pseudo(aco_opcode::p_discard_if, Operand::c32(-1u)); + ctx->block->kind |= block_kind_uses_discard_if; + return; } enum aco_descriptor_type {