ir3: Prevent propagating shared regs out of loops
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6752>
This commit is contained in:
parent
394c597b1b
commit
590efd180b
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in New Issue