[Mesa-dev] [PATCH v3 2/7] nir: propagates if condition evaluation down some alu chains

Timothy Arceri tarceri at itsqueeze.com
Mon Aug 20 02:49:20 UTC 2018


shader-db IVB results:

total instructions in shared programs: 9993483 -> 9993472 (-0.00%)
instructions in affected programs: 1300 -> 1289 (-0.85%)
helped: 11
HURT: 0

total cycles in shared programs: 219476091 -> 219476059 (-0.00%)
cycles in affected programs: 7675 -> 7643 (-0.42%)
helped: 10
HURT: 1
---
 src/compiler/nir/nir_opt_if.c | 155 ++++++++++++++++++++++++++++++++--
 1 file changed, 149 insertions(+), 6 deletions(-)

diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c
index 8c886041708..95c6dbb136a 100644
--- a/src/compiler/nir/nir_opt_if.c
+++ b/src/compiler/nir/nir_opt_if.c
@@ -405,9 +405,134 @@ replace_if_condition_use_with_const(nir_src *use, unsigned nir_boolean,
       nir_instr_rewrite_src(use->parent_instr, use, new_src);
 }
 
+/*
+ * This propagates if condition evaluation down the chain of some alu
+ * instructions. For example by checking the use of some of the following alu
+ * instruction we can eventually replace ssa_107 with NIR_TRUE.
+ *
+ *   loop {
+ *      block block_1:
+ *      vec1 32 ssa_85 = load_const (0x00000002)
+ *      vec1 32 ssa_86 = ieq ssa_48, ssa_85
+ *      vec1 32 ssa_87 = load_const (0x00000001)
+ *      vec1 32 ssa_88 = ieq ssa_48, ssa_87
+ *      vec1 32 ssa_89 = ior ssa_86, ssa_88
+ *      vec1 32 ssa_90 = ieq ssa_48, ssa_0
+ *      vec1 32 ssa_91 = ior ssa_89, ssa_90
+ *      if ssa_86 {
+ *         block block_2:
+ *             ...
+ *            break
+ *      } else {
+ *            block block_3:
+ *      }
+ *      block block_4:
+ *      if ssa_88 {
+ *            block block_5:
+ *             ...
+ *            break
+ *      } else {
+ *            block block_6:
+ *      }
+ *      block block_7:
+ *      if ssa_90 {
+ *            block block_8:
+ *             ...
+ *            break
+ *      } else {
+ *            block block_9:
+ *      }
+ *      block block_10:
+ *      vec1 32 ssa_107 = inot ssa_91
+ *      if ssa_107 {
+ *            block block_11:
+ *            break
+ *      } else {
+ *            block block_12:
+ *      }
+ *   }
+ */
 static bool
