[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