[Mesa-dev] [PATCH 03/10] nir: allow more nested loops to be unrolled
Jason Ekstrand
jason at jlekstrand.net
Sun Jul 22 09:32:34 UTC 2018
On Tue, Jul 10, 2018 at 11:49 PM Timothy Arceri <tarceri at itsqueeze.com>
wrote:
> The innermost check was added to stop us from unrolling multiple
> loops in a single pass, and to stop outer loops from unrolling.
>
Do you mean "multiple nested loops in a single pass..."?
> When we successfully unroll a loop we need to run the analysis
> pass again before deciding if we want to go ahead an unroll a
> second loop.
>
"unroll its parent loop" or perhaps "unroll a loop containing it"?
> However the logic was flawed because it never tried to unroll any
> nested loops other than the first innermost loop it found.
> If this innermost loop is not unrolled we end up skipping all
> other nested loops.
>
> No change to shader-db. Unrolls a loop in a shader from the game
> Prey when running on DXVK.
> ---
> src/compiler/nir/nir_opt_loop_unroll.c | 31 ++++++++++++++------------
> 1 file changed, 17 insertions(+), 14 deletions(-)
>
> diff --git a/src/compiler/nir/nir_opt_loop_unroll.c
> b/src/compiler/nir/nir_opt_loop_unroll.c
> index 955dfede694..f31f84bee76 100644
> --- a/src/compiler/nir/nir_opt_loop_unroll.c
> +++ b/src/compiler/nir/nir_opt_loop_unroll.c
> @@ -483,7 +483,7 @@ is_loop_small_enough_to_unroll(nir_shader *shader,
> nir_loop_info *li)
> }
>
> static bool
> -process_loops(nir_shader *sh, nir_cf_node *cf_node, bool *innermost_loop)
> +process_loops(nir_shader *sh, nir_cf_node *cf_node, bool *has_nested_loop)
> {
> bool progress = false;
> nir_loop *loop;
> @@ -494,32 +494,33 @@ process_loops(nir_shader *sh, nir_cf_node *cf_node,
> bool *innermost_loop)
> case nir_cf_node_if: {
> nir_if *if_stmt = nir_cf_node_as_if(cf_node);
> foreach_list_typed_safe(nir_cf_node, nested_node, node,
> &if_stmt->then_list)
> - progress |= process_loops(sh, nested_node, innermost_loop);
> + progress |= process_loops(sh, nested_node, has_nested_loop);
> foreach_list_typed_safe(nir_cf_node, nested_node, node,
> &if_stmt->else_list)
> - progress |= process_loops(sh, nested_node, innermost_loop);
> + progress |= process_loops(sh, nested_node, has_nested_loop);
> return progress;
> }
> case nir_cf_node_loop: {
> + *has_nested_loop = false;
>
If I'm understanding what you're trying to do correctly, I think this patch
is correct but the usage of the recursive boolean is driving me nuts. How
about we rename the function parameter to has_nested_loop_out and declare a
local variable has_nested_loop which we initialize to false. Then we would
pass the function parameter version straight through in the if case and, in
the loop case we would set *has_nested_loop_out = true and then pass the
local one into the recursive call. Would that make more sense? Recursion
is hard.
> loop = nir_cf_node_as_loop(cf_node);
> foreach_list_typed_safe(nir_cf_node, nested_node, node, &loop->body)
> - progress |= process_loops(sh, nested_node, innermost_loop);
> + progress |= process_loops(sh, nested_node, has_nested_loop);
> +
>
break;
> }
> default:
> unreachable("unknown cf node type");
> }
>
> - if (*innermost_loop) {
> - /* Don't attempt to unroll outer loops or a second inner loop in
> - * this pass wait until the next pass as we have altered the cf.
> - */
> - *innermost_loop = false;
> + /* Don't attempt to unroll a second inner loop in this pass, wait
> until the
> + * next pass as we have altered the cf.
> + */
> + if (!progress) {
>
> - if (loop->info->limiting_terminator == NULL)
> - return progress;
> + if (*has_nested_loop || loop->info->limiting_terminator == NULL)
> + goto exit;
>
> if (!is_loop_small_enough_to_unroll(sh, loop->info))
> - return progress;
> + goto exit;
>
> if (loop->info->is_trip_count_known) {
> simple_unroll(loop);
> @@ -555,6 +556,8 @@ process_loops(nir_shader *sh, nir_cf_node *cf_node,
> bool *innermost_loop)
> }
> }
>
> +exit:
> + *has_nested_loop = true;
> return progress;
> }
>
> @@ -567,9 +570,9 @@ nir_opt_loop_unroll_impl(nir_function_impl *impl,
> nir_metadata_require(impl, nir_metadata_block_index);
>
> foreach_list_typed_safe(nir_cf_node, node, node, &impl->body) {
> - bool innermost_loop = true;
> + bool has_nested_loop = false;
> progress |= process_loops(impl->function->shader, node,
> - &innermost_loop);
> + &has_nested_loop);
> }
>
> if (progress)
> --
> 2.17.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20180722/aa1ced19/attachment-0001.html>
More information about the mesa-dev
mailing list