<div dir="ltr"><div>It took me a while to figure out what you're doing here but, once I've grokked it, I like it.  That said, I'd like to see your response to my comments on patch 1 as that would cause this to get restructured a good bit.  (I think it will be much improved for it.)</div><div><br></div><div>--Jason<br></div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jul 23, 2018 at 3:02 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">shader-db IVB results:<br>
<br>
total instructions in shared programs: 9993483 -> 9993472 (-0.00%)<br>
instructions in affected programs: 1300 -> 1289 (-0.85%)<br>
helped: 11<br>
HURT: 0<br>
<br>
total cycles in shared programs: 219476091 -> 219476059 (-0.00%)<br>
cycles in affected programs: 7675 -> 7643 (-0.42%)<br>
helped: 10<br>
HURT: 1<br>
---<br>
 src/compiler/nir/nir_opt_if.c | 155 ++++++++++++++++++++++++++++++++--<br>
 1 file changed, 149 insertions(+), 6 deletions(-)<br>
<br>
diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c<br>
index b3d5046a76e..c9e50cec1fe 100644<br>
--- a/src/compiler/nir/nir_opt_if.c<br>
+++ b/src/compiler/nir/nir_opt_if.c<br>
@@ -404,9 +404,134 @@ replace_if_condition_use_with_const(nir_src *use, unsigned nir_boolean,<br>
       nir_instr_rewrite_src(use->parent_instr, use, new_src);<br>
 }<br>
<br>
+/*<br>
+ * This propagates if condition evaluation down the chain of some alu<br>
+ * instructions. For example by checking the use of some of the following alu<br>
+ * instruction we can eventually replace ssa_107 with NIR_TRUE.<br>
+ *<br>
+ *   loop {<br>
+ *      block block_1:<br>
+ *      vec1 32 ssa_85 = load_const (0x00000002)<br>
+ *      vec1 32 ssa_86 = ieq ssa_48, ssa_85<br>
+ *      vec1 32 ssa_87 = load_const (0x00000001)<br>
+ *      vec1 32 ssa_88 = ieq ssa_48, ssa_87<br>
+ *      vec1 32 ssa_89 = ior ssa_86, ssa_88<br>
+ *      vec1 32 ssa_90 = ieq ssa_48, ssa_0<br>
+ *      vec1 32 ssa_91 = ior ssa_89, ssa_90<br>
+ *      if ssa_86 {<br>
+ *         block block_2:<br>
+ *             ...<br>
+ *            break<br>
+ *      } else {<br>
+ *            block block_3:<br>
+ *      }<br>
+ *      block block_4:<br>
+ *      if ssa_88 {<br>
+ *            block block_5:<br>
+ *             ...<br>
+ *            break<br>
+ *      } else {<br>
+ *            block block_6:<br>
+ *      }<br>
+ *      block block_7:<br>
+ *      if ssa_90 {<br>
+ *            block block_8:<br>
+ *             ...<br>
+ *            break<br>
+ *      } else {<br>
+ *            block block_9:<br>
+ *      }<br>
+ *      block block_10:<br>
+ *      vec1 32 ssa_107 = inot ssa_91<br>
+ *      if ssa_107 {<br>
+ *            block block_11:<br>
+ *            break<br>
+ *      } else {<br>
+ *            block block_12:<br>
+ *      }<br>
+ *   }<br>
+ */<br>
+static bool<br>
+propagate_condition_eval(nir_builder *b, nir_if *nif, nir_src *use_src,<br>
+                         nir_src *alu_use, nir_alu_instr *alu, void *mem_ctx,<br>
+                         bool if_condition)<br>
+{<br>
+   bool progress = false;<br>
+<br>
+   nir_block *use_block;<br>
+   if (if_condition) {<br>
+      use_block =<br>
+         nir_cf_node_as_block(nir_cf_node_prev(&alu_use->parent_if->cf_node));<br>
+   } else {<br>
+      use_block = alu_use->parent_instr->block;<br>
+   }<br>
+<br>
+   if (nir_op_infos[alu->op].num_inputs == 1) {<br>
+      if (nir_block_dominates(nir_if_first_then_block(nif), use_block)) {<br>
+         replace_if_condition_use_with_const(alu_use, NIR_TRUE, mem_ctx,<br>
+                                             if_condition);<br>
+         progress = true;<br>
+      } else if (nir_block_dominates(nir_if_first_else_block(nif),<br>
+                                     use_block)) {<br>
+         replace_if_condition_use_with_const(alu_use, NIR_FALSE, mem_ctx,<br>
+                                             if_condition);<br>
+         progress = true;<br>
+      }<br>
+   } else {<br>
+      assert(alu->op == nir_op_ior || alu->op == nir_op_iand);<br>
+<br>
+      bool found = false;<br>
+      unsigned nir_boolean = 0;<br>
+      if (nir_block_dominates(nir_if_first_then_block(nif), use_block)) {<br>
+         nir_boolean = NIR_TRUE;<br>
+         found = true;<br>
+      } else if (nir_block_dominates(nir_if_first_else_block(nif),<br>
+                                     use_block)) {<br>
+         nir_boolean = NIR_FALSE;<br>
+         found = true;<br>
+      }<br>
+<br>
+      if (found) {<br>
+         nir_ssa_def *def[2];<br>
+         for (unsigned i = 0; i < 2; i++) {<br>
+            if (alu->src[i].src.ssa == use_src->ssa) {<br>
+               if (if_condition) {<br>
+                  b->cursor =<br>
+                     nir_before_cf_node(&alu_use->parent_if->cf_node);<br>
+               } else {<br>
+                  b->cursor = nir_before_instr(alu_use->parent_instr);<br>
+               }<br>
+<br>
+               nir_const_value value;<br>
+               value.u32[0] = nir_boolean;<br>
+<br>
+               def[i] = nir_build_imm(b, 1, 32, value);<br>
+            } else {<br>
+               def[i] = alu->src[i].src.ssa;<br>
+            }<br>
+         }<br>
+<br>
+         nir_ssa_def *nalu =<br>
+            nir_build_alu(b, alu->op, def[0], def[1], NULL, NULL);<br>
+<br>
+         /* Rewrite use to use new alu instruction */<br>
+         nir_src new_src = nir_src_for_ssa(nalu);<br>
+<br>
+         if (if_condition)<br>
+            nir_if_rewrite_condition(alu_use->parent_if, new_src);<br>
+         else<br>
+            nir_instr_rewrite_src(alu_use->parent_instr, alu_use, new_src);<br>
+<br>
+         progress = true;<br>
+      }<br>
+   }<br>
+<br>
+   return progress;<br>
+}<br>
+<br>
 static bool<br>
