nir: Replace nir_ssa_def->live_index with nir_instr->index.
live_index had two things going on: 0 meant the instr was an undef and
always dead, and otherwise ssa defs had increasing numbers by instruction
order. We already have a field in the instruction for storing instruction
order, and ssa defs don't need that number to be contiguous (if you want a
compact per-ssa-def number, use ssa->index after reindexing).
We don't use ssa->index for this, because reindexing those would change
nir_print, and that would be rude to people trying to track what's
happening in optimization passes.
This openend up a hole in nir_ssa_def, so we move nir_ssa_def->index
toward the end to shrink the struct from 64 bytes to 56.
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3395>
diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c
index 032dbcb..b3a5384 100644
--- a/src/compiler/nir/nir.c
+++ b/src/compiler/nir/nir.c
@@ -1555,7 +1555,6 @@
unsigned bit_size, const char *name)
{
def->name = ralloc_strdup(instr, name);
- def->live_index = UINT_MAX; /* Something clearly OOB */
def->parent_instr = instr;
list_inithead(&def->uses);
list_inithead(&def->if_uses);
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index b480e69..70eed79 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -786,12 +786,6 @@
/** for debugging only, can be NULL */
const char* name;
- /** generic SSA definition index. */
- unsigned index;
-
- /** Ordered SSA definition index used by nir_liveness. */
- unsigned live_index;
-
/** Instruction which produces this SSA value. */
nir_instr *parent_instr;
@@ -801,6 +795,9 @@
/** set of nir_ifs where this register is used as a condition */
struct list_head if_uses;
+ /** generic SSA definition index. */
+ unsigned index;
+
uint8_t num_components;
/* The bit-size of each channel; must be one of 8, 16, 32, or 64 */
@@ -2841,7 +2838,6 @@
*
* This includes:
*
- * - nir_ssa_def::live_index
* - nir_block::live_in
* - nir_block::live_out
*
diff --git a/src/compiler/nir/nir_from_ssa.c b/src/compiler/nir/nir_from_ssa.c
index 52c3a2c..fcaf156 100644
--- a/src/compiler/nir/nir_from_ssa.c
+++ b/src/compiler/nir/nir_from_ssa.c
@@ -44,17 +44,33 @@
bool progress;
};
+/* Returns if def @a comes after def @b.
+ *
+ * We treat SSA undefs as always coming before other instruction types.
+ */
+static bool
+def_after(nir_ssa_def *a, nir_ssa_def *b)
+{
+ if (a->parent_instr->type == nir_instr_type_ssa_undef)
+ return false;
+
+ if (b->parent_instr->type == nir_instr_type_ssa_undef)
+ return true;
+
+ return a->parent_instr->index > b->parent_instr->index;
+}
+
/* Returns true if a dominates b */
static bool
ssa_def_dominates(nir_ssa_def *a, nir_ssa_def *b)
{
- if (a->live_index == 0) {
+ if (a->parent_instr->type == nir_instr_type_ssa_undef) {
/* SSA undefs always dominate */
return true;
- } else if (b->live_index < a->live_index) {
+ } if (def_after(a, b)) {
return false;
} else if (a->parent_instr->block == b->parent_instr->block) {
- return a->live_index <= b->live_index;
+ return def_after(b, a);
} else {
return nir_block_dominates(a->parent_instr->block,
b->parent_instr->block);
@@ -157,7 +173,7 @@
merge_node *b_node = exec_node_data(merge_node, bn, node);
if (exec_node_is_tail_sentinel(an) ||
- a_node->def->live_index > b_node->def->live_index) {
+ def_after(a_node->def, b_node->def)) {
struct exec_node *next = bn->next;
exec_node_remove(bn);
exec_node_insert_node_before(an, bn);
@@ -202,7 +218,7 @@
merge_node *a_node = exec_node_data(merge_node, an, node);
merge_node *b_node = exec_node_data(merge_node, bn, node);
- if (a_node->def->live_index <= b_node->def->live_index) {
+ if (def_after(b_node->def, a_node->def)) {
current = a_node;
an = an->next;
} else {
@@ -785,7 +801,8 @@
nir_metadata_preserve(impl, nir_metadata_block_index |
nir_metadata_dominance);
- nir_metadata_require(impl, nir_metadata_live_ssa_defs |
+ nir_metadata_require(impl, nir_metadata_instr_index |
+ nir_metadata_live_ssa_defs |
nir_metadata_dominance);
nir_foreach_block(block, impl) {
diff --git a/src/compiler/nir/nir_liveness.c b/src/compiler/nir/nir_liveness.c
index 9b9df10..accb418 100644
--- a/src/compiler/nir/nir_liveness.c
+++ b/src/compiler/nir/nir_liveness.c
@@ -43,7 +43,6 @@
*/
struct live_ssa_defs_state {
- unsigned num_ssa_defs;
unsigned bitset_words;
/* Used in propagate_across_edge() */
@@ -52,19 +51,6 @@
nir_block_worklist worklist;
};
-static bool
-index_ssa_def(nir_ssa_def *def, void *void_state)
-{
- struct live_ssa_defs_state *state = void_state;
-
- if (def->parent_instr->type == nir_instr_type_ssa_undef)
- def->live_index = 0;
- else
- def->live_index = state->num_ssa_defs++;
-
- return true;
-}
-
/* Initialize the liveness data to zero and add the given block to the
* worklist.
*/
@@ -93,7 +79,7 @@
if (!src->is_ssa)
return true;
- if (src->ssa->live_index == 0)
+ if (src->ssa->parent_instr->type == nir_instr_type_ssa_undef)
return true; /* undefined variables are never live */
BITSET_SET(live, src->ssa->index);
@@ -165,15 +151,10 @@
};
state.tmp_live = rzalloc_array(impl, BITSET_WORD, state.bitset_words),
- /* We start at 1 because we reserve the index value of 0 for ssa_undef
- * instructions. Those are never live, so their liveness information
- * can be compacted into a single bit.
+ /* Number the instructions so we can do cheap interference tests using the
+ * instruction index.
*/
- state.num_ssa_defs = 1;
- nir_foreach_block(block, impl) {
- nir_foreach_instr(instr, block)
- nir_foreach_ssa_def(instr, index_ssa_def, &state);
- }
+ nir_metadata_require(impl, nir_metadata_instr_index);
nir_block_worklist_init(&state.worklist, impl->num_blocks, NULL);
@@ -295,10 +276,11 @@
* least one isn't dead.
*/
return true;
- } else if (a->live_index == 0 || b->live_index == 0) {
+ } else if (a->parent_instr->type == nir_instr_type_ssa_undef ||
+ b->parent_instr->type == nir_instr_type_ssa_undef) {
/* If either variable is an ssa_undef, then there's no interference */
return false;
- } else if (a->live_index < b->live_index) {
+ } else if (a->parent_instr->index < b->parent_instr->index) {
return nir_ssa_def_is_live_at(a, b->parent_instr);
} else {
return nir_ssa_def_is_live_at(b, a->parent_instr);