mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-27 14:50:10 +01:00
nir/repair_ssa: Replace the unreachable check with the phi builder
Ina3268599f3, I attempted to fix nir_repair_ssa for unreachable blocks. However, that commit missed the possibility that the use is in a block which, itself, is unreachable. In this case, we can end up in an infinite loop trying to replace a def with itself. Even though a no-op replacement is a fine operation, it keeps extending the end of the uses list as we're walking it. Instead of explicitly checking for the group of conditions, just check if the phi builder gives us a different def. That's guaranteed to be 100% reliable and, while it lacks symmetry with the is_valid checks, should be more reliable. Fixes:a3268599"nir/repair_ssa: Repair dominance for unreachable..." Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
parent
2c050b49b3
commit
d63162cff0
1 changed files with 44 additions and 35 deletions
|
|
@ -103,48 +103,57 @@ repair_ssa_def(nir_ssa_def *def, void *void_state)
|
|||
|
||||
nir_foreach_use_safe(src, def) {
|
||||
nir_block *src_block = get_src_block(src);
|
||||
if (nir_block_is_unreachable(src_block) ||
|
||||
!nir_block_dominates(def->parent_instr->block, src_block)) {
|
||||
nir_ssa_def *block_def =
|
||||
nir_phi_builder_value_get_block_def(val, src_block);
|
||||
|
||||
/* If def was a deref and the use we're looking at is a deref that
|
||||
* isn't a cast, we need to wrap it in a cast so we don't loose any
|
||||
* deref information.
|
||||
*/
|
||||
if (def->parent_instr->type == nir_instr_type_deref &&
|
||||
src->parent_instr->type == nir_instr_type_deref &&
|
||||
nir_instr_as_deref(src->parent_instr)->deref_type != nir_deref_type_cast) {
|
||||
nir_deref_instr *cast =
|
||||
nir_deref_instr_create(state->impl->function->shader,
|
||||
nir_deref_type_cast);
|
||||
|
||||
nir_deref_instr *deref = nir_instr_as_deref(def->parent_instr);
|
||||
cast->mode = deref->mode;
|
||||
cast->type = deref->type;
|
||||
cast->parent = nir_src_for_ssa(block_def);
|
||||
cast->cast.ptr_stride = nir_deref_instr_ptr_as_array_stride(deref);
|
||||
|
||||
nir_ssa_dest_init(&cast->instr, &cast->dest,
|
||||
def->num_components, def->bit_size, NULL);
|
||||
nir_instr_insert(nir_before_instr(src->parent_instr),
|
||||
&cast->instr);
|
||||
block_def = &cast->dest.ssa;
|
||||
}
|
||||
|
||||
nir_instr_rewrite_src(src->parent_instr, src,
|
||||
nir_src_for_ssa(block_def));
|
||||
if (src_block == def->parent_instr->block) {
|
||||
assert(nir_phi_builder_value_get_block_def(val, src_block) == def);
|
||||
continue;
|
||||
}
|
||||
|
||||
nir_ssa_def *block_def =
|
||||
nir_phi_builder_value_get_block_def(val, src_block);
|
||||
if (block_def == def)
|
||||
continue;
|
||||
|
||||
/* If def was a deref and the use we're looking at is a deref that
|
||||
* isn't a cast, we need to wrap it in a cast so we don't loose any
|
||||
* deref information.
|
||||
*/
|
||||
if (def->parent_instr->type == nir_instr_type_deref &&
|
||||
src->parent_instr->type == nir_instr_type_deref &&
|
||||
nir_instr_as_deref(src->parent_instr)->deref_type != nir_deref_type_cast) {
|
||||
nir_deref_instr *cast =
|
||||
nir_deref_instr_create(state->impl->function->shader,
|
||||
nir_deref_type_cast);
|
||||
|
||||
nir_deref_instr *deref = nir_instr_as_deref(def->parent_instr);
|
||||
cast->mode = deref->mode;
|
||||
cast->type = deref->type;
|
||||
cast->parent = nir_src_for_ssa(block_def);
|
||||
cast->cast.ptr_stride = nir_deref_instr_ptr_as_array_stride(deref);
|
||||
|
||||
nir_ssa_dest_init(&cast->instr, &cast->dest,
|
||||
def->num_components, def->bit_size, NULL);
|
||||
nir_instr_insert(nir_before_instr(src->parent_instr),
|
||||
&cast->instr);
|
||||
block_def = &cast->dest.ssa;
|
||||
}
|
||||
|
||||
nir_instr_rewrite_src(src->parent_instr, src, nir_src_for_ssa(block_def));
|
||||
}
|
||||
|
||||
nir_foreach_if_use_safe(src, def) {
|
||||
nir_block *block_before_if =
|
||||
nir_cf_node_as_block(nir_cf_node_prev(&src->parent_if->cf_node));
|
||||
if (nir_block_is_unreachable(block_before_if) ||
|
||||
!nir_block_dominates(def->parent_instr->block, block_before_if)) {
|
||||
nir_if_rewrite_condition(src->parent_if, nir_src_for_ssa(
|
||||
nir_phi_builder_value_get_block_def(val, block_before_if)));
|
||||
if (block_before_if == def->parent_instr->block) {
|
||||
assert(nir_phi_builder_value_get_block_def(val, block_before_if) == def);
|
||||
continue;
|
||||
}
|
||||
|
||||
nir_ssa_def *block_def =
|
||||
nir_phi_builder_value_get_block_def(val, block_before_if);
|
||||
if (block_def == def)
|
||||
continue;
|
||||
|
||||
nir_if_rewrite_condition(src->parent_if, nir_src_for_ssa(block_def));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue