Mesa (staging/19.2): nir/repair_ssa: Replace the unreachable check with the phi builder

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Sep 23 18:32:12 UTC 2019


Module: Mesa
Branch: staging/19.2
Commit: dc7129777fd3077a8c00ff0d4d7bc0e20dc4f04b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=dc7129777fd3077a8c00ff0d4d7bc0e20dc4f04b

Author: Jason Ekstrand <jason at jlekstrand.net>
Date:   Mon Sep  9 13:38:37 2019 -0500

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 at intel.com>
(cherry picked from commit d63162cff0e0922fc3c2ef5dfd4402004caf141e)

---

 src/compiler/nir/nir_repair_ssa.c | 79 ++++++++++++++++++++++-----------------
 1 file 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;




More information about the mesa-commit mailing list