nir/cf: use a cursor for inserting control flow

Signed-off-by: Connor Abbott <connor.w.abbott@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Connor Abbott 2015-07-21 19:54:33 -07:00 committed by Kenneth Graunke
parent d356f84d4c
commit 476eb5e4a1
2 changed files with 49 additions and 175 deletions

View 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)
{

View 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);