mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-06 17:30:20 +01:00
aco: emit nir_intrinsic_discard() as p_discard_if()
This simplifies the code and emits a slightly better sequence in some cases. Reviewed-by: Rhys Perry <pendingchaos02@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14805>
This commit is contained in:
parent
1895e17591
commit
b67092e685
2 changed files with 22 additions and 42 deletions
|
|
@ -718,18 +718,27 @@ process_instructions(exec_ctx& ctx, Block* block, std::vector<aco_ptr<Instructio
|
|||
transition_to_WQM(ctx, bld, block->index);
|
||||
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());
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue