nir: Properly clean up CF nodes when we remove them
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 4 Feb 2015 05:39:56 +0000 (21:39 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Fri, 20 Feb 2015 01:06:17 +0000 (17:06 -0800)
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>
src/glsl/nir/nir.c

index 3b78766e6a224a389c2633008fd38d389cf72076..5b0e4bc50612d4d2299a3f31973e7da28e5ca0af 100644 (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