<div dir="ltr"><div>Both are<br><br></div>Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Mar 19, 2018 at 4:34 PM, Caio Marcelo de Oliveira Filho <span dir="ltr"><<a href="mailto:caio.oliveira@intel.com" target="_blank">caio.oliveira@intel.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">Generalize the code for remove dead loops to also remove dead if<br>
nodes. The conditions are the same in both cases, if the node (and<br>
it's children) don't have side-effects AND the nodes after it don't<br>
use the values produced by the node.<br>
<br>
The only difference is when evaluating side effects: loops consider<br>
only return jumps as a side-effect -- they can stop execution of nodes<br>
</span>after it; 'if' nodes outside loops should consider all kinds of<br>
<span class="">jumps (return, break, continue) since all of them can cause execution<br>
of nodes after it to be skipped.<br>
<br>
After this patch, empty ifs (those which both then and else blocks are<br>
empty) will be removed by nir_opt_dead_cf.<br>
<br>
It caused no change to shader-db, in part because the removal of empty<br>
ifs is currently covered by nir_opt_peephole_select.<br>
<br>
v2: Improve the identification of cases where break/continue can cause<br>
    side-effects. (Jason)<br>
<br>
</span>v3: Move code comment changes to a different patch. (Jason)<br>
---<br>
 src/compiler/nir/nir_opt_dead_<wbr>cf.c | 44 ++++++++++++++++++++++++++----<wbr>--------<br>
 1 file changed, 30 insertions(+), 14 deletions(-)<br>
<br>
diff --git a/src/compiler/nir/nir_opt_<wbr>dead_cf.c b/src/compiler/nir/nir_opt_<wbr>dead_cf.c<br>
index b15dfdd0c9..a652bcd99b 100644<br>
<span class="">--- a/src/compiler/nir/nir_opt_<wbr>dead_cf.c<br>
+++ b/src/compiler/nir/nir_opt_<wbr>dead_cf.c<br>
@@ -60,12 +60,12 @@<br>
  * }<br>
  * ...<br>
  *<br>
- * Finally, we also handle removing useless loops, i.e. loops with no side<br>
- * effects and without any definitions that are used elsewhere. This case is a<br>
- * little different from the first two in that the code is actually run (it<br>
- * just never does anything), but there are similar issues with needing to<br>
- * be careful with restarting after deleting the cf_node (see dead_cf_list())<br>
- * so this is a convenient place to remove them.<br>
+ * Finally, we also handle removing useless loops and ifs, i.e. loops and ifs<br>
+ * with no side effects and without any definitions that are used<br>
+ * elsewhere. This case is a little different from the first two in that the<br>
+ * code is actually run (it just never does anything), but there are similar<br>
+ * issues with needing to be careful with restarting after deleting the<br>
+ * cf_node (see dead_cf_list()) so this is a convenient place to remove them.<br>
  */<br>
<br>
 static void<br>
</span>@@ -136,6 +136,12 @@ static bool<br>
<span class=""> cf_node_has_side_effects(nir_<wbr>cf_node *node)<br>
 {<br>
    nir_foreach_block_in_cf_node(<wbr>block, node) {<br>
+      bool inside_loop = node->type == nir_cf_node_loop;<br>
+      for (nir_cf_node *n = &block->cf_node; !inside_loop && n != node; n = n->parent) {<br>
+         if (n->type == nir_cf_node_loop)<br>
+            inside_loop = true;<br>
+      }<br>
+<br>
       nir_foreach_instr(instr, block) {<br>
</span><span class="">          if (instr->type == nir_instr_type_call)<br>
             return true;<br>
</span>@@ -143,10 +149,13 @@ cf_node_has_side_effects(nir_<wbr>cf_node *node)<br>
<span class="">          /* Return instructions can cause us to skip over other side-effecting<br>
           * instructions after the loop, so consider them to have side effects<br>
           * here.<br>
+          *<br>
+          * When the block is not inside a loop, break and continue might also<br>
+          * cause a skip.<br>
           */<br>
<br>
          if (instr->type == nir_instr_type_jump &&<br>
-             nir_instr_as_jump(instr)->type == nir_jump_return)<br>
+             (!inside_loop || nir_instr_as_jump(instr)->type == nir_jump_return))<br>
             return true;<br>
<br>
          if (instr->type != nir_instr_type_intrinsic)<br>
</span>@@ -171,7 +180,7 @@ def_not_live_out(nir_ssa_def *def, void *state)<br>
 }<br>
<br>
 /*<br>
- * Test if a loop is dead. A loop node is dead if:<br>
<span class="">+ * Test if a loop node or if node is dead. Such nodes are dead if:<br>
  *<br>
  * 1) It has no side effects (i.e. intrinsics which could possibly affect the<br>
  * state of the program aside from producing an SSA value, indicated by a lack<br>
</span>@@ -187,19 +196,21 @@ def_not_live_out(nir_ssa_def *def, void *state)<br>
<span class="">  */<br>
<br>
 static bool<br>
-loop_is_dead(nir_loop *loop)<br>
+node_is_dead(nir_cf_node *node)<br>
 {<br>
-   nir_block *before = nir_cf_node_as_block(nir_cf_<wbr>node_prev(&loop->cf_node));<br>
-   nir_block *after = nir_cf_node_as_block(nir_cf_<wbr>node_next(&loop->cf_node));<br>
+   assert(node->type == nir_cf_node_loop || node->type == nir_cf_node_if);<br>
+<br>
+   nir_block *before = nir_cf_node_as_block(nir_cf_<wbr>node_prev(node));<br>
+   nir_block *after = nir_cf_node_as_block(nir_cf_<wbr>node_next(node));<br>
<br>
    if (!exec_list_is_empty(&after-><wbr>instr_list) &&<br>
        nir_block_first_instr(after)-><wbr>type == nir_instr_type_phi)<br>
       return false;<br>
<br>
-   if (cf_node_has_side_effects(&<wbr>loop->cf_node))<br>
+   if (cf_node_has_side_effects(<wbr>node))<br>
       return false;<br>
<br>
-   nir_function_impl *impl = nir_cf_node_get_function(&<wbr>loop->cf_node);<br>
+   nir_function_impl *impl = nir_cf_node_get_function(node)<wbr>;<br>
    nir_metadata_require(impl, nir_metadata_live_ssa_defs |<br>
                               nir_metadata_dominance);<br>
<br>
</span>@@ -219,6 +230,11 @@ dead_cf_block(nir_block *block)<br>
<span class=""> {<br>
    nir_if *following_if = nir_block_get_following_if(<wbr>block);<br>
    if (following_if) {<br>
+      if (node_is_dead(&following_if-><wbr>cf_node)) {<br>
+         nir_cf_node_remove(&following_<wbr>if->cf_node);<br>
+         return true;<br>
+      }<br>
+<br>
       nir_const_value *const_value =<br>
          nir_src_as_const_value(<wbr>following_if->condition);<br>
<br>
</span>@@ -233,7 +249,7 @@ dead_cf_block(nir_block *block)<br>
<div class="HOEnZb"><div class="h5">    if (!following_loop)<br>
       return false;<br>
<br>
-   if (!loop_is_dead(following_loop)<wbr>)<br>
+   if (!node_is_dead(&following_<wbr>loop->cf_node))<br>
       return false;<br>
<br>
    nir_cf_node_remove(&following_<wbr>loop->cf_node);<br>
--<br>
2.16.2<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</div></div></blockquote></div><br></div>