mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 08:50:13 +01:00
freedreno/ir3: detect scheduler fail
There are some cases where the scheduler can get itself into impossible situations, by scheduling the wrong write to pred or addr register first. (Ie. it could end up being unable to schedule any instruction if some instruction which depends on the current addr/reg value also depends on another addr/reg value.) To solve this we'd need to be able to insert extra mov instructions (which would also help when register assignment gets into impossible situations). To do that, we'd need to move the nop padding from sched into legalize. But to start with, just detect when we get into an impossible situation and bail, rather than sitting forever in an infinite loop. This way it will at least fall back to the old compiler, which might even work if you are lucky. Signed-off-by: Rob Clark <robclark@freedesktop.org>
This commit is contained in:
parent
932b0ef1ce
commit
b823abedf8
3 changed files with 21 additions and 4 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue