nir/trivialize: Trivialize cross-block loads

In order for a register load to be trivial, it cannot be used in any
block other than the one in which it is loaded.  We're not currently
explicitly doing anything to ensure this invariant holds.  It may be
that it holds regardless but I couldn't find any documented reason why
it should so let's explicitly handle that case.  Worst case, the newly
added code does nothing.

Fixes: d313eba94e ("nir: Add pass for trivializing register access")
Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24153>
This commit is contained in:
Faith Ekstrand
2023-07-18 10:17:31 -05:00
committed by Marge Bot
parent f1f05cc7cf
commit f8b69abbd4
+22 -10
View File
@@ -76,10 +76,15 @@ trivialize_load(nir_intrinsic_instr *load)
assert(list_is_singular(&load->dest.ssa.uses));
}
struct trivialize_src_state {
nir_block *block;
BITSET_WORD *trivial_regs;
};
static bool
trivialize_src(nir_src *src, void *trivial_regs_)
trivialize_src(nir_src *src, void *state_)
{
BITSET_WORD *trivial_regs = trivial_regs_;
struct trivialize_src_state *state = state_;
assert(src->is_ssa && "register intrinsics only");
nir_instr *parent = src->ssa->parent_instr;
@@ -91,7 +96,8 @@ trivialize_src(nir_src *src, void *trivial_regs_)
return true;
unsigned reg_index = intr->src[0].ssa->index;
if (!BITSET_TEST(trivial_regs, reg_index))
if (intr->instr.block != state->block ||
!BITSET_TEST(state->trivial_regs, reg_index))
trivialize_load(intr);
return true;
@@ -100,11 +106,17 @@ trivialize_src(nir_src *src, void *trivial_regs_)
static void
trivialize_loads(nir_function_impl *impl, nir_block *block)
{
BITSET_WORD *trivial_regs =
calloc(BITSET_WORDS(impl->ssa_alloc), sizeof(BITSET_WORD));
struct trivialize_src_state state = {
.block = block,
.trivial_regs = calloc(BITSET_WORDS(impl->ssa_alloc),
sizeof(BITSET_WORD)),
};
nir_foreach_instr_safe(instr, block) {
nir_foreach_src(instr, trivialize_src, trivial_regs);
/* Our cross-block serialization can't handle phis */
assert(instr->type != nir_instr_type_phi);
nir_foreach_src(instr, trivialize_src, &state);
/* We maintain a set of registers which can be accessed trivially. When we
* hit a load, the register becomes trivial. When the register is stored,
@@ -118,18 +130,18 @@ trivialize_loads(nir_function_impl *impl, nir_block *block)
if (intr->intrinsic == nir_intrinsic_load_reg_indirect)
trivialize_load(intr);
else if (intr->intrinsic == nir_intrinsic_load_reg)
BITSET_SET(trivial_regs, intr->src[0].ssa->index);
BITSET_SET(state.trivial_regs, intr->src[0].ssa->index);
else if (nir_is_store_reg(intr))
BITSET_CLEAR(trivial_regs, intr->src[1].ssa->index);
BITSET_CLEAR(state.trivial_regs, intr->src[1].ssa->index);
}
}
/* Also check the condition of the next if */
nir_if *nif = nir_block_get_following_if(block);
if (nif)
trivialize_src(&nif->condition, trivial_regs);
trivialize_src(&nif->condition, &state);
free(trivial_regs);
free(state.trivial_regs);
}
/*