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,
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");
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 *
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) {
if (addr || pred) {
int ret = trysched(ctx, instr);
+
+ if (ret != DELAYED)
+ all_delayed = false;
+
if (ret == SCHEDULED)
cnt = 0;
else if (ret > 0)
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;
}
}
}
- 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)
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;
}