From 590efd180be05817163d1b70990273b535a82afe Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Thu, 27 May 2021 17:28:09 +0200 Subject: [PATCH] ir3: Prevent propagating shared regs out of loops Part-of: --- src/freedreno/ir3/ir3.h | 2 ++ src/freedreno/ir3/ir3_compiler_nir.c | 5 +++++ src/freedreno/ir3/ir3_context.h | 2 ++ src/freedreno/ir3/ir3_cp.c | 11 +++++++++++ 4 files changed, 20 insertions(+) diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index eab2360..e181439 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -563,6 +563,8 @@ struct ir3_block { uint32_t dom_pre_index; uint32_t dom_post_index; + uint32_t loop_id; + #ifdef DEBUG uint32_t serialno; #endif diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index ff52d1c..6b219a2 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -2861,6 +2861,8 @@ emit_block(struct ir3_context *ctx, nir_block *nblock) list_addtail(&ctx->block->node, &ctx->ir->block_list); + ctx->block->loop_id = ctx->loop_id; + /* re-emit addr register in each block if needed: */ for (int i = 0; i < ARRAY_SIZE(ctx->addr0_ht); i++) { _mesa_hash_table_destroy(ctx->addr0_ht[i], NULL); @@ -2915,8 +2917,11 @@ emit_if(struct ir3_context *ctx, nir_if *nif) static void emit_loop(struct ir3_context *ctx, nir_loop *nloop) { + unsigned old_loop_id = ctx->loop_id; + ctx->loop_id = ctx->so->loops + 1; emit_cf_list(ctx, &nloop->body); ctx->so->loops++; + ctx->loop_id = old_loop_id; } static void diff --git a/src/freedreno/ir3/ir3_context.h b/src/freedreno/ir3/ir3_context.h index 31ab63c..25e95c6 100644 --- a/src/freedreno/ir3/ir3_context.h +++ b/src/freedreno/ir3/ir3_context.h @@ -110,6 +110,8 @@ struct ir3_context { */ unsigned stack, max_stack; + unsigned loop_id; + /* a common pattern for indirect addressing is to request the * same address register multiple times. To avoid generating * duplicate instruction sequences (which our backend does not diff --git a/src/freedreno/ir3/ir3_cp.c b/src/freedreno/ir3/ir3_cp.c index 0efe02e..a0c5ac9 100644 --- a/src/freedreno/ir3/ir3_cp.c +++ b/src/freedreno/ir3/ir3_cp.c @@ -310,6 +310,17 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, { struct ir3_instruction *src = ssa(reg); + /* Values that are uniform inside a loop can become divergent outside + * it if the loop has a divergent trip count. This means that we can't + * propagate a copy of a shared to non-shared register if it would + * make the shared reg's live range extend outside of its loop. Users + * outside the loop would see the value for the thread(s) that last + * exited the loop, rather than for their own thread. + */ + if ((src->dsts[0]->flags & IR3_REG_SHARED) && + src->block->loop_id != instr->block->loop_id) + return false; + if (is_eligible_mov(src, instr, true)) { /* simple case, no immed/const/relativ, only mov's w/ ssa src: */ struct ir3_register *src_reg = src->srcs[0]; -- 2.7.4