[Mesa-dev] [RFC 2/2] nir: When splitting blocks, always put the new block after the old
Jason Ekstrand
jason at jlekstrand.net
Fri Sep 16 04:00:36 UTC 2016
This makes block splitting happen a bit more deterministically. In
particular, if using nir_builder to build a shader, it means that you can
always save off nir_cursor_current_block and then add another CF node after
that without fear that the nir_block pointer you just saved will get
replaced out from under you.
---
src/compiler/nir/nir.h | 2 +
src/compiler/nir/nir_control_flow.c | 97 +++++++++++++------------------------
2 files changed, 35 insertions(+), 64 deletions(-)
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 6f059720..9ab8440 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -1511,6 +1511,8 @@ nir_block_last_instr(nir_block *block)
foreach_list_typed_reverse(nir_instr, instr, node, &(block)->instr_list)
#define nir_foreach_instr_safe(instr, block) \
foreach_list_typed_safe(nir_instr, instr, node, &(block)->instr_list)
+#define nir_foreach_instr_safe_after(instr, block, after) \
+ foreach_list_typed_safe_after(nir_instr, instr, node, after)
#define nir_foreach_instr_reverse_safe(instr, block) \
foreach_list_typed_reverse_safe(nir_instr, instr, node, &(block)->instr_list)
diff --git a/src/compiler/nir/nir_control_flow.c b/src/compiler/nir/nir_control_flow.c
index 1ff7a53..7210197 100644
--- a/src/compiler/nir/nir_control_flow.c
+++ b/src/compiler/nir/nir_control_flow.c
@@ -178,60 +178,6 @@ link_block_to_non_block(nir_block *block, nir_cf_node *node)
}
-/**
- * Replace a block's successor with a different one.
- */
-static void
-replace_successor(nir_block *block, nir_block *old_succ, nir_block *new_succ)
-{
- if (block->successors[0] == old_succ) {
- block->successors[0] = new_succ;
- } else {
- assert(block->successors[1] == old_succ);
- block->successors[1] = new_succ;
- }
-
- block_remove_pred(old_succ, block);
- block_add_pred(new_succ, block);
-}
-
-/**
- * Takes a basic block and inserts a new empty basic block before it, making its
- * predecessors point to the new block. This essentially splits the block into
- * an empty header and a body so that another non-block CF node can be inserted
- * between the two. Note that this does *not* link the two basic blocks, so
- * some kind of cleanup *must* be performed after this call.
- */
-
-static nir_block *
-split_block_beginning(nir_block *block)
-{
- nir_block *new_block = nir_block_create(ralloc_parent(block));
- new_block->cf_node.parent = block->cf_node.parent;
- exec_node_insert_node_before(&block->cf_node.node, &new_block->cf_node.node);
-
- struct set_entry *entry;
- set_foreach(block->predecessors, entry) {
- nir_block *pred = (nir_block *) entry->key;
- replace_successor(pred, block, new_block);
- }
-
- /* Any phi nodes must stay part of the new block, or else their
- * sourcse will be messed up. This will reverse the order of the phi's, but
- * order shouldn't matter.
- */
- nir_foreach_instr_safe(instr, block) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- exec_node_remove(&instr->node);
- instr->block = new_block;
- exec_list_push_head(&new_block->instr_list, &instr->node);
- }
-
- return new_block;
-}
-
static void
rewrite_phi_preds(nir_block *block, nir_block *old_pred, nir_block *new_pred)
{
@@ -359,6 +305,28 @@ block_add_normal_succs(nir_block *block)
}
static nir_block *
+split_block_beginning(nir_block *block)
+{
+ nir_block *new_block = nir_block_create(ralloc_parent(block));
+ new_block->cf_node.parent = block->cf_node.parent;
+ exec_node_insert_after(&block->cf_node.node, &new_block->cf_node.node);
+
+ /* Move everything except the phis to the new block */
+ nir_foreach_instr_safe(cur_instr, block) {
+ if (cur_instr->type == nir_instr_type_phi)
+ continue;
+
+ exec_node_remove(&cur_instr->node);
+ cur_instr->block = new_block;
+ exec_list_push_tail(&new_block->instr_list, &cur_instr->node);
+ }
+
+ move_successors(block, new_block);
+
+ return new_block;
+}
+
+static nir_block *
split_block_end(nir_block *block)
{
nir_block *new_block = nir_block_create(ralloc_parent(block));
@@ -381,12 +349,13 @@ static nir_block *
split_block_before_instr(nir_instr *instr)
{
assert(instr->type != nir_instr_type_phi);
- nir_block *new_block = split_block_beginning(instr->block);
+ nir_block *block = instr->block;
- nir_foreach_instr_safe(cur_instr, instr->block) {
- if (cur_instr == instr)
- break;
+ nir_block *new_block = nir_block_create(ralloc_parent(block));
+ new_block->cf_node.parent = block->cf_node.parent;
+ exec_node_insert_after(&block->cf_node.node, &new_block->cf_node.node);
+ nir_foreach_instr_safe_after(cur_instr, instr->block, instr) {
exec_node_remove(&cur_instr->node);
cur_instr->block = new_block;
exec_list_push_tail(&new_block->instr_list, &cur_instr->node);
@@ -409,8 +378,8 @@ split_block_cursor(nir_cursor cursor,
nir_block *before, *after;
switch (cursor.option) {
case nir_cursor_before_block:
- after = cursor.block;
- before = split_block_beginning(cursor.block);
+ before = cursor.block;
+ after = split_block_beginning(cursor.block);
break;
case nir_cursor_after_block:
@@ -419,8 +388,8 @@ split_block_cursor(nir_cursor cursor,
break;
case nir_cursor_before_instr:
- after = cursor.instr->block;
- before = split_block_before_instr(cursor.instr);
+ before = cursor.instr->block;
+ after = split_block_before_instr(cursor.instr);
break;
case nir_cursor_after_instr:
@@ -431,8 +400,8 @@ split_block_cursor(nir_cursor cursor,
before = cursor.instr->block;
after = split_block_end(cursor.instr->block);
} else {
- after = cursor.instr->block;
- before = split_block_before_instr(nir_instr_next(cursor.instr));
+ before = cursor.instr->block;
+ after = split_block_before_instr(nir_instr_next(cursor.instr));
}
break;
--
2.5.0.400.gff86faf
More information about the mesa-dev
mailing list