aboutsummaryrefslogtreecommitdiffstats
path: root/src/panfrost/midgard
diff options
context:
space:
mode:
authorAlyssa Rosenzweig <[email protected]>2019-09-28 10:43:51 -0400
committerAlyssa Rosenzweig <[email protected]>2019-09-30 08:40:13 -0400
commita3ca283bc171e5d241bbd619dd52773f1d0f892d (patch)
tree5e3c25cdfbacf9b36a02692584157ef11f66a0a6 /src/panfrost/midgard
parent12a70ccd9ec7bd4d28bc66a3646942a1a4e055c2 (diff)
pan/midgard: Allow writeout to see into the future
If an instruction could be scheduled to vmul to satisfy the writeout conditions, let's do that and save an instruction+cycle per fragment shader. Signed-off-by: Alyssa Rosenzweig <[email protected]>
Diffstat (limited to 'src/panfrost/midgard')
-rw-r--r--src/panfrost/midgard/midgard_schedule.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/src/panfrost/midgard/midgard_schedule.c b/src/panfrost/midgard/midgard_schedule.c
index ff71e0dcd3f..d09726bf449 100644
--- a/src/panfrost/midgard/midgard_schedule.c
+++ b/src/panfrost/midgard/midgard_schedule.c
@@ -339,6 +339,12 @@ struct midgard_predicate {
/* Don't schedule instructions consuming conditionals (since we already
* scheduled one). Excludes conditional branches and csel */
bool no_cond;
+
+ /* Require a minimal mask and (if nonzero) given destination. Used for
+ * writeout optimizations */
+
+ unsigned mask;
+ unsigned dest;
};
/* For an instruction that can fit, adjust it to fit and update the constants
@@ -400,6 +406,10 @@ mir_choose_instruction(
bool scalar = (unit != ~0) && (unit & UNITS_SCALAR);
bool no_cond = predicate->no_cond;
+ unsigned mask = predicate->mask;
+ unsigned dest = predicate->dest;
+ bool needs_dest = mask & 0xF;
+
/* Iterate to find the best instruction satisfying the predicate */
unsigned i;
BITSET_WORD tmp;
@@ -440,6 +450,12 @@ mir_choose_instruction(
if (alu && !mir_adjust_constants(instructions[i], predicate, false))
continue;
+ if (needs_dest && instructions[i]->dest != dest)
+ continue;
+
+ if (mask && ((~instructions[i]->mask) & mask))
+ continue;
+
bool conditional = alu && !branch && OP_IS_CSEL(instructions[i]->alu.op);
conditional |= (branch && !instructions[i]->prepacked_branch && instructions[i]->branch.conditional);
@@ -817,7 +833,30 @@ mir_schedule_alu(
bad_writeout |= mir_has_arg(stages[i], branch->src[0]);
}
- /* Add a move if necessary */
+ /* It's possible we'll be able to schedule something into vmul
+ * to fill r0. Let's peak into the future, trying to schedule
+ * vmul specially that way. */
+
+ if (!bad_writeout && writeout_mask != 0xF) {
+ predicate.unit = UNIT_VMUL;
+ predicate.dest = src;
+ predicate.mask = writeout_mask ^ 0xF;
+
+ struct midgard_instruction *peaked =
+ mir_choose_instruction(instructions, worklist, len, &predicate);
+
+ if (peaked) {
+ vmul = peaked;
+ vmul->unit = UNIT_VMUL;
+ writeout_mask |= predicate.mask;
+ assert(writeout_mask == 0xF);
+ }
+
+ /* Cleanup */
+ predicate.dest = predicate.mask = 0;
+ }
+
+ /* Finally, add a move if necessary */
if (bad_writeout || writeout_mask != 0xF) {
unsigned temp = (branch->src[0] == ~0) ? SSA_FIXED_REGISTER(0) : make_compiler_temp(ctx);
midgard_instruction mov = v_mov(src, blank_alu_src, temp);