<div dir="ltr">Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Aug 27, 2018 at 4:09 AM Timothy Arceri <<a href="mailto:tarceri@itsqueeze.com">tarceri@itsqueeze.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This adds support for unrolling the classic<br>
<br>
    do {<br>
        // ...<br>
    } while (false)<br>
<br>
that is used to wrap multi-line macros. GLSL IR also wraps switch<br>
statements in a loop like this.<br>
<br>
shader-db results IVB:<br>
<br>
total loops in shared programs: 2515 -> 2512 (-0.12%)<br>
loops in affected programs: 33 -> 30 (-9.09%)<br>
helped: 3<br>
HURT: 0<br>
---<br>
 src/compiler/nir/nir_opt_loop_unroll.c | 77 ++++++++++++++++++++++++++<br>
 1 file changed, 77 insertions(+)<br>
<br>
diff --git a/src/compiler/nir/nir_opt_loop_unroll.c b/src/compiler/nir/nir_opt_loop_unroll.c<br>
index e0e0b754716..9c33267cb72 100644<br>
--- a/src/compiler/nir/nir_opt_loop_unroll.c<br>
+++ b/src/compiler/nir/nir_opt_loop_unroll.c<br>
@@ -465,6 +465,65 @@ complex_unroll(nir_loop *loop, nir_loop_terminator *unlimit_term,<br>
    _mesa_hash_table_destroy(remap_table, NULL);<br>
 }<br>
<br>
+/* Unrolls the classic wrapper loops e.g<br>
+ *<br>
+ *    do {<br>
+ *        // ...<br>
+ *    } while (false)<br>
+ */<br>
+static bool<br>
+wrapper_unroll(nir_loop *loop)<br>
+{<br>
+   bool progress = false;<br>
+<br>
+   nir_block *blk_after_loop =<br>
+      nir_cursor_current_block(nir_after_cf_node(&loop->cf_node));<br>
+<br>
+   /* There may still be some single src phis following the loop that<br>
+    * have not yet been cleaned up by another pass. Tidy those up before<br>
+    * unrolling the loop.<br>
+    */<br>
+   nir_foreach_instr_safe(instr, blk_after_loop) {<br>
+      if (instr->type != nir_instr_type_phi)<br>
+         break;<br>
+<br>
+      nir_phi_instr *phi = nir_instr_as_phi(instr);<br>
+      assert(exec_list_length(&phi->srcs) == 1);<br>
+<br>
+      nir_phi_src *phi_src = exec_node_data(nir_phi_src,<br>
+                                            exec_list_get_head(&phi->srcs),<br>
+                                            node);<br>
+<br>
+      nir_ssa_def_rewrite_uses(&phi->dest.ssa, phi_src->src);<br>
+      nir_instr_remove(instr);<br>
+<br>
+      progress = true;<br>
+   }<br>
+<br>
+   nir_block *last_loop_blk = nir_loop_last_block(loop);<br>
+   if (nir_block_ends_in_break(last_loop_blk)) {<br>
+<br>
+      /* Remove break at end of the loop */<br>
+      nir_instr *break_instr = nir_block_last_instr(last_loop_blk);<br>
+      nir_instr_remove(break_instr);<br>
+<br>
+      /* Pluck out the loop body. */<br>
+      nir_cf_list loop_body;<br>
+      nir_cf_extract(&loop_body, nir_before_block(nir_loop_first_block(loop)),<br>
+                     nir_after_block(nir_loop_last_block(loop)));<br>
+<br>
+      /* Reinsert loop body after the loop */<br>
+      nir_cf_reinsert(&loop_body, nir_after_cf_node(&loop->cf_node));<br>
+<br>
+      /* The loop has been unrolled so remove it. */<br>
+      nir_cf_node_remove(&loop->cf_node);<br>
+<br>
+      progress = true;<br>
+   }<br>
+<br>
+   return progress;<br>
+}<br>
+<br>
 static bool<br>
 is_loop_small_enough_to_unroll(nir_shader *shader, nir_loop_info *li)<br>
 {<br>
@@ -516,6 +575,24 @@ process_loops(nir_shader *sh, nir_cf_node *cf_node, bool *has_nested_loop_out)<br>
     */<br>
    if (!progress) {<br>
<br>
+      /* Check for the classic<br>
+       *<br>
+       *    do {<br>
+       *        // ...<br>
+       *    } while (false)<br>
+       *<br>
+       * that is used to wrap multi-line macros. GLSL IR also wraps switch<br>
+       * statements in a loop like this.<br>
+       */<br>
+      if (loop->info->limiting_terminator == NULL &&<br>
+          list_empty(&loop->info->loop_terminator_list) &&<br>
+          !loop->info->complex_loop) {<br>
+<br>
+         progress = wrapper_unroll(loop);<br>
+<br>
+         goto exit;<br>
+      }<br>
+<br>
       if (has_nested_loop || loop->info->limiting_terminator == NULL)<br>
          goto exit;<br>
<br>
-- <br>
2.17.1<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">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/mailman/listinfo/mesa-dev</a><br>
</blockquote></div>