GlobalISel: Try to widen merges with other merges
If the requested source type an be used as a merge source type, create
a merge of merges. This avoids creating large, illegal extensions and
bit-ops directly to the result type.
llvm-svn: 364841
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index d62e786..6958303 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -794,12 +794,38 @@
if (!DstTy.isScalar())
return UnableToLegalize;
+ Register Src1 = MI.getOperand(1).getReg();
+ LLT SrcTy = MRI.getType(Src1);
+ int NumMerge = DstTy.getSizeInBits() / WideTy.getSizeInBits();
+
+ // Try to turn this into a merge of merges if we can use the requested type as
+ // the source.
+
+ // TODO: Pad with undef if DstTy > WideTy
+ if (NumMerge > 1 && WideTy.getSizeInBits() % SrcTy.getSizeInBits() == 0) {
+ int PartsPerMerge = WideTy.getSizeInBits() / SrcTy.getSizeInBits();
+ SmallVector<Register, 4> Parts;
+ SmallVector<Register, 4> SubMerges;
+
+ for (int I = 0; I != NumMerge; ++I) {
+ for (int J = 0; J != PartsPerMerge; ++J)
+ Parts.push_back(MI.getOperand(I * PartsPerMerge + J + 1).getReg());
+
+ auto SubMerge = MIRBuilder.buildMerge(WideTy, Parts);
+ SubMerges.push_back(SubMerge.getReg(0));
+ Parts.clear();
+ }
+
+ MIRBuilder.buildMerge(DstReg, SubMerges);
+ MI.eraseFromParent();
+ return Legalized;
+ }
+
unsigned NumOps = MI.getNumOperands();
unsigned NumSrc = MI.getNumOperands() - 1;
unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
- Register Src1 = MI.getOperand(1).getReg();
- Register ResultReg = MIRBuilder.buildZExt(DstTy, Src1)->getOperand(0).getReg();
+ Register ResultReg = MIRBuilder.buildZExt(DstTy, Src1).getReg(0);
for (unsigned I = 2; I != NumOps; ++I) {
const unsigned Offset = (I - 1) * PartSize;