summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3.h2
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_compiler.c4
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_sched.c19
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;
}