nir/cf: use a cursor for inserting control flow
authorConnor Abbott <cwabbott0@gmail.com>
Wed, 22 Jul 2015 02:54:33 +0000 (19:54 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Mon, 24 Aug 2015 20:31:42 +0000 (13:31 -0700)
Signed-off-by: Connor Abbott <connor.w.abbott@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/glsl/nir/nir_control_flow.c
src/glsl/nir/nir_control_flow.h

index 935ec9f2c47e309ec62e9ddc43d5e22955314241..ba39205ba29d88576b23fcf20dce07b76590adb3 100644 (file)
@@ -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)
@@ -583,60 +569,6 @@ nir_handle_remove_jump(nir_block *block, nir_jump_type type)
    nir_metadata_preserve(impl, nir_metadata_none);
 }
 
-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)
 {
@@ -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)
 {
index 407b258caf5c14cb08f91c23cdb06a8de1fbeee3..5a3be260f63005bcf5fb535f876377a9302ead1f 100644 (file)
@@ -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);