summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/nir/nir_opt_if.c119
1 files changed, 59 insertions, 60 deletions
diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c
index d507ceef275..4283d445912 100644
--- a/src/compiler/nir/nir_opt_if.c
+++ b/src/compiler/nir/nir_opt_if.c
@@ -1230,77 +1230,76 @@ opt_if_merge(nir_if *nif)
bool progress = false;
nir_block *next_blk = nir_cf_node_cf_tree_next(&nif->cf_node);
- if (next_blk && nif->condition.is_ssa) {
- nir_if *next_if = nir_block_get_following_if(next_blk);
- if (next_if && next_if->condition.is_ssa) {
-
- /* Here we merge two consecutive ifs that have the same
- * condition e.g:
- *
- * 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)) {
+ if (!next_blk || !nif->condition.is_ssa)
+ return false;
- /* This optimization isn't made to work in this case and
- * 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_if *next_if = nir_block_get_following_if(next_blk);
+ if (!next_if || !next_if->condition.is_ssa)
+ return false;
- simple_merge_if(nif, next_if, true, true);
- simple_merge_if(nif, next_if, false, false);
+ /* Here we merge two consecutive ifs that have the same condition e.g:
+ *
+ * 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 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)) {
- nir_block *new_then_block = nir_if_last_then_block(nif);
- nir_block *new_else_block = nir_if_last_else_block(nif);
+ /* This optimization isn't made to work in this case and
+ * 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 *old_then_block = nir_if_last_then_block(next_if);
- nir_block *old_else_block = nir_if_last_else_block(next_if);
+ simple_merge_if(nif, next_if, true, true);
+ simple_merge_if(nif, next_if, false, false);
- /* Rewrite the predecessor block for any phis following the second
- * if-statement.
- */
- rewrite_phi_predecessor_blocks(next_if, old_then_block,
- old_else_block,
- new_then_block,
- new_else_block);
+ nir_block *new_then_block = nir_if_last_then_block(nif);
+ nir_block *new_else_block = nir_if_last_else_block(nif);
- /* Move phis after merged if to avoid them being deleted when we
- * remove the merged if-statement.
- */
- nir_block *after_next_if_block =
- nir_cf_node_as_block(nir_cf_node_next(&next_if->cf_node));
+ nir_block *old_then_block = nir_if_last_then_block(next_if);
+ nir_block *old_else_block = nir_if_last_else_block(next_if);
- nir_foreach_instr_safe(instr, after_next_if_block) {
- if (instr->type != nir_instr_type_phi)
- break;
+ /* Rewrite the predecessor block for any phis following the second
+ * if-statement.
+ */
+ rewrite_phi_predecessor_blocks(next_if, old_then_block,
+ old_else_block,
+ new_then_block,
+ new_else_block);
- exec_node_remove(&instr->node);
- exec_list_push_tail(&next_blk->instr_list, &instr->node);
- instr->block = next_blk;
- }
+ /* Move phis after merged if to avoid them being deleted when we remove
+ * the merged if-statement.
+ */
+ nir_block *after_next_if_block =
+ nir_cf_node_as_block(nir_cf_node_next(&next_if->cf_node));
- nir_cf_node_remove(&next_if->cf_node);
+ nir_foreach_instr_safe(instr, after_next_if_block) {
+ if (instr->type != nir_instr_type_phi)
+ break;
- progress = true;
- }
+ exec_node_remove(&instr->node);
+ exec_list_push_tail(&next_blk->instr_list, &instr->node);
+ instr->block = next_blk;
}
+
+ nir_cf_node_remove(&next_if->cf_node);
+
+ progress = true;
}
return progress;