GlobalISel: Implement widenScalar for G_UNMERGE_VALUES

For the scalar case only.

Also move the similar G_MERGE_VALUES handling to a separate function
and cleanup to make them look more similar.

llvm-svn: 352979
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index f1f7c98..28c103a0 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -936,6 +936,85 @@
 }
 
 LegalizerHelper::LegalizeResult
+LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx,
+                                        LLT WideTy) {
+  if (TypeIdx != 1)
+    return UnableToLegalize;
+
+  unsigned DstReg = MI.getOperand(0).getReg();
+  LLT DstTy = MRI.getType(DstReg);
+  if (!DstTy.isScalar())
+    return UnableToLegalize;
+
+  unsigned NumOps = MI.getNumOperands();
+  unsigned NumSrc = MI.getNumOperands() - 1;
+  unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
+
+  unsigned Src1 = MI.getOperand(1).getReg();
+  unsigned ResultReg = MIRBuilder.buildZExt(DstTy, Src1)->getOperand(0).getReg();
+
+  for (unsigned I = 2; I != NumOps; ++I) {
+    const unsigned Offset = (I - 1) * PartSize;
+
+    unsigned SrcReg = MI.getOperand(I).getReg();
+    assert(MRI.getType(SrcReg) == LLT::scalar(PartSize));
+
+    auto ZextInput = MIRBuilder.buildZExt(DstTy, SrcReg);
+
+    unsigned NextResult = I + 1 == NumOps ? DstReg :
+      MRI.createGenericVirtualRegister(DstTy);
+
+    auto ShiftAmt = MIRBuilder.buildConstant(DstTy, Offset);
+    auto Shl = MIRBuilder.buildShl(DstTy, ZextInput, ShiftAmt);
+    MIRBuilder.buildOr(NextResult, ResultReg, Shl);
+    ResultReg = NextResult;
+  }
+
+  MI.eraseFromParent();
+  return Legalized;
+}
+
+LegalizerHelper::LegalizeResult
+LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
+                                          LLT WideTy) {
+  if (TypeIdx != 0)
+    return UnableToLegalize;
+
+  unsigned NumDst = MI.getNumOperands() - 1;
+  unsigned SrcReg = MI.getOperand(NumDst).getReg();
+  LLT SrcTy = MRI.getType(SrcReg);
+  if (!SrcTy.isScalar())
+    return UnableToLegalize;
+
+  unsigned Dst0Reg = MI.getOperand(0).getReg();
+  LLT DstTy = MRI.getType(Dst0Reg);
+  if (!DstTy.isScalar())
+    return UnableToLegalize;
+
+  unsigned NewSrcSize = NumDst * WideTy.getSizeInBits();
+  LLT NewSrcTy = LLT::scalar(NewSrcSize);
+  unsigned SizeDiff = WideTy.getSizeInBits() - DstTy.getSizeInBits();
+
+  auto WideSrc = MIRBuilder.buildZExt(NewSrcTy, SrcReg);
+
+  for (unsigned I = 1; I != NumDst; ++I) {
+    auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, SizeDiff * I);
+    auto Shl = MIRBuilder.buildShl(NewSrcTy, WideSrc, ShiftAmt);
+    WideSrc = MIRBuilder.buildOr(NewSrcTy, WideSrc, Shl);
+  }
+
+  Observer.changingInstr(MI);
+
+  MI.getOperand(NumDst).setReg(WideSrc->getOperand(0).getReg());
+  for (unsigned I = 0; I != NumDst; ++I)
+    widenScalarDst(MI, WideTy, I);
+
+  Observer.changedInstr(MI);
+
+  return Legalized;
+}
+
+LegalizerHelper::LegalizeResult
 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
   MIRBuilder.setInstr(MI);
 
@@ -968,45 +1047,10 @@
 
     return Legalized;
   }
-  case TargetOpcode::G_MERGE_VALUES: {
-    if (TypeIdx != 1)
-      return UnableToLegalize;
-
-    unsigned DstReg = MI.getOperand(0).getReg();
-    LLT DstTy = MRI.getType(DstReg);
-    if (!DstTy.isScalar())
-      return UnableToLegalize;
-
-    unsigned NumSrc = MI.getNumOperands() - 1;
-    unsigned EltSize = DstTy.getSizeInBits() / NumSrc;
-
-    unsigned ResultReg = MRI.createGenericVirtualRegister(DstTy);
-    unsigned Offset = 0;
-    for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I,
-           Offset += EltSize) {
-      assert(MRI.getType(MI.getOperand(I).getReg()) == LLT::scalar(EltSize));
-
-      unsigned ShiftAmt = MRI.createGenericVirtualRegister(DstTy);
-      unsigned Shl = MRI.createGenericVirtualRegister(DstTy);
-      unsigned ZextInput = MRI.createGenericVirtualRegister(DstTy);
-      MIRBuilder.buildZExt(ZextInput, MI.getOperand(I).getReg());
-
-      if (Offset != 0) {
-        unsigned NextResult = I + 1 == E ? DstReg :
-          MRI.createGenericVirtualRegister(DstTy);
-
-        MIRBuilder.buildConstant(ShiftAmt, Offset);
-        MIRBuilder.buildShl(Shl, ZextInput, ShiftAmt);
-        MIRBuilder.buildOr(NextResult, ResultReg, Shl);
-        ResultReg = NextResult;
-      } else {
-        ResultReg = ZextInput;
-      }
-    }
-
-    MI.eraseFromParent();
-    return Legalized;
-  }
+  case TargetOpcode::G_MERGE_VALUES:
+    return widenScalarMergeValues(MI, TypeIdx, WideTy);
+  case TargetOpcode::G_UNMERGE_VALUES:
+    return widenScalarUnmergeValues(MI, TypeIdx, WideTy);
   case TargetOpcode::G_UADDO:
   case TargetOpcode::G_USUBO: {
     if (TypeIdx == 1)