nir/opt_if: Use early returns in opt_if_merge()

We would've had to add yet another level of indentation, or duplicated
finding the if conditions in the next commit. Refactor this function to
use early returns like our other optimizations, so that this isn't an
issue.

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6866>
This commit is contained in:
Connor Abbott
2019-04-16 19:39:11 +02:00
committed by Marge Bot
parent 656e428ff4
commit 7f0cd6f153

View File

@@ -1230,77 +1230,76 @@ opt_if_merge(nir_if *nif)
bool progress = false; bool progress = false;
nir_block *next_blk = nir_cf_node_cf_tree_next(&nif->cf_node); nir_block *next_blk = nir_cf_node_cf_tree_next(&nif->cf_node);
if (next_blk && nif->condition.is_ssa) { if (!next_blk || !nif->condition.is_ssa)
nir_if *next_if = nir_block_get_following_if(next_blk); return false;
if (next_if && next_if->condition.is_ssa) {
/* Here we merge two consecutive ifs that have the same nir_if *next_if = nir_block_get_following_if(next_blk);
* condition e.g: if (!next_if || !next_if->condition.is_ssa)
* return false;
* if ssa_12 {
* ...
* } else {
* ...
* }
* if ssa_12 {
* ...
* } else {
* ...
* }
*
* Note: This only merges if-statements when the block between them
* is empty. The reason we don't try to merge ifs that just have phis
* between them is because this can results in increased register
* pressure. For example when merging if ladders created by indirect
* indexing.
*/
if (nif->condition.ssa == next_if->condition.ssa &&
exec_list_is_empty(&next_blk->instr_list)) {
/* This optimization isn't made to work in this case and /* Here we merge two consecutive ifs that have the same condition e.g:
* opt_if_evaluate_condition_use will optimize it later. *
*/ * if ssa_12 {
if (nir_block_ends_in_jump(nir_if_last_then_block(nif)) || * ...
nir_block_ends_in_jump(nir_if_last_else_block(nif))) * } else {
return false; * ...
* }
* if ssa_12 {
* ...
* } else {
* ...
* }
*
* Note: This only merges if-statements when the block between them is
* empty. The reason we don't try to merge ifs that just have phis between
* them is because this can result in increased register pressure. For
* example when merging if ladders created by indirect indexing.
*/
if (nif->condition.ssa == next_if->condition.ssa &&
exec_list_is_empty(&next_blk->instr_list)) {
simple_merge_if(nif, next_if, true, true); /* This optimization isn't made to work in this case and
simple_merge_if(nif, next_if, false, false); * opt_if_evaluate_condition_use will optimize it later.
*/
if (nir_block_ends_in_jump(nir_if_last_then_block(nif)) ||
nir_block_ends_in_jump(nir_if_last_else_block(nif)))
return false;
nir_block *new_then_block = nir_if_last_then_block(nif); simple_merge_if(nif, next_if, true, true);
nir_block *new_else_block = nir_if_last_else_block(nif); simple_merge_if(nif, next_if, false, false);
nir_block *old_then_block = nir_if_last_then_block(next_if); nir_block *new_then_block = nir_if_last_then_block(nif);
nir_block *old_else_block = nir_if_last_else_block(next_if); nir_block *new_else_block = nir_if_last_else_block(nif);
/* Rewrite the predecessor block for any phis following the second nir_block *old_then_block = nir_if_last_then_block(next_if);
* if-statement. nir_block *old_else_block = nir_if_last_else_block(next_if);
*/
rewrite_phi_predecessor_blocks(next_if, old_then_block,
old_else_block,
new_then_block,
new_else_block);
/* Move phis after merged if to avoid them being deleted when we /* Rewrite the predecessor block for any phis following the second
* remove the merged if-statement. * if-statement.
*/ */
nir_block *after_next_if_block = rewrite_phi_predecessor_blocks(next_if, old_then_block,
nir_cf_node_as_block(nir_cf_node_next(&next_if->cf_node)); old_else_block,
new_then_block,
new_else_block);
nir_foreach_instr_safe(instr, after_next_if_block) { /* Move phis after merged if to avoid them being deleted when we remove
if (instr->type != nir_instr_type_phi) * the merged if-statement.
break; */
nir_block *after_next_if_block =
nir_cf_node_as_block(nir_cf_node_next(&next_if->cf_node));
exec_node_remove(&instr->node); nir_foreach_instr_safe(instr, after_next_if_block) {
exec_list_push_tail(&next_blk->instr_list, &instr->node); if (instr->type != nir_instr_type_phi)
instr->block = next_blk; break;
}
nir_cf_node_remove(&next_if->cf_node); exec_node_remove(&instr->node);
exec_list_push_tail(&next_blk->instr_list, &instr->node);
progress = true; instr->block = next_blk;
}
} }
nir_cf_node_remove(&next_if->cf_node);
progress = true;
} }
return progress; return progress;