summaryrefslogtreecommitdiffstats
path: root/src/freedreno/ir3
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2020-03-04 09:06:51 -0800
committerMarge Bot <[email protected]>2020-03-10 16:01:39 +0000
commit3c96e25de77b4879f54ef5727378dacf13e7e398 (patch)
treed5fa4ab00c41920eca114fa7b9dd6cc8522f1358 /src/freedreno/ir3
parentcc82521de4e8e85022a5facb1b5f52d5139d3022 (diff)
freedreno/ir3: try to avoid syncs
Update postsched to be better aware of where costly (ss) syncs would result. Sometimes it is better to allow a nop or two, to avoid a sync quickly after an SFU. Signed-off-by: Rob Clark <[email protected]> Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4071> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4071>
Diffstat (limited to 'src/freedreno/ir3')
-rw-r--r--src/freedreno/ir3/ir3_postsched.c56
1 files changed, 55 insertions, 1 deletions
diff --git a/src/freedreno/ir3/ir3_postsched.c b/src/freedreno/ir3/ir3_postsched.c
index 1e706f75a24..b283af486fb 100644
--- a/src/freedreno/ir3/ir3_postsched.c
+++ b/src/freedreno/ir3/ir3_postsched.c
@@ -62,6 +62,8 @@ struct ir3_postsched_ctx {
struct ir3_instruction *pred; /* current p0.x user, if any */
bool error;
+
+ int sfu_delay;
};
struct ir3_postsched_node {
@@ -97,6 +99,12 @@ schedule(struct ir3_postsched_ctx *ctx, struct ir3_instruction *instr)
list_addtail(&instr->node, &instr->block->instr_list);
ctx->scheduled = instr;
+ if (is_sfu(instr)) {
+ ctx->sfu_delay = 8;
+ } else if (ctx->sfu_delay > 0) {
+ ctx->sfu_delay--;
+ }
+
struct ir3_postsched_node *n = instr->data;
dag_prune_head(ctx->dag, &n->dag);
}
@@ -119,6 +127,24 @@ dump_state(struct ir3_postsched_ctx *ctx)
}
}
+/* Determine if this is an instruction that we'd prefer not to schedule
+ * yet, in order to avoid an (ss) sync. This is limited by the sfu_delay
+ * counter, ie. the more cycles it has been since the last SFU, the less
+ * costly a sync would be.
+ */
+static bool
+would_sync(struct ir3_postsched_ctx *ctx, struct ir3_instruction *instr)
+{
+ if (ctx->sfu_delay) {
+ struct ir3_register *reg;
+ foreach_src (reg, instr)
+ if (reg->instr && is_sfu(reg->instr))
+ return true;
+ }
+
+ return false;
+}
+
/* find instruction to schedule: */
static struct ir3_instruction *
choose_instr(struct ir3_postsched_ctx *ctx)
@@ -195,7 +221,35 @@ choose_instr(struct ir3_postsched_ctx *ctx)
return chosen->instr;
}
- /* First try to find a ready leader w/ soft delay (ie. including extra
+ /*
+ * Sometimes be better to take a nop, rather than scheduling an
+ * instruction that would require an (ss) shortly after another
+ * SFU.. ie. if last SFU was just one or two instr ago, and we
+ * could choose between taking a nop and then scheduling
+ * something else, vs scheduling the immed avail instruction that
+ * would require (ss), we are better with the nop.
+ */
+ for (unsigned delay = 0; delay < 4; delay++) {
+ foreach_sched_node (n, &ctx->dag->heads) {
+ if (would_sync(ctx, n->instr))
+ continue;
+
+ unsigned d = ir3_delay_calc(ctx->block, n->instr, true, false);
+
+ if (d > delay)
+ continue;
+
+ if (!chosen || (chosen->max_delay < n->max_delay))
+ chosen = n;
+ }
+
+ if (chosen) {
+ di(chosen->instr, "csp: chose (soft ready, delay=%u)", delay);
+ return chosen->instr;
+ }
+ }
+
+ /* Next try to find a ready leader w/ soft delay (ie. including extra
* delay for things like tex fetch which can be synchronized w/ sync
* bit (but we probably do want to schedule some other instructions
* while we wait)