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>
This commit is contained in:
@@ -1555,7 +1555,6 @@ nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def,
|
|||||||
unsigned bit_size, const char *name)
|
unsigned bit_size, const char *name)
|
||||||
{
|
{
|
||||||
def->name = ralloc_strdup(instr, name);
|
def->name = ralloc_strdup(instr, name);
|
||||||
def->live_index = UINT_MAX; /* Something clearly OOB */
|
|
||||||
def->parent_instr = instr;
|
def->parent_instr = instr;
|
||||||
list_inithead(&def->uses);
|
list_inithead(&def->uses);
|
||||||
list_inithead(&def->if_uses);
|
list_inithead(&def->if_uses);
|
||||||
|
@@ -786,12 +786,6 @@ typedef struct nir_ssa_def {
|
|||||||
/** for debugging only, can be NULL */
|
/** for debugging only, can be NULL */
|
||||||
const char* name;
|
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. */
|
/** Instruction which produces this SSA value. */
|
||||||
nir_instr *parent_instr;
|
nir_instr *parent_instr;
|
||||||
|
|
||||||
@@ -801,6 +795,9 @@ typedef struct nir_ssa_def {
|
|||||||
/** set of nir_ifs where this register is used as a condition */
|
/** set of nir_ifs where this register is used as a condition */
|
||||||
struct list_head if_uses;
|
struct list_head if_uses;
|
||||||
|
|
||||||
|
/** generic SSA definition index. */
|
||||||
|
unsigned index;
|
||||||
|
|
||||||
uint8_t num_components;
|
uint8_t num_components;
|
||||||
|
|
||||||
/* The bit-size of each channel; must be one of 8, 16, 32, or 64 */
|
/* The bit-size of each channel; must be one of 8, 16, 32, or 64 */
|
||||||
@@ -2841,7 +2838,6 @@ typedef enum {
|
|||||||
*
|
*
|
||||||
* This includes:
|
* This includes:
|
||||||
*
|
*
|
||||||
* - nir_ssa_def::live_index
|
|
||||||
* - nir_block::live_in
|
* - nir_block::live_in
|
||||||
* - nir_block::live_out
|
* - nir_block::live_out
|
||||||
*
|
*
|
||||||
|
@@ -44,17 +44,33 @@ struct from_ssa_state {
|
|||||||
bool progress;
|
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 */
|
/* Returns true if a dominates b */
|
||||||
static bool
|
static bool
|
||||||
ssa_def_dominates(nir_ssa_def *a, nir_ssa_def *b)
|
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 */
|
/* SSA undefs always dominate */
|
||||||
return true;
|
return true;
|
||||||
} else if (b->live_index < a->live_index) {
|
} if (def_after(a, b)) {
|
||||||
return false;
|
return false;
|
||||||
} else if (a->parent_instr->block == b->parent_instr->block) {
|
} else if (a->parent_instr->block == b->parent_instr->block) {
|
||||||
return a->live_index <= b->live_index;
|
return def_after(b, a);
|
||||||
} else {
|
} else {
|
||||||
return nir_block_dominates(a->parent_instr->block,
|
return nir_block_dominates(a->parent_instr->block,
|
||||||
b->parent_instr->block);
|
b->parent_instr->block);
|
||||||
@@ -157,7 +173,7 @@ merge_merge_sets(merge_set *a, merge_set *b)
|
|||||||
merge_node *b_node = exec_node_data(merge_node, bn, node);
|
merge_node *b_node = exec_node_data(merge_node, bn, node);
|
||||||
|
|
||||||
if (exec_node_is_tail_sentinel(an) ||
|
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;
|
struct exec_node *next = bn->next;
|
||||||
exec_node_remove(bn);
|
exec_node_remove(bn);
|
||||||
exec_node_insert_node_before(an, bn);
|
exec_node_insert_node_before(an, bn);
|
||||||
@@ -202,7 +218,7 @@ merge_sets_interfere(merge_set *a, merge_set *b)
|
|||||||
merge_node *a_node = exec_node_data(merge_node, an, node);
|
merge_node *a_node = exec_node_data(merge_node, an, node);
|
||||||
merge_node *b_node = exec_node_data(merge_node, bn, 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;
|
current = a_node;
|
||||||
an = an->next;
|
an = an->next;
|
||||||
} else {
|
} else {
|
||||||
@@ -785,7 +801,8 @@ nir_convert_from_ssa_impl(nir_function_impl *impl, bool phi_webs_only)
|
|||||||
nir_metadata_preserve(impl, nir_metadata_block_index |
|
nir_metadata_preserve(impl, nir_metadata_block_index |
|
||||||
nir_metadata_dominance);
|
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_metadata_dominance);
|
||||||
|
|
||||||
nir_foreach_block(block, impl) {
|
nir_foreach_block(block, impl) {
|
||||||
|
@@ -43,7 +43,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct live_ssa_defs_state {
|
struct live_ssa_defs_state {
|
||||||
unsigned num_ssa_defs;
|
|
||||||
unsigned bitset_words;
|
unsigned bitset_words;
|
||||||
|
|
||||||
/* Used in propagate_across_edge() */
|
/* Used in propagate_across_edge() */
|
||||||
@@ -52,19 +51,6 @@ struct live_ssa_defs_state {
|
|||||||
nir_block_worklist worklist;
|
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
|
/* Initialize the liveness data to zero and add the given block to the
|
||||||
* worklist.
|
* worklist.
|
||||||
*/
|
*/
|
||||||
@@ -93,7 +79,7 @@ set_src_live(nir_src *src, void *void_live)
|
|||||||
if (!src->is_ssa)
|
if (!src->is_ssa)
|
||||||
return true;
|
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 */
|
return true; /* undefined variables are never live */
|
||||||
|
|
||||||
BITSET_SET(live, src->ssa->index);
|
BITSET_SET(live, src->ssa->index);
|
||||||
@@ -165,15 +151,10 @@ nir_live_ssa_defs_impl(nir_function_impl *impl)
|
|||||||
};
|
};
|
||||||
state.tmp_live = rzalloc_array(impl, BITSET_WORD, state.bitset_words),
|
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
|
/* Number the instructions so we can do cheap interference tests using the
|
||||||
* instructions. Those are never live, so their liveness information
|
* instruction index.
|
||||||
* can be compacted into a single bit.
|
|
||||||
*/
|
*/
|
||||||
state.num_ssa_defs = 1;
|
nir_metadata_require(impl, nir_metadata_instr_index);
|
||||||
nir_foreach_block(block, impl) {
|
|
||||||
nir_foreach_instr(instr, block)
|
|
||||||
nir_foreach_ssa_def(instr, index_ssa_def, &state);
|
|
||||||
}
|
|
||||||
|
|
||||||
nir_block_worklist_init(&state.worklist, impl->num_blocks, NULL);
|
nir_block_worklist_init(&state.worklist, impl->num_blocks, NULL);
|
||||||
|
|
||||||
@@ -295,10 +276,11 @@ nir_ssa_defs_interfere(nir_ssa_def *a, nir_ssa_def *b)
|
|||||||
* least one isn't dead.
|
* least one isn't dead.
|
||||||
*/
|
*/
|
||||||
return true;
|
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 */
|
/* If either variable is an ssa_undef, then there's no interference */
|
||||||
return false;
|
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);
|
return nir_ssa_def_is_live_at(a, b->parent_instr);
|
||||||
} else {
|
} else {
|
||||||
return nir_ssa_def_is_live_at(b, a->parent_instr);
|
return nir_ssa_def_is_live_at(b, a->parent_instr);
|
||||||
|
Reference in New Issue
Block a user