Module: Mesa Branch: main Commit: 312510448f25ec89028bd116b53b4133a6218c21 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=312510448f25ec89028bd116b53b4133a6218c21
Author: Daniel Schürmann <[email protected]> Date: Thu Dec 2 12:26:02 2021 +0100 nir: create nir_push_continue() and related helpers nir_control_flow.h: void nir_loop_add_continue_construct(nir_loop *loop); void nir_loop_remove_continue_construct(nir_loop *loop); Reviewed-by: Faith Ekstrand <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13962> --- src/compiler/nir/nir_builder.c | 16 ++++++++++++++++ src/compiler/nir/nir_builder.h | 3 +++ src/compiler/nir/nir_control_flow.c | 38 +++++++++++++++++++++++++++++++++++++ src/compiler/nir/nir_control_flow.h | 4 ++++ 4 files changed, 61 insertions(+) diff --git a/src/compiler/nir/nir_builder.c b/src/compiler/nir/nir_builder.c index 711208e5936..8a25316d65b 100644 --- a/src/compiler/nir/nir_builder.c +++ b/src/compiler/nir/nir_builder.c @@ -499,6 +499,22 @@ nir_push_loop(nir_builder *build) return loop; } +nir_loop * +nir_push_continue(nir_builder *build, nir_loop *loop) +{ + if (loop) { + assert(nir_builder_is_inside_cf(build, &loop->cf_node)); + } else { + nir_block *block = nir_cursor_current_block(build->cursor); + loop = nir_cf_node_as_loop(block->cf_node.parent); + } + + nir_loop_add_continue_construct(loop); + + build->cursor = nir_before_cf_list(&loop->continue_list); + return loop; +} + void nir_pop_loop(nir_builder *build, nir_loop *loop) { diff --git a/src/compiler/nir/nir_builder.h b/src/compiler/nir/nir_builder.h index 1972f125dae..d92583fb18d 100644 --- a/src/compiler/nir/nir_builder.h +++ b/src/compiler/nir/nir_builder.h @@ -159,6 +159,9 @@ nir_if_phi(nir_builder *build, nir_ssa_def *then_def, nir_ssa_def *else_def); nir_loop * nir_push_loop(nir_builder *build); +nir_loop * +nir_push_continue(nir_builder *build, nir_loop *loop); + void nir_pop_loop(nir_builder *build, nir_loop *loop); static inline nir_ssa_def * diff --git a/src/compiler/nir/nir_control_flow.c b/src/compiler/nir/nir_control_flow.c index 43d02f2e176..8a93435ef30 100644 --- a/src/compiler/nir/nir_control_flow.c +++ b/src/compiler/nir/nir_control_flow.c @@ -435,6 +435,44 @@ nearest_loop(nir_cf_node *node) return nir_cf_node_as_loop(node); } +void +nir_loop_add_continue_construct(nir_loop *loop) +{ + assert(!nir_loop_has_continue_construct(loop)); + + nir_block *cont = nir_block_create(ralloc_parent(loop)); + exec_list_push_tail(&loop->continue_list, &cont->cf_node.node); + cont->cf_node.parent = &loop->cf_node; + + /* change predecessors and successors */ + nir_block *header = nir_loop_first_block(loop); + nir_block *preheader = nir_block_cf_tree_prev(header); + set_foreach(header->predecessors, entry) { + nir_block *pred = (nir_block *) entry->key; + if (pred != preheader) + replace_successor(pred, header, cont); + } + + link_blocks(cont, header, NULL); +} + +void +nir_loop_remove_continue_construct(nir_loop *loop) +{ + assert(nir_cf_list_is_empty_block(&loop->continue_list)); + + /* change predecessors and successors */ + nir_block *header = nir_loop_first_block(loop); + nir_block *cont = nir_loop_first_continue_block(loop); + set_foreach(cont->predecessors, entry) { + nir_block *pred = (nir_block*) entry->key; + replace_successor(pred, cont, header); + } + block_remove_pred(header, cont); + + exec_node_remove(&cont->cf_node.node); +} + static void remove_phi_src(nir_block *block, nir_block *pred) { diff --git a/src/compiler/nir/nir_control_flow.h b/src/compiler/nir/nir_control_flow.h index 34e79b7ad80..e31cd8e732d 100644 --- a/src/compiler/nir/nir_control_flow.h +++ b/src/compiler/nir/nir_control_flow.h @@ -175,6 +175,10 @@ nir_cf_node_remove(nir_cf_node *node) /** inserts undef phi sources from predcessor into phis of the block */ void nir_insert_phi_undef(nir_block *block, nir_block *pred); +/** Modify loop continue behavior */ +void nir_loop_add_continue_construct(nir_loop *loop); +void nir_loop_remove_continue_construct(nir_loop *loop); + #ifdef __cplusplus } #endif
