[Mesa-dev] [PATCH 2/2] nir: Optimize away IF statements with no body on either side.

Eric Anholt eric at anholt.net
Thu Jul 7 00:12:33 UTC 2016


Due to the rampant dead code elimination in coordinate shaders for vc4, we
often end up with IFs that do nothing on either side.  In the
loops-enabled build, shader-db gives:

total instructions in shared programs: 125192 -> 119693 (-4.39%)
instructions in affected programs:     30649 -> 25150 (-17.94%)
total uniforms in shared programs: 38436 -> 37632 (-2.09%)
uniforms in affected programs:     6168 -> 5364 (-13.04%)
---
 src/compiler/nir/nir_opt_dead_cf.c | 41 ++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/src/compiler/nir/nir_opt_dead_cf.c b/src/compiler/nir/nir_opt_dead_cf.c
index 81c1b650da96..eb98dc9507fb 100644
--- a/src/compiler/nir/nir_opt_dead_cf.c
+++ b/src/compiler/nir/nir_opt_dead_cf.c
@@ -60,6 +60,12 @@
  * }
  * ...
  *
+ * We also delete IF statements with no instructions in either body:
+ *
+ * if (...) {
+ * } else {
+ * }
+ *
  * Finally, we also handle removing useless loops, i.e. loops with no side
  * effects and without any definitions that are used elsewhere. This case is a
  * little different from the first two in that the code is actually run (it
@@ -134,6 +140,32 @@ opt_constant_if(nir_if *if_stmt, bool condition)
    nir_cf_node_remove(&if_stmt->cf_node);
 }
 
+/* If the nir_if has no instructions on either side, then we can delete the
+ * IF, and therefore also its use of the condition variable.
+ */
+static bool
+opt_empty_if(nir_if *if_stmt)
+{
+   nir_cf_node *then_node = nir_if_first_then_node(if_stmt);
+   nir_cf_node *else_node = nir_if_first_else_node(if_stmt);
+
+   /* We can only have one block in each side, with no instructions in them */
+   if (nir_if_last_then_node(if_stmt) != then_node)
+      return false;
+   if (nir_if_last_else_node(if_stmt) != else_node)
+      return false;
+   nir_block *then_block = nir_cf_node_as_block(then_node);
+   nir_block *else_block = nir_cf_node_as_block(else_node);
+   if (!exec_list_is_empty(&then_block->instr_list))
+      return false;
+   if (!exec_list_is_empty(&else_block->instr_list))
+      return false;
+
+   nir_cf_node_remove(&if_stmt->cf_node);
+
+   return true;
+}
+
 static bool
 cf_node_has_side_effects(nir_cf_node *node)
 {
@@ -224,11 +256,12 @@ dead_cf_block(nir_block *block)
       nir_const_value *const_value =
          nir_src_as_const_value(following_if->condition);
 
-      if (!const_value)
-         return false;
+      if (const_value) {
+         opt_constant_if(following_if, const_value->u32[0] != 0);
+         return true;
+      }
 
-      opt_constant_if(following_if, const_value->u32[0] != 0);
-      return true;
+      return opt_empty_if(following_if);
    }
 
    nir_loop *following_loop = nir_block_get_following_loop(block);
-- 
2.8.1



More information about the mesa-dev mailing list