summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Ekstrand <jason@jlekstrand.net>2019-09-09 13:38:37 -0500
committerJuan A. Suarez Romero <jasuarez@igalia.com>2019-10-02 09:41:27 -0400
commitc94e5e3ee13a7e5657d3074722137e6ff92119d9 (patch)
tree98c624fa55e9180e43f2b45e90c3f8928547ecd6
parentc140c260c18263eb98bae941371af7a8ac82d190 (diff)
downloadmesa-c94e5e3ee13a7e5657d3074722137e6ff92119d9.tar.gz
nir/repair_ssa: Replace the unreachable check with the phi builder
In a3268599f3c9, 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> (cherry picked from commit d63162cff0e0922fc3c2ef5dfd4402004caf141e)
-rw-r--r--src/compiler/nir/nir_repair_ssa.c79
1 files changed, 44 insertions, 35 deletions
diff --git a/src/compiler/nir/nir_repair_ssa.c b/src/compiler/nir/nir_repair_ssa.c
index 757afff490d..8eceadcebb0 100644
--- a/src/compiler/nir/nir_repair_ssa.c
+++ b/src/compiler/nir/nir_repair_ssa.c
@@ -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;