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