From 0f98ed4afe5f8131fc453dc91db1f4e73efd290c Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Mon, 9 May 2022 20:20:26 +1000 Subject: [PATCH] nir: remove unreachable loop terminators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the conditional break statements associated with all terminators that are associated with a fixed iteration count, except for the one associated with the limiting terminator. This logic matches similiar functionality that exists in the old GLSL IR unrolling code. This change helps a piglit test pass on the r300 driver once we switch off the old GLSL IR unrolling code. Shader-db results IRIS (BDW): total instructions in shared programs: 17538619 -> 17538595 (<.01%) instructions in affected programs: 216 -> 192 (-11.11%) helped: 3 HURT: 0 helped stats (abs) min: 7 max: 10 x̄: 8.00 x̃: 7 helped stats (rel) min: 10.00% max: 12.07% x̄: 11.38% x̃: 12.07% total cycles in shared programs: 858674910 -> 858672810 (<.01%) cycles in affected programs: 79540 -> 77440 (-2.64%) helped: 3 HURT: 0 helped stats (abs) min: 620 max: 800 x̄: 700.00 x̃: 680 helped stats (rel) min: 2.45% max: 2.83% x̄: 2.63% x̃: 2.62% Reviewed-by: Emma Anholt Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/nir/nir_opt_loop_unroll.c | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/compiler/nir/nir_opt_loop_unroll.c b/src/compiler/nir/nir_opt_loop_unroll.c index e81cebbb338..49c696dc514 100644 --- a/src/compiler/nir/nir_opt_loop_unroll.c +++ b/src/compiler/nir/nir_opt_loop_unroll.c @@ -946,6 +946,43 @@ process_loops(nir_shader *sh, nir_cf_node *cf_node, bool *has_nested_loop_out, */ if (!progress && loop->control != nir_loop_control_dont_unroll) { + /* Remove the conditional break statements associated with all terminators + * that are associated with a fixed iteration count, except for the one + * associated with the limiting terminator--that one needs to stay, since + * it terminates the loop. + */ + if (loop->info->limiting_terminator) { + list_for_each_entry_safe(nir_loop_terminator, t, + &loop->info->loop_terminator_list, + loop_terminator_link) { + if (t->exact_trip_count_unknown) + continue; + + if (t != loop->info->limiting_terminator) { + + /* Only delete the if-statement if the continue block is empty. + * We trust that nir_opt_if() does its job well enough to + * remove all instructions from the continue block when possible. + */ + nir_block *first_continue_from_blk = t->continue_from_then ? + nir_if_first_then_block(t->nif) : + nir_if_first_else_block(t->nif); + + if (!(nir_cf_node_is_last(&first_continue_from_blk->cf_node) && + exec_list_is_empty(&first_continue_from_blk->instr_list))) + continue; + + /* Now delete the if */ + nir_cf_node_remove(&t->nif->cf_node); + + /* Also remove it from the terminator list */ + list_del(&t->loop_terminator_link); + + progress = true; + } + } + } + /* Check for the classic * * do {