diff options
author | Alyssa Rosenzweig <[email protected]> | 2019-09-28 10:43:51 -0400 |
---|---|---|
committer | Alyssa Rosenzweig <[email protected]> | 2019-09-30 08:40:13 -0400 |
commit | a3ca283bc171e5d241bbd619dd52773f1d0f892d (patch) | |
tree | 5e3c25cdfbacf9b36a02692584157ef11f66a0a6 /src/panfrost/midgard | |
parent | 12a70ccd9ec7bd4d28bc66a3646942a1a4e055c2 (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.c | 41 |
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); |