}
-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++)
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
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;
}
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;
}
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;