nir: Switch the indexing of block->live_in/out arrays.
In nir-to-tgsi, I want to free temps storing SSA values when they go dead, and NIR liveness has most of the information I need. Hoever, when I reach the end of a block, I need to free whatever temps were in liveout which are dead at that point. If liveout is indexed by live_index, then I don't know the maximum live_index for iterating the live_out bitset, and I also don't have a way to map that index back to the def->index that my temps are stored under. We can use the more typical def->index for these bitsets, which resolves both of those problems. The only cost is that ssa_undefs don't get merged into a single bit in the bitfield, but there are generally 1-4 of them in a shader and we don't track liveness for those anyway so splitting them apart is fine. Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6408>
This commit is contained in:
@@ -1847,6 +1847,8 @@ nir_index_ssa_defs(nir_function_impl *impl)
|
|||||||
{
|
{
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
|
|
||||||
|
impl->valid_metadata &= ~nir_metadata_live_ssa_defs;
|
||||||
|
|
||||||
nir_foreach_block_unstructured(block, impl) {
|
nir_foreach_block_unstructured(block, impl) {
|
||||||
nir_foreach_instr(instr, block)
|
nir_foreach_instr(instr, block)
|
||||||
nir_foreach_ssa_def(instr, index_ssa_def_cb, &index);
|
nir_foreach_ssa_def(instr, index_ssa_def_cb, &index);
|
||||||
|
@@ -768,7 +768,7 @@ typedef struct nir_ssa_def {
|
|||||||
/** generic SSA definition index. */
|
/** generic SSA definition index. */
|
||||||
unsigned index;
|
unsigned index;
|
||||||
|
|
||||||
/** Index into the live_in and live_out bitfields */
|
/** Ordered SSA definition index used by nir_liveness. */
|
||||||
unsigned live_index;
|
unsigned live_index;
|
||||||
|
|
||||||
/** Instruction which produces this SSA value. */
|
/** Instruction which produces this SSA value. */
|
||||||
@@ -2603,7 +2603,9 @@ typedef struct nir_block {
|
|||||||
*/
|
*/
|
||||||
int16_t dom_pre_index, dom_post_index;
|
int16_t dom_pre_index, dom_post_index;
|
||||||
|
|
||||||
/* live in and out for this block; used for liveness analysis */
|
/* SSA def live in and out for this block; used for liveness analysis.
|
||||||
|
* Indexed by ssa_def->index
|
||||||
|
*/
|
||||||
BITSET_WORD *live_in;
|
BITSET_WORD *live_in;
|
||||||
BITSET_WORD *live_out;
|
BITSET_WORD *live_out;
|
||||||
} nir_block;
|
} nir_block;
|
||||||
|
@@ -96,7 +96,7 @@ set_src_live(nir_src *src, void *void_live)
|
|||||||
if (src->ssa->live_index == 0)
|
if (src->ssa->live_index == 0)
|
||||||
return true; /* undefined variables are never live */
|
return true; /* undefined variables are never live */
|
||||||
|
|
||||||
BITSET_SET(live, src->ssa->live_index);
|
BITSET_SET(live, src->ssa->index);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ set_ssa_def_dead(nir_ssa_def *def, void *void_live)
|
|||||||
{
|
{
|
||||||
BITSET_WORD *live = void_live;
|
BITSET_WORD *live = void_live;
|
||||||
|
|
||||||
BITSET_CLEAR(live, def->live_index);
|
BITSET_CLEAR(live, def->index);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,10 @@ propagate_across_edge(nir_block *pred, nir_block *succ,
|
|||||||
void
|
void
|
||||||
nir_live_ssa_defs_impl(nir_function_impl *impl)
|
nir_live_ssa_defs_impl(nir_function_impl *impl)
|
||||||
{
|
{
|
||||||
struct live_ssa_defs_state state;
|
struct live_ssa_defs_state state = {
|
||||||
|
.bitset_words = BITSET_WORDS(impl->ssa_alloc),
|
||||||
|
};
|
||||||
|
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
|
/* We start at 1 because we reserve the index value of 0 for ssa_undef
|
||||||
* instructions. Those are never live, so their liveness information
|
* instructions. Those are never live, so their liveness information
|
||||||
@@ -174,12 +177,9 @@ nir_live_ssa_defs_impl(nir_function_impl *impl)
|
|||||||
|
|
||||||
nir_block_worklist_init(&state.worklist, impl->num_blocks, NULL);
|
nir_block_worklist_init(&state.worklist, impl->num_blocks, NULL);
|
||||||
|
|
||||||
/* We now know how many unique ssa definitions we have and we can go
|
/* Allocate live_in and live_out sets and add all of the blocks to the
|
||||||
* ahead and allocate live_in and live_out sets and add all of the
|
* worklist.
|
||||||
* blocks to the worklist.
|
|
||||||
*/
|
*/
|
||||||
state.bitset_words = BITSET_WORDS(state.num_ssa_defs);
|
|
||||||
state.tmp_live = rzalloc_array(impl, BITSET_WORD, state.bitset_words);
|
|
||||||
nir_foreach_block(block, impl) {
|
nir_foreach_block(block, impl) {
|
||||||
init_liveness_block(block, &state);
|
init_liveness_block(block, &state);
|
||||||
}
|
}
|
||||||
@@ -259,13 +259,13 @@ search_for_use_after_instr(nir_instr *start, nir_ssa_def *def)
|
|||||||
static bool
|
static bool
|
||||||
nir_ssa_def_is_live_at(nir_ssa_def *def, nir_instr *instr)
|
nir_ssa_def_is_live_at(nir_ssa_def *def, nir_instr *instr)
|
||||||
{
|
{
|
||||||
if (BITSET_TEST(instr->block->live_out, def->live_index)) {
|
if (BITSET_TEST(instr->block->live_out, def->index)) {
|
||||||
/* Since def dominates instr, if def is in the liveout of the block,
|
/* Since def dominates instr, if def is in the liveout of the block,
|
||||||
* it's live at instr
|
* it's live at instr
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (BITSET_TEST(instr->block->live_in, def->live_index) ||
|
if (BITSET_TEST(instr->block->live_in, def->index) ||
|
||||||
def->parent_instr->block == instr->block) {
|
def->parent_instr->block == instr->block) {
|
||||||
/* In this case it is either live coming into instr's block or it
|
/* In this case it is either live coming into instr's block or it
|
||||||
* is defined in the same block. In this case, we simply need to
|
* is defined in the same block. In this case, we simply need to
|
||||||
|
Reference in New Issue
Block a user