diff options
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3_compiler.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3_sched.c | 19 |
3 files changed, 21 insertions, 4 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.h b/src/gallium/drivers/freedreno/ir3/ir3.h index 9ed914ba2e4..d4059ad004a 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3.h +++ b/src/gallium/drivers/freedreno/ir3/ir3.h @@ -406,7 +406,7 @@ void ir3_block_depth(struct ir3_block *block); void ir3_block_cp(struct ir3_block *block); /* scheduling: */ -void ir3_block_sched(struct ir3_block *block); +int ir3_block_sched(struct ir3_block *block); /* register assignment: */ int ir3_block_ra(struct ir3_block *block, enum shader_t type, diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler.c index 1fa2fd4e389..b587ee07a93 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_compiler.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler.c @@ -2574,7 +2574,9 @@ ir3_compile_shader(struct ir3_shader_variant *so, ir3_dump_instr_list(block->head); } - ir3_block_sched(block); + ret = ir3_block_sched(block); + if (ret) + goto out; if (fd_mesa_debug & FD_DBG_OPTMSGS) { printf("AFTER SCHED:\n"); diff --git a/src/gallium/drivers/freedreno/ir3/ir3_sched.c b/src/gallium/drivers/freedreno/ir3/ir3_sched.c index 3ef67731926..33d1caacca6 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_sched.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_sched.c @@ -64,6 +64,7 @@ struct ir3_sched_ctx { struct ir3_instruction *addr; /* current a0.x user, if any */ struct ir3_instruction *pred; /* current p0.x user, if any */ unsigned cnt; + bool error; }; static struct ir3_instruction * @@ -308,6 +309,7 @@ static int block_sched_undelayed(struct ir3_sched_ctx *ctx, struct ir3_instruction *instr = block->head; bool addr_in_use = false; bool pred_in_use = false; + bool all_delayed = true; unsigned cnt = ~0; while (instr) { @@ -317,6 +319,10 @@ static int block_sched_undelayed(struct ir3_sched_ctx *ctx, if (addr || pred) { int ret = trysched(ctx, instr); + + if (ret != DELAYED) + all_delayed = false; + if (ret == SCHEDULED) cnt = 0; else if (ret > 0) @@ -336,6 +342,12 @@ static int block_sched_undelayed(struct ir3_sched_ctx *ctx, if (!pred_in_use) ctx->pred = NULL; + /* detect if we've gotten ourselves into an impossible situation + * and bail if needed + */ + if (all_delayed) + ctx->error = true; + return cnt; } @@ -356,7 +368,7 @@ static void block_sched(struct ir3_sched_ctx *ctx, struct ir3_block *block) } } - while ((instr = block->head)) { + while ((instr = block->head) && !ctx->error) { /* NOTE: always grab next *before* trysched(), in case the * instruction is actually scheduled (and therefore moved * from depth list into scheduled list) @@ -393,9 +405,12 @@ static void block_sched(struct ir3_sched_ctx *ctx, struct ir3_block *block) block->head = reverse(ctx->scheduled); } -void ir3_block_sched(struct ir3_block *block) +int ir3_block_sched(struct ir3_block *block) { struct ir3_sched_ctx ctx = {0}; ir3_clear_mark(block->shader); block_sched(&ctx, block); + if (ctx.error) + return -1; + return 0; } |