diff --git a/src/nouveau/compiler/nak_nir_lower_cf.c b/src/nouveau/compiler/nak_nir_lower_cf.c index b859b1964a9..ec29e715c3b 100644 --- a/src/nouveau/compiler/nak_nir_lower_cf.c +++ b/src/nouveau/compiler/nak_nir_lower_cf.c @@ -498,3 +498,36 @@ nak_nir_lower_cf(nir_shader *nir) return progress; } + +bool +nak_block_is_divergent(const nir_block *block) +{ + const nir_cf_node* node = &block->cf_node; + + while (node) { + switch (node->type) { + case nir_cf_node_if: { + nir_if *nif = nir_cf_node_as_if(node); + if (nir_src_is_divergent(&nif->condition)) + return true; + break; + } + case nir_cf_node_loop: { + nir_loop *loop = nir_cf_node_as_loop(node); + if (nir_loop_is_divergent(loop)) + return true; + break; + } + case nir_cf_node_block: { + nir_block *block = nir_cf_node_as_block(node); + if (block->divergent) + return true; + break; + } + case nir_cf_node_function: + break; + } + node = node->parent; + } + return false; +} diff --git a/src/nouveau/compiler/nak_nir_lower_scan_reduce.c b/src/nouveau/compiler/nak_nir_lower_scan_reduce.c index 700392030b3..38516bc75a2 100644 --- a/src/nouveau/compiler/nak_nir_lower_scan_reduce.c +++ b/src/nouveau/compiler/nak_nir_lower_scan_reduce.c @@ -229,7 +229,7 @@ nak_nir_lower_scan_reduce_intrin(nir_builder *b, nir_op_infos[red_op].output_type != nir_type_float && intrin->src[0].ssa->bit_size == 32 && cluster_size == 32 && - !intrin->instr.block->divergent) { + !nak_block_is_divergent(intrin->instr.block)) { /* TODO: We could probably also use REDUX for the non-uniform case if we * were allowed to write uregs from non-uniform control flow. */ diff --git a/src/nouveau/compiler/nak_private.h b/src/nouveau/compiler/nak_private.h index 13a43bc9fcc..57ec68f7885 100644 --- a/src/nouveau/compiler/nak_private.h +++ b/src/nouveau/compiler/nak_private.h @@ -343,6 +343,16 @@ bool nak_nir_add_barriers(nir_shader *nir, const struct nak_compiler *nak); bool nak_nir_lower_cf(nir_shader *nir); bool nak_nir_lower_cmat(nir_shader *shader, const struct nak_compiler *nak); +/** + * Check if, for nak's purposes, a block is divergent + * + * Note that this differs from block->divergent because in nir's terms, the + * start block of a loop with divergent continues can be non-divergent but nak + * will always consider this divergent. This matters because nak does not allow + * writing uregs from these blocks. + */ +bool nak_block_is_divergent(const nir_block *block); + void nak_optimize_nir(nir_shader *nir, const struct nak_compiler *nak); #ifdef __cplusplus