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; > } _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev