nir/nir_opt_move: handle non-SSA defs
authorIago Toral Quiroga <itoral@igalia.com>
Fri, 18 Feb 2022 10:23:32 +0000 (11:23 +0100)
committerMarge Bot <emma+marge@anholt.net>
Thu, 24 Feb 2022 11:36:00 +0000 (11:36 +0000)
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>

src/compiler/nir/nir_opt_move.c

index 97baf45..81bcde5 100644 (file)
  * 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;