-evaluate_condition_use(nir_if *nif, nir_src *use_src, void *mem_ctx,
-                       bool if_condition)
+propagate_condition_eval(nir_builder *b, nir_if *nif, nir_src *use_src,
+                         nir_src *alu_use, nir_alu_instr *alu, void *mem_ctx,
+                         bool if_condition)
+{
+   bool progress = false;
+
+   nir_block *use_block;
+   if (if_condition) {
+      use_block =
+         nir_cf_node_as_block(nir_cf_node_prev(&alu_use->parent_if->cf_node));
+   } else {
+      use_block = alu_use->parent_instr->block;
+   }
+
+   if (nir_op_infos[alu->op].num_inputs == 1) {
+      if (nir_block_dominates(nir_if_first_then_block(nif), use_block)) {
+         replace_if_condition_use_with_const(alu_use, NIR_TRUE, mem_ctx,
+                                             if_condition);
+         progress = true;
+      } else if (nir_block_dominates(nir_if_first_else_block(nif),
+                                     use_block)) {
+         replace_if_condition_use_with_const(alu_use, NIR_FALSE, mem_ctx,
+                                             if_condition);
+         progress = true;
+      }
+   } else {
+      assert(alu->op == nir_op_ior || alu->op == nir_op_iand);
+
+      bool found = false;
+      unsigned nir_boolean = 0;
+      if (nir_block_dominates(nir_if_first_then_block(nif), use_block)) {
+         nir_boolean = NIR_TRUE;
+         found = true;
+      } else if (nir_block_dominates(nir_if_first_else_block(nif),
+                                     use_block)) {
+         nir_boolean = NIR_FALSE;
+         found = true;
+      }
+
+      if (found) {
+         nir_ssa_def *def[2];
+         for (unsigned i = 0; i < 2; i++) {
+            if (alu->src[i].src.ssa == use_src->ssa) {
+               if (if_condition) {
+                  b->cursor =
+                     nir_before_cf_node(&alu_use->parent_if->cf_node);
+               } else {
+                  b->cursor = nir_before_instr(alu_use->parent_instr);
+               }
+
+               nir_const_value value;
+               value.u32[0] = nir_boolean;
+
+               def[i] = nir_build_imm(b, 1, 32, value);
+            } else {
+               def[i] = alu->src[i].src.ssa;
+            }
+         }
+
+         nir_ssa_def *nalu =
+            nir_build_alu(b, alu->op, def[0], def[1], NULL, NULL);
+
+         /* Rewrite use to use new alu instruction */
+         nir_src new_src = nir_src_for_ssa(nalu);
+
+         if (if_condition)
+            nir_if_rewrite_condition(alu_use->parent_if, new_src);
+         else
+            nir_instr_rewrite_src(alu_use->parent_instr, alu_use, new_src);
+
+         progress = true;
+      }
+   }
+
+   return progress;
+}
+
+static bool
+evaluate_condition_use(nir_builder *b, nir_if *nif, nir_src *use_src,
+                       void *mem_ctx, bool if_condition)
 {
    bool progress = false;
 
@@ -439,23 +564,41 @@ evaluate_condition_use(nir_if *nif, nir_src *use_src, void *mem_ctx,
       progress = true;
    }
 
+   if (!if_condition && use_src->parent_instr->type == nir_instr_type_alu &&
+       (nir_instr_as_alu(use_src->parent_instr)->op == nir_op_ior ||
+        nir_instr_as_alu(use_src->parent_instr)->op == nir_op_iand ||
+        nir_op_infos[nir_instr_as_alu(use_src->parent_instr)->op].num_inputs == 1)) {
+
+         nir_alu_instr *alu = nir_instr_as_alu(use_src->parent_instr);
+
+         nir_foreach_use_safe(alu_use, &alu->dest.dest.ssa) {
+            progress |= propagate_condition_eval(b, nif, use_src, alu_use, alu,
+                                                 mem_ctx, false);
+         }
+
+         nir_foreach_if_use_safe(alu_use, &alu->dest.dest.ssa) {
+            progress |= propagate_condition_eval(b, nif, use_src, alu_use, alu,
+                                                 mem_ctx, true);
+         }
+   }
+
    return progress;
 }
 
 static bool
-opt_if_evaluate_condition_use(nir_if *nif, void *mem_ctx)
+opt_if_evaluate_condition_use(nir_builder *b, nir_if *nif, void *mem_ctx)
 {
    bool progress = false;
 
    /* Evaluate any uses of the if condition inside the if branches */
    assert(nif->condition.is_ssa);
    nir_foreach_use_safe(use_src, nif->condition.ssa) {
-      progress |= evaluate_condition_use(nif, use_src, mem_ctx, false);
+      progress |= evaluate_condition_use(b, nif, use_src, mem_ctx, false);
    }
 
    nir_foreach_if_use_safe(use_src, nif->condition.ssa) {
       if (use_src->parent_if != nif)
-         progress |= evaluate_condition_use(nif, use_src, mem_ctx, true);
+         progress |= evaluate_condition_use(b, nif, use_src, mem_ctx, true);
    }
 
    return progress;
@@ -511,7 +654,7 @@ opt_if_safe_cf_list(nir_builder *b, struct exec_list *cf_list, void *mem_ctx)
          nir_if *nif = nir_cf_node_as_if(cf_node);
          progress |= opt_if_safe_cf_list(b, &nif->then_list, mem_ctx);
          progress |= opt_if_safe_cf_list(b, &nif->else_list, mem_ctx);
-         progress |= opt_if_evaluate_condition_use(nif, mem_ctx);
+         progress |= opt_if_evaluate_condition_use(b, nif, mem_ctx);
          break;
       }
 
-- 
2.17.1



More information about the mesa-dev mailing list