nir: Properly handle divergence for load_reg

This commit makes three changes:

 1. Default all newly created registers divergent because this is the
    safer default.

 2. Make divergence analysis do something sane with register divergence.
    It's not perfect because divergence analysis isn't able to prove
    registers divergent based on stores but at least if someone uses
    registers a bit they'll end up with safe defaults.  This matches
    what they'd get with nir_ssa_def_init().

 3. Make the load_reg() helper automatically propagate divergence from
    the register.  Because the defaults for both nir_ssa_def_init() and
    nir_decl_reg() are to mark everything divergent, this only means
    that nir_load_reg() of a uniform reg is now uniform.

Putting all these together, nir_from_ssa should now be producing
load_reg intrinsics with the proper uniform information.

Fixes: 7229bffcb1 ("nir: Add intrinsics for register access")
Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24153>
This commit is contained in:
Faith Ekstrand 2023-07-19 11:20:16 -05:00 committed by Marge Bot
parent 91c3ee2412
commit 4fd257d20f
2 changed files with 14 additions and 1 deletions

View file

@ -1697,6 +1697,7 @@ nir_decl_reg(nir_builder *b, unsigned num_components, unsigned bit_size,
nir_intrinsic_set_num_components(decl, num_components);
nir_intrinsic_set_bit_size(decl, bit_size);
nir_intrinsic_set_num_array_elems(decl, num_array_elems);
nir_intrinsic_set_divergent(decl, true);
nir_ssa_dest_init(&decl->instr, &decl->dest, 1, 32);
nir_instr_insert(nir_before_cf_list(&b->impl->body), &decl->instr);
@ -1712,7 +1713,10 @@ nir_load_reg(nir_builder *b, nir_ssa_def *reg)
unsigned num_components = nir_intrinsic_num_components(decl);
unsigned bit_size = nir_intrinsic_bit_size(decl);
return nir_build_load_reg(b, num_components, bit_size, reg);
nir_ssa_def *res = nir_build_load_reg(b, num_components, bit_size, reg);
res->divergent = nir_intrinsic_divergent(decl);
return res;
}
#undef nir_store_reg

View file

@ -218,6 +218,15 @@ visit_intrinsic(nir_shader *shader, nir_intrinsic_instr *instr)
is_divergent = false;
break;
case nir_intrinsic_load_reg:
case nir_intrinsic_load_reg_indirect: {
nir_intrinsic_instr *decl = nir_reg_get_decl(instr->src[0].ssa);
is_divergent = nir_intrinsic_divergent(decl);
if (instr->intrinsic == nir_intrinsic_load_reg_indirect)
is_divergent |= instr->src[1].ssa->divergent;
break;
}
/* Intrinsics with divergence depending on shader stage and hardware */
case nir_intrinsic_load_shader_record_ptr:
is_divergent = !(options & nir_divergence_shader_record_ptr_uniform);