summaryrefslogtreecommitdiffstats
path: root/src/glsl/nir/nir.c
diff options
context:
space:
mode:
authorJason Ekstrand <jason.ekstrand@intel.com>2015-02-03 21:39:56 -0800
committerJason Ekstrand <jason.ekstrand@intel.com>2015-02-19 17:06:17 -0800
commit98ecb25f89c59da2d1bd4b02e12a5e39fac8a9e5 (patch)
treec9e1f3b2cbf7a54196111c903baba3ab3b0fa811 /src/glsl/nir/nir.c
parente025943134ada9dad02926e8191dd1bd2e7fc95e (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 <cwabbott0@gmail.com>
Diffstat (limited to 'src/glsl/nir/nir.c')
-rw-r--r--src/glsl/nir/nir.c54
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