nir: Properly clean up CF nodes when we remove them

Previously, if you remved a CF node that still had instructions in it, none
of the use/def information from those instructions would get cleaned up.
Also, we weren't removing if statements from the if_uses of the
corresponding register or SSA def.  This commit fixes both of these
problems

Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
This commit is contained in:
Jason Ekstrand 2015-02-03 21:39:56 -08:00
parent e025943134
commit 98ecb25f89
1 changed files with 54 additions and 0 deletions

View File

@ -1150,6 +1150,58 @@ stitch_blocks(nir_block *before, nir_block *after)
exec_node_remove(&after->cf_node.node);
}
static void
remove_defs_uses(nir_instr *instr);
static void
cleanup_cf_node(nir_cf_node *node)
{
switch (node->type) {
case nir_cf_node_block: {
nir_block *block = nir_cf_node_as_block(node);
/* We need to walk the instructions and clean up defs/uses */
nir_foreach_instr(block, instr)
remove_defs_uses(instr);
break;
}
case nir_cf_node_if: {
nir_if *if_stmt = nir_cf_node_as_if(node);
foreach_list_typed(nir_cf_node, child, node, &if_stmt->then_list)
cleanup_cf_node(child);
foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list)
cleanup_cf_node(child);
struct set *if_uses;
if (if_stmt->condition.is_ssa) {
if_uses = if_stmt->condition.ssa->if_uses;
} else {
if_uses = if_stmt->condition.reg.reg->if_uses;
}
struct set_entry *entry = _mesa_set_search(if_uses, if_stmt);
assert(entry);
_mesa_set_remove(if_uses, entry);
break;
}
case nir_cf_node_loop: {
nir_loop *loop = nir_cf_node_as_loop(node);
foreach_list_typed(nir_cf_node, child, node, &loop->body)
cleanup_cf_node(child);
break;
}
case nir_cf_node_function: {
nir_function_impl *impl = nir_cf_node_as_function(node);
foreach_list_typed(nir_cf_node, child, node, &impl->body)
cleanup_cf_node(child);
break;
}
default:
unreachable("Invalid CF node type");
}
}
void
nir_cf_node_remove(nir_cf_node *node)
{
@ -1177,6 +1229,8 @@ nir_cf_node_remove(nir_cf_node *node)
exec_node_remove(&node->node);
stitch_blocks(before_block, after_block);
}
cleanup_cf_node(node);
}
static bool