From c601ba332b4a106072cd3315b7886e9937d86212 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Fri, 20 May 2022 13:57:23 +0200 Subject: [PATCH] ir3/sched: Fix could_sched() determination This needs to be accurate so that when we split and then schedule a new a0.x/a1.x/p0.x write we will eventually make progress. It wasn't taking the kill_path into account which could create an infinite loop as we keep scheduling writes whose uses are blocked because they are memory instructions not on the kill_path. Closes: #6413 Part-of: --- src/freedreno/ir3/ir3_sched.c | 46 +++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/freedreno/ir3/ir3_sched.c b/src/freedreno/ir3/ir3_sched.c index cd76918e371..ddb9de08c2b 100644 --- a/src/freedreno/ir3/ir3_sched.c +++ b/src/freedreno/ir3/ir3_sched.c @@ -371,9 +371,28 @@ struct ir3_sched_notes { bool addr0_conflict, addr1_conflict, pred_conflict; }; +static bool +should_skip(struct ir3_sched_ctx *ctx, struct ir3_instruction *instr) +{ + if (ctx->remaining_kills && (is_tex(instr) || is_mem(instr))) { + /* avoid texture/memory access if we have unscheduled kills + * that could make the expensive operation unnecessary. By + * definition, if there are remaining kills, and this instr + * is not a dependency of a kill, there are other instructions + * that we can choose from. + */ + struct ir3_sched_node *n = instr->data; + if (!n->kill_path) + return true; + } + + return false; +} + /* could an instruction be scheduled if specified ssa src was scheduled? */ static bool -could_sched(struct ir3_instruction *instr, struct ir3_instruction *src) +could_sched(struct ir3_sched_ctx *ctx, + struct ir3_instruction *instr, struct ir3_instruction *src) { foreach_ssa_src (other_src, instr) { /* if dependency not scheduled, we aren't ready yet: */ @@ -381,7 +400,13 @@ could_sched(struct ir3_instruction *instr, struct ir3_instruction *src) return false; } } - return true; + + /* Instructions not in the current block can never be scheduled. + */ + if (instr->block != src->block) + return false; + + return !should_skip(ctx, instr); } /* Check if instruction is ok to schedule. Make sure it is not blocked @@ -400,17 +425,8 @@ check_instr(struct ir3_sched_ctx *ctx, struct ir3_sched_notes *notes, return false; } - if (ctx->remaining_kills && (is_tex(instr) || is_mem(instr))) { - /* avoid texture/memory access if we have unscheduled kills - * that could make the expensive operation unnecessary. By - * definition, if there are remaining kills, and this instr - * is not a dependency of a kill, there are other instructions - * that we can choose from. - */ - struct ir3_sched_node *n = instr->data; - if (!n->kill_path) - return false; - } + if (should_skip(ctx, instr)) + return false; /* For instructions that write address register we need to * make sure there is at least one instruction that uses the @@ -428,7 +444,7 @@ check_instr(struct ir3_sched_ctx *ctx, struct ir3_sched_notes *notes, continue; if (indirect->address->def != instr->dsts[0]) continue; - ready = could_sched(indirect, instr); + ready = could_sched(ctx, indirect, instr); } /* nothing could be scheduled, so keep looking: */ @@ -445,7 +461,7 @@ check_instr(struct ir3_sched_ctx *ctx, struct ir3_sched_notes *notes, continue; if (indirect->address->def != instr->dsts[0]) continue; - ready = could_sched(indirect, instr); + ready = could_sched(ctx, indirect, instr); } /* nothing could be scheduled, so keep looking: */