diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/glsl/nir/nir_control_flow.c | 197 | ||||
-rw-r--r-- | src/glsl/nir/nir_control_flow.h | 27 |
2 files changed, 49 insertions, 175 deletions
diff --git a/src/glsl/nir/nir_control_flow.c b/src/glsl/nir/nir_control_flow.c index 935ec9f2c47..ba39205ba29 100644 --- a/src/glsl/nir/nir_control_flow.c +++ b/src/glsl/nir/nir_control_flow.c @@ -455,20 +455,6 @@ insert_non_block(nir_block *before, nir_cf_node *node, nir_block *after) link_non_block_to_block(node, after); } -/** - * Inserts a non-basic block before a basic block. - */ - -static void -insert_non_block_before_block(nir_cf_node *node, nir_block *block) -{ - /* split off the beginning of block into new_block */ - nir_block *new_block = split_block_beginning(block); - - /* insert our node in between new_block and block */ - insert_non_block(new_block, node, block); -} - /* walk up the control flow tree to find the innermost enclosed loop */ static nir_loop * nearest_loop(nir_cf_node *node) @@ -584,60 +570,6 @@ nir_handle_remove_jump(nir_block *block, nir_jump_type type) } static void -insert_non_block_after_block(nir_block *block, nir_cf_node *node) -{ - /* split off the end of block into new_block */ - nir_block *new_block = split_block_end(block); - - /* insert our node in between block and new_block */ - insert_non_block(block, node, new_block); -} - -/** - * Inserts a basic block before another by merging the instructions. - * - * @param block the target of the insertion - * @param before the block to be inserted - must not have been inserted before - * @param has_jump whether \before has a jump instruction at the end - */ - -static void -insert_block_before_block(nir_block *block, nir_block *before, bool has_jump) -{ - assert(!has_jump || exec_list_is_empty(&block->instr_list)); - - foreach_list_typed(nir_instr, instr, node, &before->instr_list) { - instr->block = block; - } - - exec_list_prepend(&block->instr_list, &before->instr_list); - - if (has_jump) - nir_handle_add_jump(block); -} - -/** - * Inserts a basic block after another by merging the instructions. - * - * @param block the target of the insertion - * @param after the block to be inserted - must not have been inserted before - * @param has_jump whether \after has a jump instruction at the end - */ - -static void -insert_block_after_block(nir_block *block, nir_block *after, bool has_jump) -{ - foreach_list_typed(nir_instr, instr, node, &after->instr_list) { - instr->block = block; - } - - exec_list_append(&block->instr_list, &after->instr_list); - - if (has_jump) - nir_handle_add_jump(block); -} - -static void update_if_uses(nir_cf_node *node) { if (node->type != nir_cf_node_if) @@ -655,109 +587,6 @@ update_if_uses(nir_cf_node *node) } } -void -nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after) -{ - update_if_uses(after); - - if (after->type == nir_cf_node_block) { - /* - * either node or the one after it must be a basic block, by invariant #2; - * in either case, just merge the blocks together. - */ - nir_block *after_block = nir_cf_node_as_block(after); - - bool has_jump = !exec_list_is_empty(&after_block->instr_list) && - nir_block_last_instr(after_block)->type == nir_instr_type_jump; - - if (node->type == nir_cf_node_block) { - insert_block_after_block(nir_cf_node_as_block(node), after_block, - has_jump); - } else { - nir_cf_node *next = nir_cf_node_next(node); - assert(next->type == nir_cf_node_block); - nir_block *next_block = nir_cf_node_as_block(next); - - insert_block_before_block(next_block, after_block, has_jump); - } - } else { - if (node->type == nir_cf_node_block) { - insert_non_block_after_block(nir_cf_node_as_block(node), after); - } else { - /* - * We have to insert a non-basic block after a non-basic block. Since - * every non-basic block has a basic block after it, this is equivalent - * to inserting a non-basic block before a basic block. - */ - - nir_cf_node *next = nir_cf_node_next(node); - assert(next->type == nir_cf_node_block); - nir_block *next_block = nir_cf_node_as_block(next); - - insert_non_block_before_block(after, next_block); - } - } - - nir_function_impl *impl = nir_cf_node_get_function(node); - nir_metadata_preserve(impl, nir_metadata_none); -} - -void -nir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before) -{ - update_if_uses(before); - - if (before->type == nir_cf_node_block) { - nir_block *before_block = nir_cf_node_as_block(before); - - bool has_jump = !exec_list_is_empty(&before_block->instr_list) && - nir_block_last_instr(before_block)->type == nir_instr_type_jump; - - if (node->type == nir_cf_node_block) { - insert_block_before_block(nir_cf_node_as_block(node), before_block, - has_jump); - } else { - nir_cf_node *prev = nir_cf_node_prev(node); - assert(prev->type == nir_cf_node_block); - nir_block *prev_block = nir_cf_node_as_block(prev); - - insert_block_after_block(prev_block, before_block, has_jump); - } - } else { - if (node->type == nir_cf_node_block) { - insert_non_block_before_block(before, nir_cf_node_as_block(node)); - } else { - /* - * We have to insert a non-basic block before a non-basic block. This - * is equivalent to inserting a non-basic block after a basic block. - */ - - nir_cf_node *prev_node = nir_cf_node_prev(node); - assert(prev_node->type == nir_cf_node_block); - nir_block *prev_block = nir_cf_node_as_block(prev_node); - - insert_non_block_after_block(prev_block, before); - } - } - - nir_function_impl *impl = nir_cf_node_get_function(node); - nir_metadata_preserve(impl, nir_metadata_none); -} - -void -nir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node) -{ - nir_cf_node *begin = exec_node_data(nir_cf_node, list->head, node); - nir_cf_node_insert_before(begin, node); -} - -void -nir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node) -{ - nir_cf_node *end = exec_node_data(nir_cf_node, list->tail_pred, node); - nir_cf_node_insert_after(end, node); -} - /** * Stitch two basic blocks together into one. The aggregate must have the same * predecessors as the first and the same successors as the second. @@ -793,6 +622,32 @@ stitch_blocks(nir_block *before, nir_block *after) } } +void +nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node) +{ + nir_block *before, *after; + + split_block_cursor(cursor, &before, &after); + + if (node->type == nir_cf_node_block) { + nir_block *block = nir_cf_node_as_block(node); + exec_node_insert_after(&before->cf_node.node, &block->cf_node.node); + block->cf_node.parent = before->cf_node.parent; + /* stitch_blocks() assumes that any block that ends with a jump has + * already been setup with the correct successors, so we need to set + * up jumps here as the block is being inserted. + */ + if (block_ends_in_jump(block)) + nir_handle_add_jump(block); + + stitch_blocks(block, after); + stitch_blocks(before, block); + } else { + update_if_uses(node); + insert_non_block(before, node, after); + } +} + static bool replace_ssa_def_uses(nir_ssa_def *def, void *void_impl) { diff --git a/src/glsl/nir/nir_control_flow.h b/src/glsl/nir/nir_control_flow.h index 407b258caf5..5a3be260f63 100644 --- a/src/glsl/nir/nir_control_flow.h +++ b/src/glsl/nir/nir_control_flow.h @@ -130,17 +130,36 @@ nir_after_cf_list(struct exec_list *cf_list) /** Control flow insertion. */ +/** puts a control flow node where the cursor is */ +void nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node); + /** puts a control flow node immediately after another control flow node */ -void nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after); +static inline void +nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after) +{ + nir_cf_node_insert(nir_after_cf_node(node), after); +} /** puts a control flow node immediately before another control flow node */ -void nir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before); +static inline void +nir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before) +{ + nir_cf_node_insert(nir_before_cf_node(node), before); +} /** puts a control flow node at the beginning of a list from an if, loop, or function */ -void nir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node); +static inline void +nir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node) +{ + nir_cf_node_insert(nir_before_cf_list(list), node); +} /** puts a control flow node at the end of a list from an if, loop, or function */ -void nir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node); +static inline void +nir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node) +{ + nir_cf_node_insert(nir_after_cf_list(list), node); +} /** removes a control flow node, doing any cleanup necessary */ void nir_cf_node_remove(nir_cf_node *node); |