mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-01 03:48:06 +02:00
aco: optimize boolean phi with empty else block
We can keep the else empty by handling the phi in the "then" block. Foz-DB Navi21: Totals from 921 (1.15% of 80065) affected shaders: Instrs: 4532598 -> 4527309 (-0.12%); split: -0.12%, +0.00% CodeSize: 24498484 -> 24481780 (-0.07%); split: -0.08%, +0.01% Latency: 41016915 -> 41020477 (+0.01%); split: -0.10%, +0.11% InvThroughput: 9998405 -> 9991873 (-0.07%); split: -0.08%, +0.02% SClause: 128261 -> 128267 (+0.00%) Copies: 409949 -> 408585 (-0.33%); split: -0.36%, +0.02% Branches: 169740 -> 169222 (-0.31%); split: -0.58%, +0.27% PreSGPRs: 64408 -> 64398 (-0.02%) VALU: 2972521 -> 2972518 (-0.00%) SALU: 673844 -> 668973 (-0.72%); split: -0.72%, +0.00% Reviewed-by: Daniel Schürmann <daniel@schuermann.dev> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35165>
This commit is contained in:
parent
4a2884237a
commit
001fe8c236
1 changed files with 67 additions and 4 deletions
|
|
@ -184,7 +184,6 @@ build_const_else_merge_code(Program* program, Block& invert_block, aco_ptr<Instr
|
|||
* instructions to the invert block instead.
|
||||
* This allows us to actually delete the else block when it's empty.
|
||||
*/
|
||||
assert(invert_block.kind & block_kind_invert);
|
||||
Builder bld(program);
|
||||
Operand then = phi->operands[0];
|
||||
const Operand els = phi->operands[1];
|
||||
|
|
@ -220,6 +219,61 @@ build_const_else_merge_code(Program* program, Block& invert_block, aco_ptr<Instr
|
|||
phi->operands[1] = Operand(tmp);
|
||||
}
|
||||
|
||||
bool
|
||||
block_is_empty(Block& block)
|
||||
{
|
||||
for (auto& instr : block.instructions) {
|
||||
if (instr->opcode != aco_opcode::p_logical_start &&
|
||||
instr->opcode != aco_opcode::p_logical_end && instr->opcode != aco_opcode::p_branch)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
build_empty_else_merge_code(Program* program, Block& merge_block, Block& invert_block,
|
||||
aco_ptr<Instruction>& phi)
|
||||
{
|
||||
/* If the else block is empty, we know that the else phi operand dominates the
|
||||
* then block, so we can handle the phi only in the then block.
|
||||
*/
|
||||
Builder bld(program);
|
||||
Block& then_block = program->blocks[merge_block.logical_preds[0]];
|
||||
Operand then_op = phi->operands[0];
|
||||
Operand else_op = phi->operands[1];
|
||||
|
||||
auto before_logical_end =
|
||||
std::find_if(then_block.instructions.begin(), then_block.instructions.end(),
|
||||
[](const aco_ptr<Instruction>& instr) -> bool
|
||||
{ return instr->opcode == aco_opcode::p_logical_end; });
|
||||
bld.reset(&then_block.instructions, before_logical_end);
|
||||
|
||||
Operand new_op;
|
||||
|
||||
if (then_op.constantEquals(-1)) {
|
||||
new_op =
|
||||
bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(s1, scc), else_op, Operand(exec, bld.lm));
|
||||
} else if (then_op.constantEquals(0)) {
|
||||
new_op = bld.sop2(Builder::s_andn2, bld.def(bld.lm), bld.def(s1, scc), else_op,
|
||||
Operand(exec, bld.lm));
|
||||
} else {
|
||||
new_op = bld.sop2(Builder::s_andn2, bld.def(bld.lm), bld.def(s1, scc), else_op,
|
||||
Operand(exec, bld.lm));
|
||||
then_op = bld.sop2(Builder::s_and, bld.def(bld.lm), bld.def(s1, scc), then_op,
|
||||
Operand(exec, bld.lm));
|
||||
new_op = bld.sop2(Builder::s_or, bld.def(bld.lm), bld.def(s1, scc), then_op, new_op);
|
||||
}
|
||||
|
||||
/* Insert new linear phi in the invert block, make merge block phi trivial to not invalidate
|
||||
* iterators. */
|
||||
bld.reset(&invert_block.instructions, invert_block.instructions.begin());
|
||||
Temp tmp = bld.pseudo(aco_opcode::p_linear_phi, bld.def(bld.lm), new_op, else_op);
|
||||
|
||||
phi->opcode = aco_opcode::p_linear_phi;
|
||||
phi->operands[0] = Operand(tmp);
|
||||
phi->operands[1] = Operand(tmp);
|
||||
}
|
||||
|
||||
void
|
||||
init_state(Program* program, Block* block, ssa_state* state, aco_ptr<Instruction>& phi)
|
||||
{
|
||||
|
|
@ -337,9 +391,18 @@ lower_phi_to_linear(Program* program, ssa_state* state, Block* block, aco_ptr<In
|
|||
}
|
||||
|
||||
if ((block->kind & block_kind_merge) && phi->opcode == aco_opcode::p_boolean_phi &&
|
||||
phi->operands.size() == 2 && phi->operands[1].isConstant()) {
|
||||
build_const_else_merge_code(program, program->blocks[block->linear_idom], phi);
|
||||
return;
|
||||
phi->operands.size() == 2) {
|
||||
Block& invert_block = program->blocks[block->linear_idom];
|
||||
Block& els_block = program->blocks[block->logical_preds[1]];
|
||||
assert(invert_block.kind & block_kind_invert);
|
||||
if (phi->operands[1].isConstant()) {
|
||||
build_const_else_merge_code(program, invert_block, phi);
|
||||
return;
|
||||
} else if (phi->operands[1].isTemp() && block_is_empty(els_block) &&
|
||||
els_block.linear_preds[0] == invert_block.index) {
|
||||
build_empty_else_merge_code(program, *block, invert_block, phi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
init_state(program, block, state, phi);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue