From 4fd257d20fed9efdfedc4eefc99b4900841c6f85 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Wed, 19 Jul 2023 11:20:16 -0500 Subject: [PATCH] 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: 7229bffcb133 ("nir: Add intrinsics for register access") Reviewed-by: Alyssa Rosenzweig Part-of: --- src/compiler/nir/nir_builder.h | 6 +++++- src/compiler/nir/nir_divergence_analysis.c | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/compiler/nir/nir_builder.h b/src/compiler/nir/nir_builder.h index 898dbb25133..6602a405add 100644 --- a/src/compiler/nir/nir_builder.h +++ b/src/compiler/nir/nir_builder.h @@ -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 diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index 091050dde4c..9c0f2d2de52 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -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);