diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 0d30139e439..801798ad47b 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -3317,6 +3317,22 @@ typedef enum { */ nir_metadata_instr_index = 0x20, + /** Indicates that divergence analysis information is valid. + * + * This includes: + * - nir_def::divergent + * - nir_def::loop_invariant + * - nir_block::divergent + * - nir_loop::divergent_break + * - nir_loop::divergent_continue + * + * A pass can preserve this metadata type if it never adds any instructions or + * moves them across loop breaks, as well as if it only removes instructions. + * CF modifications usually invalidate this metadata. Most passes + * shouldn't preserve this metadata type. + */ + nir_metadata_divergence = 0x40, + /** All control flow metadata * * This includes all metadata preserved by a pass that preserves control flow diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index 66ad5679bad..1a119482f74 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -1448,17 +1448,19 @@ nir_divergence_analysis_impl(nir_function_impl *impl, nir_divergence_options opt visit_cf_list(&impl->body, &state); - nir_metadata_preserve(impl, nir_metadata_all); + /* Unless this pass is called with shader->options->divergence_analysis_options, + * it invalidates nir_metadata_divergence. + */ + nir_metadata_preserve(impl, ~nir_metadata_divergence); } void nir_divergence_analysis(nir_shader *shader) { - shader->info.divergence_analysis_run = true; nir_foreach_function_impl(impl, shader) { - nir_divergence_analysis_impl(impl, - shader->options->divergence_analysis_options); + nir_metadata_require(impl, nir_metadata_divergence); } + shader->info.divergence_analysis_run = true; } /* Compute divergence between vertices of the same primitive. This uses @@ -1484,7 +1486,7 @@ nir_vertex_divergence_analysis(nir_shader *shader) nir_metadata_require(impl, nir_metadata_block_index); state.impl = impl; visit_cf_list(&impl->body, &state); - nir_metadata_preserve(impl, nir_metadata_all); + nir_metadata_preserve(impl, nir_metadata_all & ~nir_metadata_divergence); } } diff --git a/src/compiler/nir/nir_metadata.c b/src/compiler/nir/nir_metadata.c index a9afbee2e9e..2ab2b00659f 100644 --- a/src/compiler/nir/nir_metadata.c +++ b/src/compiler/nir/nir_metadata.c @@ -40,6 +40,9 @@ nir_metadata_require(nir_function_impl *impl, nir_metadata required, ...) nir_calc_dominance_impl(impl); if (NEEDS_UPDATE(nir_metadata_live_defs)) nir_live_defs_impl(impl); + if (NEEDS_UPDATE(nir_metadata_divergence)) + nir_divergence_analysis_impl(impl, + impl->function->shader->options->divergence_analysis_options); if (required & nir_metadata_loop_analysis) { va_list ap; va_start(ap, required);