diff options
author | Jason Ekstrand <[email protected]> | 2015-02-03 21:39:56 -0800 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-02-19 17:06:17 -0800 |
commit | 98ecb25f89c59da2d1bd4b02e12a5e39fac8a9e5 (patch) | |
tree | c9e1f3b2cbf7a54196111c903baba3ab3b0fa811 /src/glsl/nir | |
parent | e025943134ada9dad02926e8191dd1bd2e7fc95e (diff) |
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 <[email protected]>
Diffstat (limited to 'src/glsl/nir')
-rw-r--r-- | src/glsl/nir/nir.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/glsl/nir/nir.c b/src/glsl/nir/nir.c index 3b78766e6a2..5b0e4bc5061 100644 --- a/src/glsl/nir/nir.c +++ b/src/glsl/nir/nir.c @@ -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 |