aco: expand vectors passed as copy operands

Most copies which hit this case use p_create_vector, but in the future
p_parallelcopy will be used instead.

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Daniel Schürmann <daniel@schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7216>
diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp
index 22497a1..c839e06 100644
--- a/src/amd/compiler/aco_optimizer.cpp
+++ b/src/amd/compiler/aco_optimizer.cpp
@@ -1212,6 +1212,27 @@
    case aco_opcode::s_mov_b32: /* propagate */
    case aco_opcode::s_mov_b64:
    case aco_opcode::v_mov_b32:
+      if (instr->operands[0].isTemp() && ctx.info[instr->operands[0].tempId()].is_vec() &&
+          instr->operands[0].regClass() != instr->definitions[0].regClass()) {
+         /* We might not be able to copy-propagate if it's a SGPR->VGPR copy, so
+          * duplicate the vector instead.
+          */
+         Instruction *vec = ctx.info[instr->operands[0].tempId()].instr;
+         aco_ptr<Instruction> old_copy = std::move(instr);
+
+         instr.reset(create_instruction<Pseudo_instruction>(aco_opcode::p_create_vector, Format::PSEUDO, vec->operands.size(), 1));
+         instr->definitions[0] = old_copy->definitions[0];
+         std::copy(vec->operands.begin(), vec->operands.end(), instr->operands.begin());
+         for (unsigned i = 0; i < vec->operands.size(); i++) {
+            Operand& op = instr->operands[i];
+            if (op.isTemp() && ctx.info[op.tempId()].is_temp() &&
+                ctx.info[op.tempId()].temp.type() == instr->definitions[0].regClass().type())
+               op.setTemp(ctx.info[op.tempId()].temp);
+         }
+         ctx.info[instr->definitions[0].tempId()].set_vec(instr.get());
+         break;
+      }
+      /* fallthrough */
    case aco_opcode::p_as_uniform:
       if (instr->definitions[0].isFixed()) {
          /* don't copy-propagate copies into fixed registers */