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 <robdclark@chromium.org> Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4071> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4071>
This commit is contained in:
parent
cc82521de4
commit
3c96e25de7
|
@ -62,6 +62,8 @@ struct ir3_postsched_ctx {
|
||||||
struct ir3_instruction *pred; /* current p0.x user, if any */
|
struct ir3_instruction *pred; /* current p0.x user, if any */
|
||||||
|
|
||||||
bool error;
|
bool error;
|
||||||
|
|
||||||
|
int sfu_delay;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ir3_postsched_node {
|
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);
|
list_addtail(&instr->node, &instr->block->instr_list);
|
||||||
ctx->scheduled = instr;
|
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;
|
struct ir3_postsched_node *n = instr->data;
|
||||||
dag_prune_head(ctx->dag, &n->dag);
|
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: */
|
/* find instruction to schedule: */
|
||||||
static struct ir3_instruction *
|
static struct ir3_instruction *
|
||||||
choose_instr(struct ir3_postsched_ctx *ctx)
|
choose_instr(struct ir3_postsched_ctx *ctx)
|
||||||
|
@ -195,7 +221,35 @@ choose_instr(struct ir3_postsched_ctx *ctx)
|
||||||
return chosen->instr;
|
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
|
* delay for things like tex fetch which can be synchronized w/ sync
|
||||||
* bit (but we probably do want to schedule some other instructions
|
* bit (but we probably do want to schedule some other instructions
|
||||||
* while we wait)
|
* while we wait)
|
||||||
|
|
Loading…
Reference in New Issue