<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sun, Mar 25, 2018 at 6:32 PM, Timothy Arceri <span dir="ltr"><<a href="mailto:tarceri@itsqueeze.com" target="_blank">tarceri@itsqueeze.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">When an if nesting inside anouther if is optimised away we can<br>
end up with a loop terminator and following block that looks like<br>
this:<br>
<br>
        if ssa_596 {<br>
                block block_5:<br>
                /* preds: block_4 */<br>
                vec1 32 ssa_601 = load_const (0xffffffff /* -nan */)<br>
                break<br>
                /* succs: block_8 */<br>
        } else {<br>
                block block_6:<br>
                /* preds: block_4 */<br>
                /* succs: block_7 */<br>
        }<br>
        block block_7:<br>
        /* preds: block_6 */<br>
        vec1 32 ssa_602 = phi block_6: ssa_552<br>
        vec1 32 ssa_603 = phi block_6: ssa_553<br>
        vec1 32 ssa_604 = iadd ssa_551, ssa_66<br>
<br>
The problem is the phis. Loop unrolling expects the last block in<br>
the loop to be empty once we splice the instructions in the last<br>
block into the continue branch. The problem is we cant move phis<br>
so here we lower the phis to regs when preparing the loop for<br>
unrolling. As it could be possible to have multiple additional<br>
blocks/ifs following the terminator we just convert all phis at<br>
the top level of the loop body for simplicity.<br>
<br>
We also add some comments to loop_prepare_for_unroll() while we<br>
are here.<br>
<br>
Fixes: 51daccb289eb "nir: add a loop unrolling pass"<br>
<br>
Bugzilla: <a href="https://bugs.freedesktop.org/show_bug.cgi?id=105670" rel="noreferrer" target="_blank">https://bugs.freedesktop.org/s<wbr>how_bug.cgi?id=105670</a><br>
---<br>
 src/compiler/nir/nir_opt_<wbr>loop_unroll.c | 17 ++++++++++++-----<br>
 1 file changed, 12 insertions(+), 5 deletions(-)<br>
<br>
diff --git a/src/compiler/nir/nir_opt_loo<wbr>p_unroll.c b/src/compiler/nir/nir_opt_loo<wbr>p_unroll.c<br>
index 79d04f978bc..85df3097264 100644<br>
--- a/src/compiler/nir/nir_opt_loo<wbr>p_unroll.c<br>
+++ b/src/compiler/nir/nir_opt_loo<wbr>p_unroll.c<br>
@@ -37,10 +37,10 @@<br>
 #define LOOP_UNROLL_LIMIT 26<br>
<br>
 /* Prepare this loop for unrolling by first converting to lcssa and then<br>
- * converting the phis from the loops first block and the block that follows<br>
- * the loop into regs.  Partially converting out of SSA allows us to unroll<br>
- * the loop without having to keep track of and update phis along the way<br>
- * which gets tricky and doesn't add much value over conveting to regs.<br>
+ * converting the phis from the top level of the loop body to regs.<br>
+ * Partially converting out of SSA allows us to unroll the loop without having<br>
+ * to keep track of and update phis along the way which gets tricky and<br>
+ * doesn't add much value over conveting to regs.<br></blockquote><div><br></div><div>converting<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  *<br>
  * The loop may have a continue instruction at the end of the loop which does<br>
  * nothing.  Once we're out of SSA, we can safely delete it so we don't have<br>
@@ -51,13 +51,20 @@ loop_prepare_for_unroll(nir_lo<wbr>op *loop)<br>
 {<br>
    nir_convert_loop_to_lcssa(loop<wbr>);<br>
<br>
-   nir_lower_phis_to_regs_block(<wbr>nir_loop_first_block(loop));<br>
+   /* Lower phis at the top level of the loop body */<br>
+   foreach_list_typed_safe(nir_c<wbr>f_node, node, node, &loop->body) {<br>
+      if (nir_cf_node_block == node->type) {<br>
+         nir_lower_phis_to_regs_block(<wbr>nir_cf_node_as_block(node));<br>
+      }<br>
+   }<br></blockquote><div><br></div><div>This is a bit of a big hammer and I don't really like it for that but it does work.  We could predicate it on block->predecessors->entries == 1 or we could try and do something even more clever.  That said, this is tricky and what you've done is robust so I'm ok with it as-is.<br><br></div><div>Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
+   /* Lower phis after the loop */<br>
    nir_block *block_after_loop =<br>
       nir_cf_node_as_block(nir_cf_n<wbr>ode_next(&loop->cf_node));<br>
<br>
    nir_lower_phis_to_regs_block(b<wbr>lock_after_loop);<br>
<br>
+   /* Remove continue if its the last instruction in the loop */<br>
    nir_instr *last_instr = nir_block_last_instr(nir_loop_<wbr>last_block(loop));<br>
    if (last_instr && last_instr->type == nir_instr_type_jump) {<br>
       assert(nir_instr_as_jump(<wbr>last_instr)->type == nir_jump_continue);<br>
<span class="m_-8834972475437675592HOEnZb"><font color="#888888">--<br>
2.14.3<br>
<br>
______________________________<wbr>_________________<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/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>