nir/nir_opt_move: handle non-SSA defs

We just skip register defs and avoid moving register reads across them.
This allows us to run this pass in non-SSA form.

Reviewed-by: Daniel Schürmann <daniel@schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15056>
This commit is contained in:
Iago Toral Quiroga 2022-02-18 11:23:32 +01:00 committed by Marge Bot
parent fe2249eac5
commit f1d20ec67c
1 changed files with 25 additions and 0 deletions

View File

@ -51,6 +51,18 @@
* lower register pressure.
*/
static ALWAYS_INLINE bool
src_is_ssa(nir_src *src, void *state)
{
return src->is_ssa;
}
static ALWAYS_INLINE bool
instr_reads_register(nir_instr *instr)
{
return !nir_foreach_src(instr, src_is_ssa, NULL);
}
static bool
nir_opt_move_block(nir_block *block, nir_move_options options)
{
@ -68,9 +80,16 @@ nir_opt_move_block(nir_block *block, nir_move_options options)
* the original order is kept.
*/
unsigned index = 1;
unsigned last_reg_def_index = 0;
nir_foreach_instr_reverse_safe(instr, block) {
instr->index = index++;
/* Don't move register defs */
if (nir_instr_def_is_register(instr)) {
last_reg_def_index = instr->index;
continue;
}
/* Check if this instruction can be moved downwards */
if (!nir_can_move_instr(instr, options))
continue;
@ -95,6 +114,12 @@ nir_opt_move_block(nir_block *block, nir_move_options options)
if (nir_instr_prev(first_user) == instr)
continue;
/* Don't move register reads past register defs */
if (first_user->index < last_reg_def_index &&
instr_reads_register(instr)) {
continue;
}
/* Insert the instruction before it's first user */
exec_node_remove(&instr->node);
instr->index = first_user->index;