Module: Mesa
Branch: master
Commit: c730feacc0dea9749d8ff070b2d45fcd0cfeaf51
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=c730feacc0dea9749d8ff070b2d45fcd0cfeaf51

Author: Eric Anholt <[email protected]>
Date:   Wed Jul 22 09:06:48 2020 -0700

nir: Add a call to get a struct describing SSA liveness per instruction.

nir-to-tgsi will use this to release release temporaries for SSA storage
back to ureg's linear register allocation once they're dead.

Reviewed-by: Jason Ekstrand <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3395>

---

 src/compiler/nir/nir.h          | 20 +++++++++++
 src/compiler/nir/nir_liveness.c | 75 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)

diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 250d47f79b4..4238cec4868 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -3477,6 +3477,26 @@ nir_shader_get_entrypoint(nir_shader *shader)
    return func->impl;
 }
 
+typedef struct nir_liveness_bounds {
+   uint32_t start;
+   uint32_t end;
+} nir_liveness_bounds;
+
+typedef struct nir_instr_liveness {
+   /**
+    * nir_instr->index for the start and end of a single live interval for SSA
+    * defs.  ssa values last used by a nir_if condition will have an interval
+    * ending at the first instruction after the last one before the if
+    * condition.
+    *
+    * Indexed by def->index (impl->ssa_alloc elements).
+    */
+   struct nir_liveness_bounds *defs;
+} nir_instr_liveness;
+
+nir_instr_liveness *
+nir_live_ssa_defs_per_instr(nir_function_impl *impl);
+
 nir_shader *nir_shader_create(void *mem_ctx,
                               gl_shader_stage stage,
                               const nir_shader_compiler_options *options,
diff --git a/src/compiler/nir/nir_liveness.c b/src/compiler/nir/nir_liveness.c
index accb418e6e4..8ed6d844ba1 100644
--- a/src/compiler/nir/nir_liveness.c
+++ b/src/compiler/nir/nir_liveness.c
@@ -286,3 +286,78 @@ nir_ssa_defs_interfere(nir_ssa_def *a, nir_ssa_def *b)
       return nir_ssa_def_is_live_at(b, a->parent_instr);
    }
 }
+
+/* Takes an SSA def's defs and uses and expands the live interval to cover
+ * that range.  Control flow effects are handled separately.
+ */
+static bool def_cb(nir_ssa_def *def, void *state)
+{
+   nir_instr_liveness *liveness = state;
+   nir_instr *instr = def->parent_instr;
+   int index = def->index;
+
+   liveness->defs[index].start = MIN2(liveness->defs[index].start, 
instr->index);
+
+   nir_foreach_use(src, def) {
+      liveness->defs[index].end = MAX2(liveness->defs[index].end,
+                                       src->parent_instr->index);
+   }
+
+   return true;
+}
+
+nir_instr_liveness *
+nir_live_ssa_defs_per_instr(nir_function_impl *impl)
+{
+   /* We'll use block-level live_ssa_defs to expand our per-instr ranges for
+    * control flow.
+    */
+   nir_metadata_require(impl,
+                        nir_metadata_block_index |
+                        nir_metadata_instr_index |
+                        nir_metadata_live_ssa_defs);
+
+   /* Make our struct. */
+   nir_instr_liveness *liveness = ralloc(NULL, nir_instr_liveness);
+   liveness->defs = rzalloc_array(liveness, nir_liveness_bounds,
+                                  impl->ssa_alloc);
+
+   /* Set our starts so we can use MIN2() as we accumulate bounds. */
+   for (int i = 0; i < impl->ssa_alloc; i++)
+      liveness->defs->start = ~0;
+
+   unsigned last_instr = 0;
+   nir_foreach_block(block, impl) {
+      unsigned index;
+      BITSET_FOREACH_SET(index, block->live_in, impl->ssa_alloc) {
+         liveness->defs[index].start = MIN2(liveness->defs[index].start,
+                                            last_instr);
+      }
+
+      nir_foreach_instr(instr, block) {
+         nir_foreach_ssa_def(instr, def_cb, liveness);
+
+         last_instr = instr->index;
+      };
+
+      /* track an if src's use.  We need to make sure that our value is live
+       * across the if reference, where we don't have an instr->index
+       * representing the use.  Mark it as live through the next real
+       * instruction.
+       */
+      nir_if *nif = nir_block_get_following_if(block);
+      if (nif) {
+         if (nif->condition.is_ssa) {
+            liveness->defs[nif->condition.ssa->index].end = MAX2(
+               liveness->defs[nif->condition.ssa->index].end,
+               last_instr + 1);
+         }
+      }
+
+      BITSET_FOREACH_SET(index, block->live_out, impl->ssa_alloc) {
+         liveness->defs[index].end = MAX2(liveness->defs[index].end, 
last_instr);
+      }
+   }
+
+   return liveness;
+}

_______________________________________________
mesa-commit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to