[Mesa-dev] [PATCH v4 2/7] nir: propagates if condition evaluation down some alu chains
Timothy Arceri
tarceri at itsqueeze.com
Mon Aug 27 09:08:54 UTC 2018
v2:
- only allow nir_op_inot or nir_op_b2i when alu input is 1.
- use some helpers as suggested by Jason.
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 | 135 ++++++++++++++++++++++++++++++++--
1 file changed, 129 insertions(+), 6 deletions(-)
diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c
index 11c6693d302..6d81705f6b7 100644
--- a/src/compiler/nir/nir_opt_if.c
+++ b/src/compiler/nir/nir_opt_if.c
@@ -403,9 +403,113 @@ evaluate_if_condition(nir_if *nif, nir_cursor cursor, uint32_t *value)
}
}
+/*
+ * 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 is_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 is_if_condition)
+{
+ bool progress = false;
+
+ uint32_t bool_value;
+ nir_cursor cursor = nir_before_src(alu_use, is_if_condition);
+ if (nir_op_infos[alu->op].num_inputs == 1) {
+ if ((alu->op == nir_op_inot || alu->op == nir_op_b2i) &&
+ evaluate_if_condition(nif, cursor, &bool_value)) {
+ replace_if_condition_use_with_const(alu_use, mem_ctx, cursor,
+ bool_value, is_if_condition);
+ progress = true;
+ }
+ } else {
+ assert(alu->op == nir_op_ior || alu->op == nir_op_iand);
+
+ if (evaluate_if_condition(nif, cursor, &bool_value)) {
+ nir_ssa_def *def[2];
+ for (unsigned i = 0; i < 2; i++) {
+ if (alu->src[i].src.ssa == use_src->ssa) {
+ if (is_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 const_value;
+ const_value.u32[0] = bool_value;
+
+ def[i] = nir_build_imm(b, 1, 32, const_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 (is_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 is_if_condition)
{
bool progress = false;
@@ -417,23 +521,42 @@ evaluate_condition_use(nir_if *nif, nir_src *use_src, void *mem_ctx,
progress = true;
}
+ if (!is_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;
@@ -489,7 +612,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