nir: Report progress properly in nir_lower_bool_to_*
[mesa.git] / src / compiler / nir / nir_lower_vec_to_movs.c
index f51cede3920c72d651fea849610ee2ae51a5708d..64b3fb4b4216c274e2ce9673ef50b93e7be102f3 100644 (file)
  * moves with partial writes.
  */
 
-struct vec_to_movs_state {
-   nir_function_impl *impl;
-   bool progress;
-};
-
 static bool
 src_matches_dest_reg(nir_dest *dest, nir_src *src)
 {
@@ -62,7 +57,7 @@ insert_mov(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader)
 {
    assert(start_idx < nir_op_infos[vec->op].num_inputs);
 
-   nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_imov);
+   nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_mov);
    nir_alu_src_copy(&mov->src[0], &vec->src[start_idx], mov);
    nir_alu_dest_copy(&mov->dest, &vec->dest, mov);
 
@@ -123,7 +118,7 @@ has_replicated_dest(nir_alu_instr *alu)
  * can then call insert_mov as normal.
  */
 static unsigned
-try_coalesce(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader)
+try_coalesce(nir_alu_instr *vec, unsigned start_idx)
 {
    assert(start_idx < nir_op_infos[vec->op].num_inputs);
 
@@ -136,7 +131,7 @@ try_coalesce(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader)
    /* If we are going to do a reswizzle, then the vecN operation must be the
     * only use of the source value.  We also can't have any source modifiers.
     */
-   nir_foreach_use(vec->src[start_idx].src.ssa, src) {
+   nir_foreach_use(src, vec->src[start_idx].src.ssa) {
       if (src->parent_instr != &vec->instr)
          return 0;
 
@@ -145,7 +140,7 @@ try_coalesce(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader)
          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)
@@ -215,13 +210,12 @@ try_coalesce(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader)
 }
 
 static bool
-lower_vec_to_movs_block(nir_block *block, void *void_state)
+lower_vec_to_movs_block(nir_block *block, nir_function_impl *impl)
 {
-   struct vec_to_movs_state *state = void_state;
-   nir_function_impl *impl = state->impl;
+   bool progress = false;
    nir_shader *shader = impl->function->shader;
 
-   nir_foreach_instr_safe(block, instr) {
+   nir_foreach_instr_safe(instr, block) {
       if (instr->type != nir_instr_type_alu)
          continue;
 
@@ -236,10 +230,12 @@ lower_vec_to_movs_block(nir_block *block, void *void_state)
          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;
 
          nir_ssa_def_rewrite_uses(&vec->dest.dest.ssa, nir_src_for_reg(reg));
 
@@ -268,8 +264,12 @@ lower_vec_to_movs_block(nir_block *block, void *void_state)
          if (!(vec->dest.write_mask & (1 << i)))
             continue;
 
-         if (!(finished_write_mask & (1 << i)))
-            finished_write_mask |= try_coalesce(vec, i, shader);
+         /* 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);
 
          if (!(finished_write_mask & (1 << i)))
             finished_write_mask |= insert_mov(vec, i, shader);
@@ -277,25 +277,29 @@ lower_vec_to_movs_block(nir_block *block, void *void_state)
 
       nir_instr_remove(&vec->instr);
       ralloc_free(vec);
-      state->progress = true;
+      progress = true;
    }
 
-   return true;
+   return progress;
 }
 
 static bool
 nir_lower_vec_to_movs_impl(nir_function_impl *impl)
 {
-   struct vec_to_movs_state state = { impl, false };
+   bool progress = false;
 
-   nir_foreach_block(impl, lower_vec_to_movs_block, &state);
+   nir_foreach_block(block, impl) {
+      progress |= lower_vec_to_movs_block(block, impl);
+   }
 
-   if (state.progress) {
+   if (progress) {
       nir_metadata_preserve(impl, nir_metadata_block_index |
                                   nir_metadata_dominance);
+   } else {
+      nir_metadata_preserve(impl, nir_metadata_all);
    }
 
-   return state.progress;
+   return progress;
 }
 
 bool
@@ -303,7 +307,7 @@ nir_lower_vec_to_movs(nir_shader *shader)
 {
    bool progress = false;
 
-   nir_foreach_function(shader, function) {
+   nir_foreach_function(function, shader) {
       if (function->impl)
          progress = nir_lower_vec_to_movs_impl(function->impl) || progress;
    }