ir3: Prevent propagating shared regs out of loops

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6752>
This commit is contained in:
Connor Abbott 2021-05-27 17:28:09 +02:00 committed by Marge Bot
parent 394c597b1b
commit 590efd180b
4 changed files with 20 additions and 0 deletions

View File

@ -563,6 +563,8 @@ struct ir3_block {
uint32_t dom_pre_index; uint32_t dom_pre_index;
uint32_t dom_post_index; uint32_t dom_post_index;
uint32_t loop_id;
#ifdef DEBUG #ifdef DEBUG
uint32_t serialno; uint32_t serialno;
#endif #endif

View File

@ -2861,6 +2861,8 @@ emit_block(struct ir3_context *ctx, nir_block *nblock)
list_addtail(&ctx->block->node, &ctx->ir->block_list); 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: */ /* re-emit addr register in each block if needed: */
for (int i = 0; i < ARRAY_SIZE(ctx->addr0_ht); i++) { for (int i = 0; i < ARRAY_SIZE(ctx->addr0_ht); i++) {
_mesa_hash_table_destroy(ctx->addr0_ht[i], NULL); _mesa_hash_table_destroy(ctx->addr0_ht[i], NULL);
@ -2915,8 +2917,11 @@ emit_if(struct ir3_context *ctx, nir_if *nif)
static void static void
emit_loop(struct ir3_context *ctx, nir_loop *nloop) 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); emit_cf_list(ctx, &nloop->body);
ctx->so->loops++; ctx->so->loops++;
ctx->loop_id = old_loop_id;
} }
static void static void

View File

@ -110,6 +110,8 @@ struct ir3_context {
*/ */
unsigned stack, max_stack; unsigned stack, max_stack;
unsigned loop_id;
/* a common pattern for indirect addressing is to request the /* a common pattern for indirect addressing is to request the
* same address register multiple times. To avoid generating * same address register multiple times. To avoid generating
* duplicate instruction sequences (which our backend does not * duplicate instruction sequences (which our backend does not

View File

@ -310,6 +310,17 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr,
{ {
struct ir3_instruction *src = ssa(reg); 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)) { if (is_eligible_mov(src, instr, true)) {
/* simple case, no immed/const/relativ, only mov's w/ ssa src: */ /* simple case, no immed/const/relativ, only mov's w/ ssa src: */
struct ir3_register *src_reg = src->srcs[0]; struct ir3_register *src_reg = src->srcs[0];