[Mesa-stable] [PATCH 5/6] freedreno/ir3: detect scheduler fail
Emil Velikov
emil.l.velikov at gmail.com
Fri Sep 5 08:35:07 PDT 2014
As requested over IRC by Rob, this patch has been dropped/rejected and the
rest of the series has been scooped up for 10.3.
-Emil
On 02/09/14 21:16, Rob Clark wrote:
> From: Rob Clark <robclark at freedesktop.org>
>
> 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 at freedesktop.org>
> ---
> src/gallium/drivers/freedreno/ir3/ir3.h | 2 +-
> src/gallium/drivers/freedreno/ir3/ir3_compiler.c | 4 +++-
> 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 9ed914b..d4059ad 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 1fa2fd4..b587ee0 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 3ef6773..33d1caa 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;
> }
>
More information about the mesa-stable
mailing list