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)