From 95732cc9ef33f6b125cfaf26ae59bf2faab54e5b Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 16 Jul 2019 15:57:19 -0700 Subject: [PATCH] pan/midgard: Obey fragment writeout criteria MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Rather than always emitting an extra move for fragments, check the actual criteria and emit accordingly. (This was lost during the RA improvements at the end of May). total bundles in shared programs: 2210 -> 2176 (-1.54%) bundles in affected programs: 501 -> 467 (-6.79%) helped: 34 HURT: 0 helped stats (abs) min: 1 max: 1 x̄: 1.00 x̃: 1 helped stats (rel) min: 1.59% max: 33.33% x̄: 13.13% x̃: 12.50% 95% mean confidence interval for bundles value: -1.00 -1.00 95% mean confidence interval for bundles %-change: -16.06% -10.21% Bundles are helped. total quadwords in shared programs: 3639 -> 3605 (-0.93%) quadwords in affected programs: 795 -> 761 (-4.28%) helped: 34 HURT: 0 helped stats (abs) min: 1 max: 1 x̄: 1.00 x̃: 1 helped stats (rel) min: 0.96% max: 33.33% x̄: 11.22% x̃: 8.33% 95% mean confidence interval for quadwords value: -1.00 -1.00 95% mean confidence interval for quadwords %-change: -14.31% -8.13% Quadwords are helped. Signed-off-by: Alyssa Rosenzweig --- src/panfrost/midgard/midgard_schedule.c | 78 ++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/src/panfrost/midgard/midgard_schedule.c b/src/panfrost/midgard/midgard_schedule.c index 6b689e4ee40..4672f144d9c 100644 --- a/src/panfrost/midgard/midgard_schedule.c +++ b/src/panfrost/midgard/midgard_schedule.c @@ -118,6 +118,68 @@ midgard_has_hazard( } +/* Fragment writeout (of r0) is allowed when: + * + * - All components of r0 are written in the bundle + * - No components of r0 are written in VLUT + * - Dependencies of r0 are not written in the bundle + * + * This function checks if these requirements are satisfied given the content + * of a scheduled bundle. + */ + +static bool +can_writeout_fragment(midgard_instruction **bundle, unsigned count, unsigned node_count) +{ + /* First scan for which components of r0 are written out. Initially + * none are written */ + + uint8_t r0_written_mask = 0x0; + + /* Simultaneously we scan for the set of dependencies */ + BITSET_WORD *dependencies = calloc(sizeof(BITSET_WORD), BITSET_WORDS(node_count)); + + for (unsigned i = 0; i < count; ++i) { + midgard_instruction *ins = bundle[i]; + + if (ins->ssa_args.dest != SSA_FIXED_REGISTER(0)) + continue; + + /* Record written out mask */ + r0_written_mask |= ins->mask; + + /* Record dependencies */ + unsigned src0 = ins->ssa_args.src0; + unsigned src1 = ins->ssa_args.src1; + + if ((src0 > 0) && (src0 < node_count)) + BITSET_SET(dependencies, src0); + + if ((src1 > 0) && (src1 < node_count)) + BITSET_SET(dependencies, src1); + + /* Requirement 2 */ + if (ins->unit == UNIT_VLUT) + return false; + } + + /* Requirement 1 */ + if ((r0_written_mask & 0xF) != 0xF) + return false; + + /* Requirement 3 */ + + for (unsigned i = 0; i < count; ++i) { + unsigned dest = bundle[i]->ssa_args.dest; + + if (dest < node_count && BITSET_TEST(dependencies, dest)) + return false; + } + + /* Otherwise, we're good to go */ + return true; +} + /* Schedules, but does not emit, a single basic block. After scheduling, the * final tag and size of the block are known, which are necessary for branching * */ @@ -128,6 +190,8 @@ schedule_bundle(compiler_context *ctx, midgard_block *block, midgard_instruction int instructions_emitted = 0, packed_idx = 0; midgard_bundle bundle = { 0 }; + midgard_instruction *scheduled[5] = { NULL }; + uint8_t tag = ins->type; /* Default to the instruction's tag */ @@ -386,15 +450,12 @@ schedule_bundle(compiler_context *ctx, midgard_block *block, midgard_instruction /* All of r0 has to be written out along with * the branch writeout */ - if (ains->writeout) { - /* The rules for when "bare" writeout - * is safe are when all components are - * r0 are written out in the final - * bundle, earlier than VLUT, where any - * register dependencies of r0 are from - * an earlier bundle. We can't verify - * this before RA, so we don't try. */ + unsigned node_count = ctx->func->impl->ssa_alloc + ctx->func->impl->reg_alloc; + if (ains->writeout && !can_writeout_fragment(scheduled, index, node_count)) { + /* We only work on full moves + * at the beginning. We could + * probably do better */ if (index != 0) break; @@ -422,6 +483,7 @@ schedule_bundle(compiler_context *ctx, midgard_block *block, midgard_instruction } /* Defer marking until after writing to allow for break */ + scheduled[index] = ains; control |= ains->unit; last_unit = ains->unit; ++instructions_emitted; -- 2.30.2