-evaluate_condition_use(nir_if *nif, nir_src *use_src, void *mem_ctx,<br>
-                       bool if_condition)<br>
+evaluate_condition_use(nir_builder *b, nir_if *nif, nir_src *use_src,<br>
+                       void *mem_ctx, bool if_condition)<br>
 {<br>
    bool progress = false;<br>
<br>
@@ -428,23 +553,41 @@ evaluate_condition_use(nir_if *nif, nir_src *use_src, void *mem_ctx,<br>
       progress = true;<br>
    }<br>
<br>
+   if (!if_condition && use_src->parent_instr->type == nir_instr_type_alu &&<br>
+       (nir_instr_as_alu(use_src->parent_instr)->op == nir_op_ior ||<br>
+        nir_instr_as_alu(use_src->parent_instr)->op == nir_op_iand ||<br>
+        nir_op_infos[nir_instr_as_alu(use_src->parent_instr)->op].num_inputs == 1)) {<br>
+<br>
+         nir_alu_instr *alu = nir_instr_as_alu(use_src->parent_instr);<br>
+<br>
+         nir_foreach_use_safe(alu_use, &alu->dest.dest.ssa) {<br>
+            progress |= propagate_condition_eval(b, nif, use_src, alu_use, alu,<br>
+                                                 mem_ctx, false);<br>
+         }<br>
+<br>
+         nir_foreach_if_use_safe(alu_use, &alu->dest.dest.ssa) {<br>
+            progress |= propagate_condition_eval(b, nif, use_src, alu_use, alu,<br>
+                                                 mem_ctx, true);<br>
+         }<br>
+   }<br>
+<br>
    return progress;<br>
 }<br>
<br>
 static bool<br>
-opt_if_evaluate_condition_use(nir_if *nif, void *mem_ctx)<br>
+opt_if_evaluate_condition_use(nir_builder *b, nir_if *nif, void *mem_ctx)<br>
 {<br>
    bool progress = false;<br>
<br>
    /* Evaluate any uses of the if condition inside the if branches */<br>
    assert(nif->condition.is_ssa);<br>
    nir_foreach_use_safe(use_src, nif->condition.ssa) {<br>
-      progress |= evaluate_condition_use(nif, use_src, mem_ctx, false);<br>
+      progress |= evaluate_condition_use(b, nif, use_src, mem_ctx, false);<br>
    }<br>
<br>
    nir_foreach_if_use_safe(use_src, nif->condition.ssa) {<br>
       if (use_src->parent_if != nif)<br>
-         progress |= evaluate_condition_use(nif, use_src, mem_ctx, true);<br>
+         progress |= evaluate_condition_use(b, nif, use_src, mem_ctx, true);<br>
    }<br>
<br>
    return progress;<br>
@@ -500,7 +643,7 @@ opt_if_safe_cf_list(nir_builder *b, struct exec_list *cf_list, void *mem_ctx)<br>
          nir_if *nif = nir_cf_node_as_if(cf_node);<br>
          progress |= opt_if_safe_cf_list(b, &nif->then_list, mem_ctx);<br>
          progress |= opt_if_safe_cf_list(b, &nif->else_list, mem_ctx);<br>
-         progress |= opt_if_evaluate_condition_use(nif, mem_ctx);<br>
+         progress |= opt_if_evaluate_condition_use(b, nif, mem_ctx);<br>
          break;<br>
       }<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>