mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2024-11-27 04:04:23 +08:00
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:
parent
29dc1b193a
commit
439e8c42cc
@ -223,6 +223,11 @@ convert_loop_exit_for_ssa(nir_def *def, void *void_state)
|
|||||||
if (all_uses_inside_loop)
|
if (all_uses_inside_loop)
|
||||||
return true;
|
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 */
|
/* Initialize a phi-instruction */
|
||||||
nir_phi_instr *phi = nir_phi_instr_create(state->shader);
|
nir_phi_instr *phi = nir_phi_instr_create(state->shader);
|
||||||
nir_def_init(&phi->instr, &phi->def, def->num_components,
|
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_instr_insert_before_block(state->block_after_loop, &phi->instr);
|
||||||
nir_def *dest = &phi->def;
|
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
|
/* Run through all uses and rewrite those outside the loop to point to
|
||||||
* the phi instead of pointing to the ssa-def.
|
* 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_block_in_cf_node_reverse(block, cf_node) {
|
||||||
nir_foreach_instr(instr, block) {
|
nir_foreach_instr_reverse_safe(instr, block) {
|
||||||
nir_foreach_def(instr, convert_loop_exit_for_ssa, state);
|
nir_foreach_def(instr, convert_loop_exit_for_ssa, state);
|
||||||
|
|
||||||
/* for outer loops, invariant instructions can be variant */
|
/* 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_invariants = false;
|
||||||
state->skip_bool_invariants = false;
|
state->skip_bool_invariants = false;
|
||||||
|
|
||||||
nir_foreach_block_in_cf_node(block, &loop->cf_node) {
|
nir_foreach_block_in_cf_node_reverse(block, &loop->cf_node) {
|
||||||
nir_foreach_instr(instr, block)
|
nir_foreach_instr_reverse_safe(instr, block)
|
||||||
nir_foreach_def(instr, convert_loop_exit_for_ssa, state);
|
nir_foreach_def(instr, convert_loop_exit_for_ssa, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user