[llvm] GlobalISel: Fix mishandling vector-as-scalar in return values (PR #175780)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 22 04:51:10 PST 2026


================
@@ -645,9 +654,22 @@ static void buildCopyToRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
     }
   }
 
-  if (LCMTy.isVector() && CoveringSize != SrcSize)
+  if (LCMTy.isVector() && CoveringSize != SrcSize) {
     UnmergeSrc = B.buildPadVectorWithUndefElements(LCMTy, SrcReg).getReg(0);
 
+    unsigned ExcessBits = CoveringSize - DstSize * DstRegs.size();
+    if (ExcessBits != 0) {
+      SmallVector<Register, 8> PaddedDstRegs(DstRegs.begin(), DstRegs.end());
+
+      MachineRegisterInfo &MRI = *B.getMRI();
+      for (unsigned I = 0; I != ExcessBits; I += PartSize)
+        PaddedDstRegs.push_back(MRI.createGenericVirtualRegister(PartTy));
+
+      B.buildUnmerge(PaddedDstRegs, UnmergeSrc);
+      return;
+    }
+  }
----------------
arsenm wrote:

This returns exactly as many registers as the target asked, the padding is just to conform to the requirements of the unmerge.

e.g. for this:
```
define <3 x i16> @ret_v3i16() {
  ret <3 x i16> poison
}
```

We get:
```
    %8:_(<3 x s16>) = G_IMPLICIT_DEF
    %11:_(s16), %12:_(s16), %13:_(s16) = G_UNMERGE_VALUES %8(<3 x s16>)
    %14:_(s16) = G_IMPLICIT_DEF
    %15:_(<6 x s16>) = G_BUILD_VECTOR %11(s16), %12(s16), %13(s16), %14(s16), %14(s16), %14(s16)
    %9:_(s32), %10:_(s32), %16:_(s32) = G_UNMERGE_VALUES %15(<6 x s16>)
    $vgpr0 = COPY %9(s32)
    $vgpr1 = COPY %10(s32)
    SI_RETURN implicit $vgpr0, implicit $vgpr1
```
The padding is the unused %16



https://github.com/llvm/llvm-project/pull/175780


More information about the llvm-commits mailing list