nir/opt_if: optimize phis between similar IFs

This small optimization targets phis between two IF statements with
the same condition. If the phi dst is only used on one branch leg,
the 'unused' phi source gets replaced with undef.

Totals from 1773 (2.23% of 79395) affected shaders: (Navi31)
Instrs: 6546338 -> 6539039 (-0.11%); split: -0.11%, +0.00%
CodeSize: 34819124 -> 34780660 (-0.11%); split: -0.11%, +0.00%
VGPRs: 92100 -> 92052 (-0.05%); split: -0.07%, +0.01%
SpillVGPRs: 2211 -> 2206 (-0.23%)
Latency: 51621404 -> 51620966 (-0.00%); split: -0.03%, +0.03%
InvThroughput: 7907110 -> 7905382 (-0.02%); split: -0.05%, +0.03%
VClause: 159268 -> 159273 (+0.00%); split: -0.00%, +0.01%
SClause: 180166 -> 180155 (-0.01%)
Copies: 559867 -> 553966 (-1.05%); split: -1.07%, +0.01%
Branches: 237327 -> 236366 (-0.40%); split: -0.41%, +0.00%
PreSGPRs: 81128 -> 81116 (-0.01%); split: -0.02%, +0.01%
PreVGPRs: 74264 -> 74245 (-0.03%)
VALU: 3547408 -> 3541257 (-0.17%); split: -0.18%, +0.00%
SALU: 824426 -> 824104 (-0.04%); split: -0.04%, +0.00%
VMEM: 265009 -> 265003 (-0.00%)
SMEM: 235766 -> 235760 (-0.00%)
VOPD: 1853 -> 1839 (-0.76%)

Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7710>
This commit is contained in:
Daniel Schürmann 2020-11-19 11:06:39 +01:00 committed by Marge Bot
parent 50d416fe89
commit 37881801c1

View file

@ -1123,6 +1123,69 @@ simple_merge_if(nir_if *dest_if, nir_if *src_if, bool dest_if_then,
nir_cf_reinsert(&if_cf_list, nir_after_block(dest_blk));
}
static bool
opt_phi_src_unused(nir_builder *b, nir_phi_instr *phi,
nir_if *prev_if, nir_if *next_if)
{
/* Return early, if either of the sources is already undef. */
nir_foreach_phi_src(phi_src, phi) {
if (phi_src->src.ssa->parent_instr->type == nir_instr_type_undef)
return false;
}
nir_block *first_then = nir_if_first_then_block(next_if);
nir_block *first_else = nir_if_first_else_block(next_if);
bool then_used = false;
bool else_used = false;
nir_foreach_use_including_if(use, &phi->def) {
nir_block *use_block = nir_src_get_block(use);
/* Check whether the if_use is on the then- or else- side. */
if (nir_block_dominates(first_then, use_block))
then_used = true;
else if (nir_block_dominates(first_else, use_block))
else_used = true;
else
return false;
if (then_used && else_used)
return false;
}
nir_block *unused_blk = then_used ? nir_if_last_else_block(prev_if)
: nir_if_last_then_block(prev_if);
nir_src *unused_src = &nir_phi_get_src_from_block(phi, unused_blk)->src;
/* Create undef and replace phi-src. */
b->cursor = nir_before_cf_node(&prev_if->cf_node);
nir_def *undef = nir_undef(b, phi->def.num_components, phi->def.bit_size);
nir_src_rewrite(unused_src, undef);
return true;
}
/*
* This small optimization targets phis between two IF statements with
* the same condition. If the phi dst is only used in one branch leg,
* the 'unused' phi source gets replaced with undef.
*/
static bool
opt_if_phi_src_unused(nir_builder *b, nir_if *nif)
{
bool progress = false;
nir_block *next_blk = nir_cf_node_cf_tree_next(&nif->cf_node);
nir_if *next_if = nir_block_get_following_if(next_blk);
if (!next_if || !nir_srcs_equal(nif->condition, next_if->condition))
return false;
nir_foreach_phi(phi, next_blk) {
progress |= opt_phi_src_unused(b, phi, nif, next_if);
}
return progress;
}
static bool
opt_if_merge(nir_if *nif)
{
@ -1304,6 +1367,7 @@ opt_if_safe_cf_list(nir_builder *b, struct exec_list *cf_list, nir_opt_if_option
progress |= opt_if_evaluate_condition_use(b, nif);
nir_scalar cond = nir_scalar_resolved(nif->condition.ssa, 0);
progress |= opt_if_rewrite_uniform_uses(b, nif, cond, true);
progress |= opt_if_phi_src_unused(b, nif);
break;
}