[Mesa-dev] [PATCH 1/2] nir: update nir_lower_returns to only predicate instructions when needed
Timothy Arceri
timothy.arceri at collabora.com
Fri Dec 9 07:16:59 UTC 2016
On Fri, 2016-12-09 at 16:49 +1100, Timothy Arceri wrote:
> Unless an if statement contains nested returns we can simply add
> any following instructions to the branch without the return.
> ---
> src/compiler/nir/nir_lower_returns.c | 36
> ++++++++++++++++++++++++++++++------
> 1 file changed, 30 insertions(+), 6 deletions(-)
>
> diff --git a/src/compiler/nir/nir_lower_returns.c
> b/src/compiler/nir/nir_lower_returns.c
> index 8dbea6e..73782a1 100644
> --- a/src/compiler/nir/nir_lower_returns.c
> +++ b/src/compiler/nir/nir_lower_returns.c
> @@ -30,6 +30,8 @@ struct lower_returns_state {
> struct exec_list *cf_list;
> nir_loop *loop;
> nir_variable *return_flag;
> + /* Are there other return statments nested in the current if */
> + bool if_nested_return;
> };
>
> static bool lower_returns_in_cf_list(struct exec_list *cf_list,
> @@ -82,8 +84,10 @@ lower_returns_in_loop(nir_loop *loop, struct
> lower_returns_state *state)
> * flag set to true. We need to predicate everything following
> the loop
> * on the return flag.
> */
> - if (progress)
> + if (progress) {
> predicate_following(&loop->cf_node, state);
> + state->if_nested_return = true;
> + }
>
> return progress;
> }
> @@ -91,10 +95,12 @@ lower_returns_in_loop(nir_loop *loop, struct
> lower_returns_state *state)
> static bool
> lower_returns_in_if(nir_if *if_stmt, struct lower_returns_state
> *state)
> {
> - bool progress;
> + bool progress, then_progress;
>
> - progress = lower_returns_in_cf_list(&if_stmt->then_list, state);
> - progress = lower_returns_in_cf_list(&if_stmt->else_list, state)
> || progress;
> + state->if_nested_return = false;
> +
> + then_progress = lower_returns_in_cf_list(&if_stmt->then_list,
> state);
> + progress = lower_returns_in_cf_list(&if_stmt->else_list, state)
> || then_progress;
>
> /* If either of the recursive calls made progress, then there
> were
> * returns inside of the body of the if. If we're in a loop,
> then these
> @@ -106,8 +112,26 @@ lower_returns_in_if(nir_if *if_stmt, struct
> lower_returns_state *state)
> * after a return, we need to predicate everything following on
> the
> * return flag.
> */
> - if (progress && !state->loop)
> - predicate_following(&if_stmt->cf_node, state);
> + if (progress && !state->loop) {
> + if (state->if_nested_return) {
> + predicate_following(&if_stmt->cf_node, state);
> + } else {
> + /* If there are no nested returns we can just add the
> instructions to
> + * the end of the branch that doesn't have the return.
> + */
> + nir_cf_list list;
> + nir_cf_extract(&list, nir_after_cf_node(&if_stmt->cf_node),
> + nir_after_cf_list(state->cf_list));
> + assert(!exec_list_is_empty(&list.list));
I've removed this assert() locally there is no need to assert if the
list is empty nir_cf_reinsert() will simply return is thats the case.
> + if (then_progress)
> + nir_cf_reinsert(&list, nir_after_cf_list(&if_stmt-
> >else_list));
> + else
> + nir_cf_reinsert(&list, nir_after_cf_list(&if_stmt-
> >then_list));
> + }
> + }
> +
> + if (progress)
> + state->if_nested_return = true;
>
> return progress;
> }
More information about the mesa-dev
mailing list