nir/lower_vec_to_movs: Convert to use nir_shader_instructions_pass().
[mesa.git] / src / compiler / nir / nir_lower_vec_to_movs.c
index 8c286117d55e8302675f0b3da13dfa689115f052..bec7b1409a511ba4794e9b5eb604aa27e2d6a8e8 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include "nir.h"
+#include "nir_builder.h"
 
 /*
  * Implements a simple pass that lowers vecN instructions to a series of
@@ -140,7 +141,7 @@ try_coalesce(nir_alu_instr *vec, unsigned start_idx)
          return 0;
    }
 
-   if (!list_empty(&vec->src[start_idx].src.ssa->if_uses))
+   if (!list_is_empty(&vec->src[start_idx].src.ssa->if_uses))
       return 0;
 
    if (vec->src[start_idx].src.ssa->parent_instr->type != nir_instr_type_alu)
@@ -210,105 +211,79 @@ try_coalesce(nir_alu_instr *vec, unsigned start_idx)
 }
 
 static bool
-lower_vec_to_movs_block(nir_block *block, nir_function_impl *impl)
+nir_lower_vec_to_movs_instr(nir_builder *b, nir_instr *instr, void *data)
 {
-   bool progress = false;
-   nir_shader *shader = impl->function->shader;
-
-   nir_foreach_instr_safe(instr, block) {
-      if (instr->type != nir_instr_type_alu)
-         continue;
-
-      nir_alu_instr *vec = nir_instr_as_alu(instr);
-
-      switch (vec->op) {
-      case nir_op_vec2:
-      case nir_op_vec3:
-      case nir_op_vec4:
-         break;
-      default:
-         continue; /* The loop */
-      }
-
-      bool vec_had_ssa_dest = vec->dest.dest.is_ssa;
-      if (vec->dest.dest.is_ssa) {
-         /* Since we insert multiple MOVs, we have a register destination. */
-         nir_register *reg = nir_local_reg_create(impl);
-         reg->num_components = vec->dest.dest.ssa.num_components;
-         reg->bit_size = vec->dest.dest.ssa.bit_size;
+   if (instr->type != nir_instr_type_alu)
+      return false;
 
-         nir_ssa_def_rewrite_uses(&vec->dest.dest.ssa, nir_src_for_reg(reg));
+   nir_alu_instr *vec = nir_instr_as_alu(instr);
 
-         nir_instr_rewrite_dest(&vec->instr, &vec->dest.dest,
-                                nir_dest_for_reg(reg));
-      }
+   switch (vec->op) {
+   case nir_op_vec2:
+   case nir_op_vec3:
+   case nir_op_vec4:
+      break;
+   default:
+      return false;
+   }
 
-      unsigned finished_write_mask = 0;
+   bool vec_had_ssa_dest = vec->dest.dest.is_ssa;
+   if (vec->dest.dest.is_ssa) {
+      /* Since we insert multiple MOVs, we have a register destination. */
+      nir_register *reg = nir_local_reg_create(b->impl);
+      reg->num_components = vec->dest.dest.ssa.num_components;
+      reg->bit_size = vec->dest.dest.ssa.bit_size;
 
-      /* First, emit a MOV for all the src channels that are in the
-       * destination reg, in case other values we're populating in the dest
-       * might overwrite them.
-       */
-      for (unsigned i = 0; i < 4; i++) {
-         if (!(vec->dest.write_mask & (1 << i)))
-            continue;
+      nir_ssa_def_rewrite_uses(&vec->dest.dest.ssa, nir_src_for_reg(reg));
 
-         if (src_matches_dest_reg(&vec->dest.dest, &vec->src[i].src)) {
-            finished_write_mask |= insert_mov(vec, i, shader);
-            break;
-         }
-      }
+      nir_instr_rewrite_dest(&vec->instr, &vec->dest.dest,
+                             nir_dest_for_reg(reg));
+   }
 
-      /* Now, emit MOVs for all the other src channels. */
-      for (unsigned i = 0; i < 4; i++) {
-         if (!(vec->dest.write_mask & (1 << i)))
-            continue;
+   unsigned finished_write_mask = 0;
 
-         /* Coalescing moves the register writes from the vec up to the ALU
-          * instruction in the source.  We can only do this if the original
-          * vecN had an SSA destination.
-          */
-         if (vec_had_ssa_dest && !(finished_write_mask & (1 << i)))
-            finished_write_mask |= try_coalesce(vec, i);
+   /* First, emit a MOV for all the src channels that are in the
+    * destination reg, in case other values we're populating in the dest
+    * might overwrite them.
+    */
+   for (unsigned i = 0; i < 4; i++) {
+      if (!(vec->dest.write_mask & (1 << i)))
+         continue;
 
-         if (!(finished_write_mask & (1 << i)))
-            finished_write_mask |= insert_mov(vec, i, shader);
+      if (src_matches_dest_reg(&vec->dest.dest, &vec->src[i].src)) {
+         finished_write_mask |= insert_mov(vec, i, b->shader);
+         break;
       }
-
-      nir_instr_remove(&vec->instr);
-      ralloc_free(vec);
-      progress = true;
    }
 
-   return progress;
-}
+   /* Now, emit MOVs for all the other src channels. */
+   for (unsigned i = 0; i < 4; i++) {
+      if (!(vec->dest.write_mask & (1 << i)))
+         continue;
 
-static bool
-nir_lower_vec_to_movs_impl(nir_function_impl *impl)
-{
-   bool progress = false;
+      /* Coalescing moves the register writes from the vec up to the ALU
+       * instruction in the source.  We can only do this if the original
+       * vecN had an SSA destination.
+       */
+      if (vec_had_ssa_dest && !(finished_write_mask & (1 << i)))
+         finished_write_mask |= try_coalesce(vec, i);
 
-   nir_foreach_block(block, impl) {
-      progress |= lower_vec_to_movs_block(block, impl);
+      if (!(finished_write_mask & (1 << i)))
+         finished_write_mask |= insert_mov(vec, i, b->shader);
    }
 
-   if (progress) {
-      nir_metadata_preserve(impl, nir_metadata_block_index |
-                                  nir_metadata_dominance);
-   }
+   nir_instr_remove(&vec->instr);
+   ralloc_free(vec);
 
-   return progress;
+   return true;
 }
 
 bool
 nir_lower_vec_to_movs(nir_shader *shader)
 {
-   bool progress = false;
-
-   nir_foreach_function(function, shader) {
-      if (function->impl)
-         progress = nir_lower_vec_to_movs_impl(function->impl) || progress;
-   }
-
-   return progress;
+   return nir_shader_instructions_pass(shader,
+                                       nir_lower_vec_to_movs_instr,
+                                       nir_metadata_block_index |
+                                       nir_metadata_dominance,
+                                       NULL);
 }