From 67a6fc01607fa9ccb16108424cde5dc598fc005a Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 22 Oct 2025 13:45:20 -0700 Subject: [PATCH] nir/opt_if: See through inot Consider if (!x) { if (x) { ... } } The inner use of `x` must be false, but so far only instances of `!x` would have been replaced with a constant. See through the `inot` to replace instances of `x` as well. shader-db: Lunar Lake total instructions in shared programs: 17205147 -> 17204908 (<.01%) instructions in affected programs: 56037 -> 55798 (-0.43%) helped: 79 / HURT: 79 total cycles in shared programs: 879847886 -> 879992944 (0.02%) cycles in affected programs: 5244138 -> 5389196 (2.77%) helped: 141 / HURT: 125 Meteor Lake, DG2, and Tiger Lake had similar results. (Meteor Lake shown) total instructions in shared programs: 19968312 -> 19968069 (<.01%) instructions in affected programs: 65698 -> 65455 (-0.37%) helped: 88 / HURT: 104 total cycles in shared programs: 884331007 -> 884469865 (0.02%) cycles in affected programs: 4839695 -> 4978553 (2.87%) helped: 172 / HURT: 136 LOST: 3 GAINED: 0 Ice Lake, Skylake, and Broadwell had similar results. (Ice Lake shown) total instructions in shared programs: 20809765 -> 20809473 (<.01%) instructions in affected programs: 65976 -> 65684 (-0.44%) helped: 89 / HURT: 102 total cycles in shared programs: 872466849 -> 872433762 (<.01%) cycles in affected programs: 5452888 -> 5419801 (-0.61%) helped: 157 / HURT: 133 total spills in shared programs: 4014 -> 4010 (-0.10%) spills in affected programs: 30 -> 26 (-13.33%) helped: 1 / HURT: 0 total fills in shared programs: 3769 -> 3765 (-0.11%) fills in affected programs: 50 -> 46 (-8.00%) helped: 1 / HURT: 0 LOST: 3 GAINED: 1 fossil-db: All Intel platforms had similar results. (Lunar Lake shown) Totals: Instrs: 910122459 -> 910097570 (-0.00%); split: -0.00%, +0.00% Subgroup size: 40045664 -> 40046176 (+0.00%) Send messages: 40724361 -> 40724036 (-0.00%) Loop count: 970500 -> 970054 (-0.05%) Cycle count: 105785543442 -> 105794147978 (+0.01%); split: -0.02%, +0.02% Spill count: 3426093 -> 3426032 (-0.00%); split: -0.00%, +0.00% Fill count: 6525296 -> 6525210 (-0.00%); split: -0.00%, +0.00% Max live registers: 188561553 -> 188519064 (-0.02%); split: -0.02%, +0.00% Max dispatch width: 47958304 -> 47958496 (+0.00%); split: +0.00%, -0.00% Non SSA regs after NIR: 227303232 -> 227296055 (-0.00%); split: -0.00%, +0.00% Totals from 15417 (0.78% of 1977988) affected shaders: Instrs: 16984488 -> 16959599 (-0.15%); split: -0.20%, +0.05% Subgroup size: 512 -> 1024 (+100.00%) Send messages: 900193 -> 899868 (-0.04%) Loop count: 23059 -> 22613 (-1.93%) Cycle count: 1200149390 -> 1208753926 (+0.72%); split: -1.48%, +2.20% Spill count: 25838 -> 25777 (-0.24%); split: -0.29%, +0.06% Fill count: 43627 -> 43541 (-0.20%); split: -0.28%, +0.08% Max live registers: 2550741 -> 2508252 (-1.67%); split: -1.75%, +0.08% Max dispatch width: 296736 -> 296928 (+0.06%); split: +0.08%, -0.02% Non SSA regs after NIR: 3264670 -> 3257493 (-0.22%); split: -0.25%, +0.03% Reviewed-by: Rhys Perry Part-of: --- src/compiler/nir/nir_opt_if.c | 44 +++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c index 8d703bcdfd8..f2b0e7e9e88 100644 --- a/src/compiler/nir/nir_opt_if.c +++ b/src/compiler/nir/nir_opt_if.c @@ -835,14 +835,14 @@ opt_if_phi_is_condition(nir_builder *b, nir_if *nif) } static bool -evaluate_if_condition(nir_if *nif, nir_cursor cursor, bool *value) +evaluate_if_condition(nir_if *nif, nir_cursor cursor, bool *value, bool invert) { nir_block *use_block = nir_cursor_current_block(cursor); if (nir_block_dominates(nir_if_first_then_block(nif), use_block)) { - *value = true; + *value = !invert; return true; } else if (nir_block_dominates(nir_if_first_else_block(nif), use_block)) { - *value = false; + *value = invert; return true; } else { return false; @@ -922,11 +922,11 @@ clone_alu_and_replace_src_defs(nir_builder *b, const nir_alu_instr *alu, */ static bool propagate_condition_eval(nir_builder *b, nir_if *nif, nir_src *use_src, - nir_src *alu_use, nir_alu_instr *alu) + nir_src *alu_use, nir_alu_instr *alu, bool invert) { bool bool_value; b->cursor = nir_before_src(alu_use); - if (!evaluate_if_condition(nif, b->cursor, &bool_value)) + if (!evaluate_if_condition(nif, b->cursor, &bool_value, invert)) return false; nir_def *def[NIR_MAX_VEC_COMPONENTS] = { 0 }; @@ -965,14 +965,15 @@ can_propagate_through_alu(nir_src *src) } static bool -evaluate_condition_use(nir_builder *b, nir_if *nif, nir_src *use_src) +evaluate_condition_use(nir_builder *b, nir_if *nif, nir_src *use_src, + bool invert) { bool progress = false; b->cursor = nir_before_src(use_src); bool bool_value; - if (evaluate_if_condition(nif, b->cursor, &bool_value)) { + if (evaluate_if_condition(nif, b->cursor, &bool_value, invert)) { /* Rewrite use to use const */ nir_src_rewrite(use_src, nir_imm_bool(b, bool_value)); progress = true; @@ -981,8 +982,10 @@ evaluate_condition_use(nir_builder *b, nir_if *nif, nir_src *use_src) if (!nir_src_is_if(use_src) && can_propagate_through_alu(use_src)) { nir_alu_instr *alu = nir_instr_as_alu(nir_src_parent_instr(use_src)); - nir_foreach_use_including_if_safe(alu_use, &alu->def) - progress |= propagate_condition_eval(b, nif, use_src, alu_use, alu); + nir_foreach_use_including_if_safe(alu_use, &alu->def) { + progress |= propagate_condition_eval(b, nif, use_src, alu_use, alu, + invert); + } } return progress; @@ -996,7 +999,28 @@ opt_if_evaluate_condition_use(nir_builder *b, nir_if *nif) /* Evaluate any uses of the if condition inside the if branches */ nir_foreach_use_including_if_safe(use_src, nif->condition.ssa) { if (!(nir_src_is_if(use_src) && nir_src_parent_if(use_src) == nif)) - progress |= evaluate_condition_use(b, nif, use_src); + progress |= evaluate_condition_use(b, nif, use_src, false); + } + + nir_alu_instr *alu = nir_src_as_alu_instr(nif->condition); + if (alu != NULL && alu->op == nir_op_inot && + nir_src_num_components(alu->src[0].src) == 1) { + /* Consider + * + * if (!x) { + * if (x) { + * ... + * } + * } + * + * The inner use of x must be false, but so far only instances of !x + * would have been replaced with a constant. See through the inot to + * replace instances of x as well. + */ + nir_foreach_use_including_if_safe(use_src, alu->src[0].src.ssa) { + if (nir_src_is_if(use_src) || nir_src_parent_instr(use_src) != &alu->instr) + progress |= evaluate_condition_use(b, nif, use_src, true); + } } return progress;