Merge branch 'master' of ../mesa into vulkan
[mesa.git] / src / glsl / nir / nir_opt_copy_propagate.c
index a2be047a65895f59af87d80465def251626a3e13..71367d001bbc1126afb50536265d317a75366d50 100644 (file)
@@ -53,22 +53,6 @@ static bool is_move(nir_alu_instr *instr)
 
 }
 
-static bool
-is_swizzleless_move(nir_alu_instr *instr)
-{
-   if (!is_move(instr))
-      return false;
-
-   for (unsigned i = 0; i < 4; i++) {
-      if (!((instr->dest.write_mask >> i) & 1))
-         break;
-      if (instr->src[0].swizzle[i] != i)
-         return false;
-   }
-
-   return true;
-}
-
 static bool is_vec(nir_alu_instr *instr)
 {
    for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++)
@@ -80,64 +64,33 @@ static bool is_vec(nir_alu_instr *instr)
           instr->op == nir_op_vec4;
 }
 
-typedef struct {
-   nir_ssa_def *def;
-   bool found;
-} search_def_state;
-
 static bool
-search_def(nir_src *src, void *_state)
-{
-   search_def_state *state = (search_def_state *) _state;
-
-   if (src->is_ssa && src->ssa == state->def)
-      state->found = true;
-
-   return true;
-}
-
-static void
-rewrite_src_instr(nir_src *src, nir_ssa_def *new_def, nir_instr *parent_instr)
+is_swizzleless_move(nir_alu_instr *instr)
 {
-   nir_ssa_def *old_def = src->ssa;
-
-   src->ssa = new_def;
-
-   /*
-    * The instruction could still use the old definition in one of its other
-    * sources, so only remove the instruction from the uses if there are no
-    * more uses left.
-    */
-
-   search_def_state search_state;
-   search_state.def = old_def;
-   search_state.found = false;
-   nir_foreach_src(parent_instr, search_def, &search_state);
-   if (!search_state.found) {
-      struct set_entry *entry =
-         _mesa_set_search(old_def->uses, _mesa_hash_pointer(parent_instr),
-                          parent_instr);
-      assert(entry);
-      _mesa_set_remove(old_def->uses, entry);
+   if (is_move(instr)) {
+      for (unsigned i = 0; i < 4; i++) {
+         if (!((instr->dest.write_mask >> i) & 1))
+            break;
+         if (instr->src[0].swizzle[i] != i)
+            return false;
+      }
+      return true;
+   } else if (is_vec(instr)) {
+      nir_ssa_def *def = NULL;
+      for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
+         if (instr->src[i].swizzle[0] != i)
+            return false;
+
+         if (def == NULL) {
+            def = instr->src[i].src.ssa;
+         } else if (instr->src[i].src.ssa != def) {
+            return false;
+         }
+      }
+      return true;
+   } else {
+      return false;
    }
-
-   _mesa_set_add(new_def->uses, _mesa_hash_pointer(parent_instr),
-                 parent_instr);
-}
-
-static void
-rewrite_src_if(nir_if *if_stmt, nir_ssa_def *new_def)
-{
-   nir_ssa_def *old_def = if_stmt->condition.ssa;
-
-   if_stmt->condition.ssa = new_def;
-
-   struct set_entry *entry =
-      _mesa_set_search(old_def->if_uses, _mesa_hash_pointer(if_stmt), if_stmt);
-   assert(entry);
-   _mesa_set_remove(old_def->if_uses, entry);
-
-   _mesa_set_add(new_def->if_uses, _mesa_hash_pointer(if_stmt), if_stmt);
 }
 
 static bool
@@ -157,10 +110,26 @@ copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if)
    if (!is_swizzleless_move(alu_instr))
       return false;
 
-   if (parent_instr)
-      rewrite_src_instr(src, alu_instr->src[0].src.ssa, parent_instr);
-   else
-      rewrite_src_if(parent_if, alu_instr->src[0].src.ssa);
+   /* Don't let copy propagation land us with a phi that has more
+    * components in its source than it has in its destination.  That badly
+    * messes up out-of-ssa.
+    */
+   if (parent_instr && parent_instr->type == nir_instr_type_phi) {
+      nir_phi_instr *phi = nir_instr_as_phi(parent_instr);
+      assert(phi->dest.is_ssa);
+      if (phi->dest.ssa.num_components !=
+          alu_instr->src[0].src.ssa->num_components)
+         return false;
+   }
+
+   if (parent_instr) {
+      nir_instr_rewrite_src(parent_instr, src,
+                            nir_src_for_ssa(alu_instr->src[0].src.ssa));
+   } else {
+      assert(src == &parent_if->condition);
+      nir_if_rewrite_condition(parent_if,
+                               nir_src_for_ssa(alu_instr->src[0].src.ssa));
+   }
 
    return true;
 }
@@ -213,7 +182,8 @@ copy_prop_alu_src(nir_alu_instr *parent_alu_instr, unsigned index)
    for (unsigned i = 0; i < 4; i++)
       src->swizzle[i] = new_swizzle[i];
 
-   rewrite_src_instr(&src->src, def, &parent_alu_instr->instr);
+   nir_instr_rewrite_src(&parent_alu_instr->instr, &src->src,
+                         nir_src_for_ssa(def));
 
    return true;
 }
@@ -244,10 +214,6 @@ copy_prop_instr(nir_instr *instr)
          while (copy_prop_alu_src(alu_instr, i))
             progress = true;
 
-      if (alu_instr->has_predicate)
-         while (copy_prop_src(&alu_instr->predicate, instr, NULL))
-            progress = true;
-
       if (!alu_instr->dest.dest.is_ssa && alu_instr->dest.dest.reg.indirect)
          while (copy_prop_src(alu_instr->dest.dest.reg.indirect, instr, NULL))
             progress = true;