mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-30 18:40:13 +01:00
nir/trivialize_registers: Handle obscure load hazard
Somebody less tired than me would add a unit test for this. Offending snippet:
32 %58 = @load_reg (%55) (base=0, legacy_fabs=0, legacy_fneg=0)
32 %57 = @load_reg (%55) (base=0, legacy_fabs=0, legacy_fneg=0)
32 %21 = iadd %57, %15 (0x1)
@store_reg (%21, %55) (base=0, wrmask=x, legacy_fsat=0)
32 %56 = @load_reg (%55) (base=0, legacy_fabs=0, legacy_fneg=0)
32 %22 = i2f32 %56
32 %23 = load_const (0x41000000 = 8.000000)
32 %24 = fdiv %22, %23 (8.000000)
32 %90 = mov %24
@store_reg_indirect (%90, %78, %58) (base=0, wrmask=x, legacy_fsat=0)
Closes: #10031
Fixes: d313eba94e ("nir: Add pass for trivializing register access")
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reported-by: Timothy Arceri <tarceri@itsqueeze.com>
Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25865>
This commit is contained in:
parent
6aef22af77
commit
9a6c20e64f
1 changed files with 33 additions and 15 deletions
|
|
@ -108,7 +108,7 @@ trivialize_load(nir_intrinsic_instr *load)
|
|||
|
||||
struct trivialize_src_state {
|
||||
nir_block *block;
|
||||
BITSET_WORD *trivial_regs;
|
||||
BITSET_WORD *trivial_loads;
|
||||
};
|
||||
|
||||
static bool
|
||||
|
|
@ -124,9 +124,8 @@ trivialize_src(nir_src *src, void *state_)
|
|||
if (!nir_is_load_reg(intr))
|
||||
return true;
|
||||
|
||||
unsigned reg_index = intr->src[0].ssa->index;
|
||||
if (intr->instr.block != state->block ||
|
||||
!BITSET_TEST(state->trivial_regs, reg_index))
|
||||
!BITSET_TEST(state->trivial_loads, intr->def.index))
|
||||
trivialize_load(intr);
|
||||
|
||||
return true;
|
||||
|
|
@ -137,8 +136,8 @@ trivialize_loads(nir_function_impl *impl, nir_block *block)
|
|||
{
|
||||
struct trivialize_src_state state = {
|
||||
.block = block,
|
||||
.trivial_regs = calloc(BITSET_WORDS(impl->ssa_alloc),
|
||||
sizeof(BITSET_WORD)),
|
||||
.trivial_loads = calloc(BITSET_WORDS(impl->ssa_alloc),
|
||||
sizeof(BITSET_WORD)),
|
||||
};
|
||||
|
||||
nir_foreach_instr_safe(instr, block) {
|
||||
|
|
@ -147,21 +146,40 @@ trivialize_loads(nir_function_impl *impl, nir_block *block)
|
|||
|
||||
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,
|
||||
* the register becomes nontrivial again. That means the window between
|
||||
* the load and the store is where the register can be accessed legally.
|
||||
/* We maintain a set of register loads which can be accessed trivially.
|
||||
* When we hit a load, it is added to the trivial set. When the register
|
||||
* is stored, all loads from the register become nontrivial. That means
|
||||
* the window between the load and the store is where the register can be
|
||||
* accessed legally.
|
||||
*
|
||||
* Note that we must track loads and not registers to correctly handle
|
||||
* cases like:
|
||||
*
|
||||
* %1 = @load_reg %0
|
||||
* %2 = @load_reg %0
|
||||
* @store_reg data, %0
|
||||
* use %1
|
||||
*
|
||||
* This is pretty obscure but it isn't a big deal to handle.
|
||||
*/
|
||||
if (instr->type == nir_instr_type_intrinsic) {
|
||||
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
||||
|
||||
/* We don't consider indirect loads to ever be trivial */
|
||||
if (intr->intrinsic == nir_intrinsic_load_reg_indirect)
|
||||
if (intr->intrinsic == nir_intrinsic_load_reg_indirect) {
|
||||
trivialize_load(intr);
|
||||
else if (intr->intrinsic == nir_intrinsic_load_reg)
|
||||
BITSET_SET(state.trivial_regs, intr->src[0].ssa->index);
|
||||
else if (nir_is_store_reg(intr))
|
||||
BITSET_CLEAR(state.trivial_regs, intr->src[1].ssa->index);
|
||||
} else if (intr->intrinsic == nir_intrinsic_load_reg) {
|
||||
BITSET_SET(state.trivial_loads, intr->def.index);
|
||||
} else if (nir_is_store_reg(intr)) {
|
||||
nir_intrinsic_instr *reg = nir_reg_get_decl(intr->src[1].ssa);
|
||||
|
||||
nir_foreach_reg_load(load, reg) {
|
||||
nir_instr *parent = nir_src_parent_instr(load);
|
||||
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(parent);
|
||||
|
||||
BITSET_CLEAR(state.trivial_loads, intr->def.index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +188,7 @@ trivialize_loads(nir_function_impl *impl, nir_block *block)
|
|||
if (nif)
|
||||
trivialize_src(&nif->condition, &state);
|
||||
|
||||
free(state.trivial_regs);
|
||||
free(state.trivial_loads);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue