nir/opt_if: Merge if-statements with inverted conditions

Cases like

    if (x) {
        ...
    } else {
        ...
    }
    if (!x) {
        ...
    } else {
        ...
    }

should be merged.

I don't know why Ice Lake is affected differetly by this commit.

v2: Add implementation of srcs_equal_or_logical_inverse after bad
rebase. That's what I get for rushing out an MR right before lunch.
Noticed by Georg.

shader-db:

Lunar Lake
No changes.

All other Iris platforms had simlar results. (Meteor Lake shown)
total cycles in shared programs: 882310108 -> 882311504 (<.01%)
cycles in affected programs: 74306 -> 75702 (1.88%)
helped: 4
HURT: 2
helped stats (abs) min: 2.0 max: 38.0 x̄: 11.00 x̃: 2
helped stats (rel) min: 0.02% max: 0.29% x̄: 0.09% x̃: 0.02%
HURT stats (abs)   min: 720.0 max: 720.0 x̄: 720.00 x̃: 720
HURT stats (rel)   min: 5.27% max: 5.27% x̄: 5.27% x̃: 5.27%
95% mean confidence interval for cycles value: -163.75 629.08
95% mean confidence interval for cycles %-change: -1.21% 4.61%
Inconclusive result (value mean confidence interval includes 0).

fossil-db:

All Intel platforms except Ice Lake had similar results. (Lunar Lake shown)
Totals:
Instrs: 914554534 -> 914546744 (-0.00%); split: -0.00%, +0.00%
CodeSize: 12887129264 -> 12886823808 (-0.00%); split: -0.00%, +0.00%
Send messages: 40220826 -> 40219429 (-0.00%); split: -0.00%, +0.00%
Cycle count: 100101810976 -> 100101804762 (-0.00%); split: -0.00%, +0.00%
Spill count: 3459811 -> 3459786 (-0.00%); split: -0.00%, +0.00%
Fill count: 4909877 -> 4909835 (-0.00%); split: -0.00%, +0.00%
Max live registers: 191837229 -> 191838000 (+0.00%); split: -0.00%, +0.00%
Max dispatch width: 48514400 -> 48514336 (-0.00%)
Non SSA regs after NIR: 136346777 -> 136343948 (-0.00%); split: -0.00%, +0.00%

Totals from 1937 (0.10% of 2003486) affected shaders:
Instrs: 3013550 -> 3005760 (-0.26%); split: -0.39%, +0.13%
CodeSize: 43169072 -> 42863616 (-0.71%); split: -0.81%, +0.10%
Send messages: 183171 -> 181774 (-0.76%); split: -0.82%, +0.06%
Cycle count: 126864798 -> 126858584 (-0.00%); split: -0.67%, +0.67%
Spill count: 7354 -> 7329 (-0.34%); split: -0.45%, +0.11%
Fill count: 5547 -> 5505 (-0.76%); split: -0.88%, +0.13%
Max live registers: 296895 -> 297666 (+0.26%); split: -0.04%, +0.30%
Max dispatch width: 41856 -> 41792 (-0.15%)
Non SSA regs after NIR: 545672 -> 542843 (-0.52%); split: -1.15%, +0.63%

Ice Lake
Totals:
Instrs: 996341606 -> 996312120 (-0.00%); split: -0.00%, +0.00%
CodeSize: 12563695936 -> 12563195200 (-0.00%); split: -0.00%, +0.00%
Send messages: 45911343 -> 45909063 (-0.00%); split: -0.00%, +0.00%
Cycle count: 82819362995 -> 82818778468 (-0.00%); split: -0.00%, +0.00%
Spill count: 2935451 -> 2935452 (+0.00%); split: -0.00%, +0.00%
Fill count: 5034267 -> 5034281 (+0.00%); split: -0.00%, +0.00%
Max live registers: 124672355 -> 124672961 (+0.00%); split: -0.00%, +0.00%
Max dispatch width: 41330808 -> 41330672 (-0.00%)
Non SSA regs after NIR: 160790466 -> 160785863 (-0.00%); split: -0.01%, +0.00%

Totals from 2163 (0.09% of 2327905) affected shaders:
Instrs: 4164788 -> 4135302 (-0.71%); split: -0.80%, +0.09%
CodeSize: 53351344 -> 52850608 (-0.94%); split: -0.95%, +0.01%
Send messages: 271164 -> 268884 (-0.84%); split: -0.84%, +0.00%
Cycle count: 145818114 -> 145233587 (-0.40%); split: -0.66%, +0.26%
Spill count: 7819 -> 7820 (+0.01%); split: -0.32%, +0.33%
Fill count: 7191 -> 7205 (+0.19%); split: -0.57%, +0.76%
Max live registers: 192403 -> 193009 (+0.31%); split: -0.08%, +0.40%
Max dispatch width: 34728 -> 34592 (-0.39%)
Non SSA regs after NIR: 570874 -> 566271 (-0.81%); split: -1.49%, +0.68%

Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41871>
This commit is contained in:
Ian Romanick 2026-05-15 16:00:51 -07:00 committed by Marge Bot
parent e8cef4725d
commit daa38c1972

View file

@ -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.
*/