nir/loop_analyze: determine whether all control flow gets eliminated upon loop unrolling

Totals from 17 (0.02% of 79839) affected shaders: (Navi48)

MaxWaves: 241 -> 243 (+0.83%); split: +5.81%, -4.98%
Instrs: 44198 -> 43786 (-0.93%); split: -8.19%, +7.26%
CodeSize: 230284 -> 226900 (-1.47%); split: -10.55%, +9.08%
VGPRs: 2152 -> 2524 (+17.29%); split: -3.90%, +21.19%
Scratch: 718848 -> 0 (-inf%)
Latency: 128977 -> 145720 (+12.98%); split: -2.12%, +15.10%
InvThroughput: 206804 -> 254250 (+22.94%); split: -0.32%, +23.27%
VClause: 1296 -> 1309 (+1.00%); split: -28.09%, +29.09%
SClause: 835 -> 833 (-0.24%)
Copies: 6284 -> 3630 (-42.23%); split: -44.51%, +2.28%
Branches: 1003 -> 961 (-4.19%)
PreSGPRs: 1003 -> 996 (-0.70%); split: -1.20%, +0.50%
PreVGPRs: 1510 -> 2130 (+41.06%)
VALU: 23577 -> 24309 (+3.10%); split: -6.26%, +9.37%
SALU: 5875 -> 5688 (-3.18%); split: -6.26%, +3.08%
VMEM: 3679 -> 3001 (-18.43%); split: -33.27%, +14.84%
SMEM: 1632 -> 1631 (-0.06%)
VOPD: 23 -> 24 (+4.35%)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38659>
This commit is contained in:
Daniel Schürmann 2025-11-25 11:35:25 +01:00 committed by Marge Bot
parent 4997d8fb1b
commit 598928d7e7
3 changed files with 17 additions and 0 deletions

View file

@ -3444,6 +3444,9 @@ typedef struct nir_loop_info {
/* Unroll the loop regardless of its size */
bool force_unroll;
/* Whether all control flow gets eliminated upon unrolling. */
bool flattens_all_control_flow;
/* Does the loop contain complex loop terminators, continues or other
* complex behaviours? If this is true we can't rely on
* loop_terminator_list to be complete or accurate.

View file

@ -1405,6 +1405,8 @@ gather_constant_fold_info(loop_info_state *state, nir_instr *instr)
static void
gather_unroll_heuristic_info(loop_info_state *state, const nir_shader_compiler_options *options)
{
state->loop->info->flattens_all_control_flow = state->loop->info->exact_trip_count_known;
nir_foreach_block_in_cf_node(block, &state->loop->cf_node) {
/* Calculate instruction cost. */
nir_foreach_instr(instr, block) {
@ -1412,6 +1414,15 @@ gather_unroll_heuristic_info(loop_info_state *state, const nir_shader_compiler_o
state->loop->info->instr_cost += instr_cost(state, instr, options);
}
nir_if *nif = nir_block_get_following_if(block);
if (nif) {
/* If all IF statements can be constant-folded after unrolling,
* the loop becomes a single large basic block.
*/
state->loop->info->flattens_all_control_flow &=
is_const_after_unrolling(state, nif->condition.ssa);
}
if (state->loop->info->force_unroll)
continue;

View file

@ -905,6 +905,9 @@ check_unrolling_restrictions(nir_shader *shader, nir_loop *loop)
/* Unroll much more aggressively if it can hide load latency. */
if (shader->options->max_unroll_iterations_aggressive && can_pipeline_loads(loop))
max_iter = shader->options->max_unroll_iterations_aggressive;
/* Unroll much more aggressively if all control flow gets eliminated. */
if (shader->options->max_unroll_iterations_aggressive && li->flattens_all_control_flow)
max_iter = shader->options->max_unroll_iterations_aggressive;
/* Tune differently if the loop has double ops and soft fp64 is in use */
else if (shader->options->max_unroll_iterations_fp64 && loop->info->has_soft_fp64)
max_iter = shader->options->max_unroll_iterations_fp64;