diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c index f44ce7149ce..15427fbddb8 100644 --- a/src/compiler/nir/nir_opt_if.c +++ b/src/compiler/nir/nir_opt_if.c @@ -1279,13 +1279,17 @@ opt_if_phi_src_unused(nir_builder *b, nir_if *nif) } static void -rewrite_phi_uses(nir_phi_instr *phi, nir_if *prev_if, nir_if *next_if) +rewrite_phi_uses(nir_phi_instr *phi, nir_if *prev_if, nir_if *next_if, + bool inverse) { nir_def *then_src = nir_phi_get_src_from_block(phi, nir_if_last_then_block(prev_if))->src.ssa; nir_def *else_src = nir_phi_get_src_from_block(phi, nir_if_last_else_block(prev_if))->src.ssa; + if (inverse) + SWAP(then_src, else_src); + /* Rewrite all uses inside the next IF with either then_src or else_src. */ nir_foreach_use_including_if_safe(use, &phi->def) { nir_cf_node *node = &nir_src_get_block(use)->cf_node; @@ -1313,6 +1317,30 @@ rewrite_phi_uses(nir_phi_instr *phi, nir_if *prev_if, nir_if *next_if) } } +static bool +srcs_equal_or_logical_inverse(nir_src src1, nir_src src2, bool *inverse) +{ + *inverse = false; + if (nir_srcs_equal(src1, src2)) + return true; + + nir_alu_instr *alu; + + alu = nir_src_as_alu(src1); + if (alu != NULL && alu->op == nir_op_inot) { + *inverse = nir_srcs_equal(alu->src[0].src, src2); + return *inverse; + } + + alu = nir_src_as_alu(src2); + if (alu != NULL && alu->op == nir_op_inot) { + *inverse = nir_srcs_equal(alu->src[0].src, src1); + return *inverse; + } + + return false; +} + static bool opt_if_merge(nir_if *nif) { @@ -1321,7 +1349,9 @@ opt_if_merge(nir_if *nif) return false; nir_if *next_if = nir_block_get_following_if(next_blk); - if (!next_if || !nir_srcs_equal(nif->condition, next_if->condition)) + bool inverse = false; + if (!next_if || !srcs_equal_or_logical_inverse(nif->condition, + next_if->condition, &inverse)) return false; /* This optimization isn't made to work in this case and @@ -1355,7 +1385,7 @@ opt_if_merge(nir_if *nif) * with the phi source from the respective branch leg of the * previous IF. */ - rewrite_phi_uses(phi, nif, next_if); + rewrite_phi_uses(phi, nif, next_if, inverse); } /* Here we merge two consecutive ifs that have the same condition e.g: @@ -1374,8 +1404,8 @@ opt_if_merge(nir_if *nif) * Note: This only merges if-statements when the block between them is * empty except for phis. */ - simple_merge_if(nif, next_if, true, true); - simple_merge_if(nif, next_if, false, false); + simple_merge_if(nif, next_if, true, !inverse); + simple_merge_if(nif, next_if, false, inverse); nir_block *new_then_block = nir_if_last_then_block(nif); nir_block *new_else_block = nir_if_last_else_block(nif); @@ -1383,6 +1413,9 @@ opt_if_merge(nir_if *nif) nir_block *old_then_block = nir_if_last_then_block(next_if); nir_block *old_else_block = nir_if_last_else_block(next_if); + if (inverse) + SWAP(new_then_block, new_else_block); + /* Rewrite the predecessor block for any phis following the second * if-statement. */