nir/lcssa: Fix rematerializing derefs

This would pull derefs out of loops by emitting the pattern
`deref(phi(deref))` which is not allowed by nir_validate.

Reviewed-by: Rhys Perry <pendingchaos02@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23712>
This commit is contained in:
Konstantin Seurer 2023-07-28 17:09:34 +02:00 committed by Marge Bot
parent 29dc1b193a
commit 439e8c42cc

View File

@ -223,6 +223,11 @@ convert_loop_exit_for_ssa(nir_def *def, void *void_state)
if (all_uses_inside_loop)
return true;
if (def->parent_instr->type == nir_instr_type_deref) {
nir_rematerialize_deref_in_use_blocks(nir_instr_as_deref(def->parent_instr));
return true;
}
/* Initialize a phi-instruction */
nir_phi_instr *phi = nir_phi_instr_create(state->shader);
nir_def_init(&phi->instr, &phi->def, def->num_components,
@ -239,23 +244,6 @@ convert_loop_exit_for_ssa(nir_def *def, void *void_state)
nir_instr_insert_before_block(state->block_after_loop, &phi->instr);
nir_def *dest = &phi->def;
/* deref instructions need a cast after the phi */
if (def->parent_instr->type == nir_instr_type_deref) {
nir_deref_instr *cast =
nir_deref_instr_create(state->shader, nir_deref_type_cast);
nir_deref_instr *instr = nir_instr_as_deref(def->parent_instr);
cast->modes = instr->modes;
cast->type = instr->type;
cast->parent = nir_src_for_ssa(&phi->def);
cast->cast.ptr_stride = nir_deref_instr_array_stride(instr);
nir_def_init(&cast->instr, &cast->def,
phi->def.num_components, phi->def.bit_size);
nir_instr_insert(nir_after_phis(state->block_after_loop), &cast->instr);
dest = &cast->def;
}
/* Run through all uses and rewrite those outside the loop to point to
* the phi instead of pointing to the ssa-def.
*/
@ -340,8 +328,8 @@ convert_to_lcssa(nir_cf_node *cf_node, lcssa_state *state)
}
}
nir_foreach_block_in_cf_node(block, cf_node) {
nir_foreach_instr(instr, block) {
nir_foreach_block_in_cf_node_reverse(block, cf_node) {
nir_foreach_instr_reverse_safe(instr, block) {
nir_foreach_def(instr, convert_loop_exit_for_ssa, state);
/* for outer loops, invariant instructions can be variant */
@ -381,8 +369,8 @@ nir_convert_loop_to_lcssa(nir_loop *loop)
state->skip_invariants = false;
state->skip_bool_invariants = false;
nir_foreach_block_in_cf_node(block, &loop->cf_node) {
nir_foreach_instr(instr, block)
nir_foreach_block_in_cf_node_reverse(block, &loop->cf_node) {
nir_foreach_instr_reverse_safe(instr, block)
nir_foreach_def(instr, convert_loop_exit_for_ssa, state);
}