From d1e36634bdf3178f8ae7290de14bb9122cebe550 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Mon, 18 Jul 2022 19:18:15 +1000 Subject: [PATCH] nir/loop_unroll: clean up after complex_unroll_single_terminator() Previously we would just unroll the loop one extra iteration and let other optimisation passes clean up the mess. This worked to a degree but if the loop happened to be nested inside another loop we would end up with phi chains that would block other passes from being able to do the cleanup. With this commit we explicitly clone the variables create by lcsaa and insert them directly in the last continue branch after we are done unrolling. With this optimisation passes can recognise both sides of the if output the same values and can progress further. Help with the issues described in: https://gitlab.freedesktop.org/mesa/mesa/-/issues/6051 Reviewed-by: Iago Toral Quiroga Part-of: --- src/compiler/nir/nir_opt_loop_unroll.c | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/compiler/nir/nir_opt_loop_unroll.c b/src/compiler/nir/nir_opt_loop_unroll.c index d101d74..095fd02 100644 --- a/src/compiler/nir/nir_opt_loop_unroll.c +++ b/src/compiler/nir/nir_opt_loop_unroll.c @@ -495,6 +495,41 @@ complex_unroll_single_terminator(nir_loop *loop) complex_unroll_loop_body(loop, terminator, &lp_header, &lp_body, remap_table, num_times_to_clone); + assert(unroll_loc->type == nir_cf_node_if); + + /* We need to clone the lcssa vars in order to insert them on both sides + * of the if in the last iteration/if-statement. Otherwise the optimisation + * passes will have trouble optimising the unrolled if ladder. + */ + nir_cursor cursor = + get_complex_unroll_insert_location(unroll_loc, + terminator->continue_from_then); + + nir_if *if_stmt = nir_cf_node_as_if(unroll_loc); + nir_cursor start_cursor; + nir_cursor end_cursor; + if (terminator->continue_from_then) { + start_cursor = nir_before_block(nir_if_first_else_block(if_stmt)); + end_cursor = nir_after_block(nir_if_last_else_block(if_stmt)); + } else { + start_cursor = nir_before_block(nir_if_first_then_block(if_stmt)); + end_cursor = nir_after_block(nir_if_last_then_block(if_stmt)); + } + + nir_cf_list lcssa_list; + nir_cf_extract(&lcssa_list, start_cursor, end_cursor); + + /* Insert the cloned vars in the last continue branch */ + nir_cf_list_clone_and_reinsert(&lcssa_list, loop->cf_node.parent, + cursor, remap_table); + + start_cursor = terminator->continue_from_then ? + nir_before_block(nir_if_first_else_block(if_stmt)) : + nir_before_block(nir_if_first_then_block(if_stmt)); + + /* Reinsert the cloned vars back where they came from */ + nir_cf_reinsert(&lcssa_list, start_cursor); + /* Delete the original loop header and body */ nir_cf_delete(&lp_header); nir_cf_delete(&lp_body); -- 2.7.4