nir: Add a dominance validation pass
We don't do full dominance validation of SSA values in nir_validate because it requires generating valid dominance information and, while that's not extremely expensive, it's probably more than we want to do on every pass. Also, dominance information is generated through the metadata system so if we ran it by default in nir_validate, we would get different beavior of the metadata system based on whether or not you have a debug build and metadata bugs would be very hard to find. However, having a pass for it that can be run occasionally, should help detect and expose bugs. For ease of use, we add a NIR_VALIDATE_SSA_DOMINANCE environment variable which can be set to manually enable dominance validation as a standard part of nir_validate. Reviewed-by: Daniel Schürmann <daniel@schuermann.dev> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5288>
This commit is contained in:

committed by
Marge Bot

parent
6cef804067
commit
45bcb10841
@@ -1206,6 +1206,60 @@ validate_var_decl(nir_variable *var, nir_variable_mode valid_modes,
|
||||
state->var = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_ssa_def_dominance(nir_ssa_def *def, void *_state)
|
||||
{
|
||||
validate_state *state = _state;
|
||||
|
||||
validate_assert(state, def->index < state->impl->ssa_alloc);
|
||||
validate_assert(state, !BITSET_TEST(state->ssa_defs_found, def->index));
|
||||
BITSET_SET(state->ssa_defs_found, def->index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_src_dominance(nir_src *src, void *_state)
|
||||
{
|
||||
validate_state *state = _state;
|
||||
if (!src->is_ssa)
|
||||
return true;
|
||||
|
||||
if (src->ssa->parent_instr->block == src->parent_instr->block) {
|
||||
validate_assert(state, src->ssa->index < state->impl->ssa_alloc);
|
||||
validate_assert(state, BITSET_TEST(state->ssa_defs_found,
|
||||
src->ssa->index));
|
||||
} else {
|
||||
validate_assert(state, nir_block_dominates(src->ssa->parent_instr->block,
|
||||
src->parent_instr->block));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
validate_ssa_dominance(nir_function_impl *impl, validate_state *state)
|
||||
{
|
||||
nir_metadata_require(impl, nir_metadata_dominance);
|
||||
|
||||
nir_foreach_block(block, impl) {
|
||||
state->block = block;
|
||||
nir_foreach_instr(instr, block) {
|
||||
state->instr = instr;
|
||||
if (instr->type == nir_instr_type_phi) {
|
||||
nir_phi_instr *phi = nir_instr_as_phi(instr);
|
||||
nir_foreach_phi_src(src, phi) {
|
||||
validate_assert(state,
|
||||
nir_block_dominates(src->src.ssa->parent_instr->block,
|
||||
src->pred));
|
||||
}
|
||||
} else {
|
||||
nir_foreach_src(instr, validate_src_dominance, state);
|
||||
}
|
||||
nir_foreach_ssa_def(instr, validate_ssa_def_dominance, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
validate_function_impl(nir_function_impl *impl, validate_state *state)
|
||||
{
|
||||
@@ -1257,6 +1311,14 @@ validate_function_impl(nir_function_impl *impl, validate_state *state)
|
||||
|
||||
validate_assert(state, state->ssa_srcs->entries == 0);
|
||||
_mesa_set_clear(state->ssa_srcs, NULL);
|
||||
|
||||
static int validate_dominance = -1;
|
||||
if (validate_dominance < 0) {
|
||||
validate_dominance =
|
||||
env_var_as_boolean("NIR_VALIDATE_SSA_DOMINANCE", false);
|
||||
}
|
||||
if (validate_dominance)
|
||||
validate_ssa_dominance(impl, state);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1365,4 +1427,38 @@ nir_validate_shader(nir_shader *shader, const char *when)
|
||||
destroy_validate_state(&state);
|
||||
}
|
||||
|
||||
void
|
||||
nir_validate_ssa_dominance(nir_shader *shader, const char *when)
|
||||
{
|
||||
static int should_validate = -1;
|
||||
if (should_validate < 0)
|
||||
should_validate = env_var_as_boolean("NIR_VALIDATE", true);
|
||||
if (!should_validate)
|
||||
return;
|
||||
|
||||
validate_state state;
|
||||
init_validate_state(&state);
|
||||
|
||||
state.shader = shader;
|
||||
|
||||
nir_foreach_function(func, shader) {
|
||||
if (func->impl == NULL)
|
||||
continue;
|
||||
|
||||
state.ssa_defs_found = reralloc(state.mem_ctx, state.ssa_defs_found,
|
||||
BITSET_WORD,
|
||||
BITSET_WORDS(func->impl->ssa_alloc));
|
||||
memset(state.ssa_defs_found, 0, BITSET_WORDS(func->impl->ssa_alloc) *
|
||||
sizeof(BITSET_WORD));
|
||||
|
||||
state.impl = func->impl;
|
||||
validate_ssa_dominance(func->impl, &state);
|
||||
}
|
||||
|
||||
if (_mesa_hash_table_num_entries(state.errors) > 0)
|
||||
dump_errors(&state, when);
|
||||
|
||||
destroy_validate_state(&state);
|
||||
}
|
||||
|
||||
#endif /* NDEBUG */
|
||||
|
Reference in New Issue
Block a user