From d34d2f8fa8afc362dc1656b369eb849486c6fb83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Tue, 3 Sep 2024 13:00:14 +0200 Subject: [PATCH] nir: consider loop invariance in nir_src_is_divergent() By doing so, this function does not require LCSSA form anymore in order to provide correct results. Reviewed-by: Rhys Perry Part-of: --- src/compiler/nir/nir_divergence_analysis.c | 35 +++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index 21269dc7b09..a0454c3970c 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -73,7 +73,40 @@ visit_cf_list(struct exec_list *list, struct divergence_state *state); bool nir_src_is_divergent(nir_src *src) { - return src->ssa->divergent; + if (src->ssa->divergent) + return true; + + nir_cf_node *use_node = nir_src_get_block(src)->cf_node.parent; + nir_cf_node *def_node = src->ssa->parent_instr->block->cf_node.parent; + + /* Short-cut the common case. */ + if (def_node == use_node) + return false; + + /* If the source was computed in a divergent loop, and is not + * loop-invariant, then it must also be considered divergent. + */ + bool loop_invariant = src->ssa->loop_invariant; + while (def_node) { + if (def_node->type == nir_cf_node_loop) { + /* Check whether the use is inside this loop. */ + for (nir_cf_node *node = use_node; node != NULL; node = node->parent) { + if (def_node == node) + return false; + } + + /* Because the use is outside of this loop, it is divergent. */ + if (nir_cf_node_as_loop(def_node)->divergent_break && !loop_invariant) + return true; + + /* For outer loops, consider this variable not loop invariant. */ + loop_invariant = false; + } + + def_node = def_node->parent; + } + + return false; } static inline bool