forked from OSchip/llvm-project
[GlobalISel] fix widenScalarUnmerge if widen type is not a multiple of destination type
Fix creation of illegal unmerge when widen was requested to a type which is not a multiple of the destination type. E.g. when trying to widen an s48 unmerge to s64 the existing code would create an illegal unmerge from s64 to s48. Instead, create further unmerges to a GCD type, then use this to remerge these intermediate results to the actual destinations. Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D88422
This commit is contained in:
parent
074ab233ed
commit
113114a5da
|
@ -1605,19 +1605,28 @@ LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
|
||||||
|
|
||||||
auto Unmerge = MIRBuilder.buildUnmerge(WideTy, WideSrc);
|
auto Unmerge = MIRBuilder.buildUnmerge(WideTy, WideSrc);
|
||||||
|
|
||||||
// Create a sequence of unmerges to the original results. since we may have
|
// Create a sequence of unmerges and merges to the original results. Since we
|
||||||
// widened the source, we will need to pad the results with dead defs to cover
|
// may have widened the source, we will need to pad the results with dead defs
|
||||||
// the source register.
|
// to cover the source register.
|
||||||
// e.g. widen s16 to s32:
|
// e.g. widen s48 to s64:
|
||||||
// %1:_(s16), %2:_(s16), %3:_(s16) = G_UNMERGE_VALUES %0:_(s48)
|
// %1:_(s48), %2:_(s48) = G_UNMERGE_VALUES %0:_(s96)
|
||||||
//
|
//
|
||||||
// =>
|
// =>
|
||||||
// %4:_(s64) = G_ANYEXT %0:_(s48)
|
// %4:_(s192) = G_ANYEXT %0:_(s96)
|
||||||
// %5:_(s32), %6:_(s32) = G_UNMERGE_VALUES %4 ; Requested unmerge
|
// %5:_(s64), %6, %7 = G_UNMERGE_VALUES %4 ; Requested unmerge
|
||||||
// %1:_(s16), %2:_(s16) = G_UNMERGE_VALUES %5 ; unpack to original regs
|
// ; unpack to GCD type, with extra dead defs
|
||||||
// %3:_(s16), dead %7 = G_UNMERGE_VALUES %6 ; original reg + extra dead def
|
// %8:_(s16), %9, %10, %11 = G_UNMERGE_VALUES %5:_(s64)
|
||||||
|
// %12:_(s16), %13, dead %14, dead %15 = G_UNMERGE_VALUES %6:_(s64)
|
||||||
|
// dead %16:_(s16), dead %17, dead %18, dead %18 = G_UNMERGE_VALUES %7:_(s64)
|
||||||
|
// %1:_(s48) = G_MERGE_VALUES %8:_(s16), %9, %10 ; Remerge to destination
|
||||||
|
// %2:_(s48) = G_MERGE_VALUES %11:_(s16), %12, %13 ; Remerge to destination
|
||||||
|
const LLT GCDTy = getGCDType(WideTy, DstTy);
|
||||||
const int NumUnmerge = Unmerge->getNumOperands() - 1;
|
const int NumUnmerge = Unmerge->getNumOperands() - 1;
|
||||||
|
const int PartsPerRemerge = DstTy.getSizeInBits() / GCDTy.getSizeInBits();
|
||||||
|
|
||||||
|
// Directly unmerge to the destination without going through a GCD type
|
||||||
|
// if possible
|
||||||
|
if (PartsPerRemerge == 1) {
|
||||||
const int PartsPerUnmerge = WideTy.getSizeInBits() / DstTy.getSizeInBits();
|
const int PartsPerUnmerge = WideTy.getSizeInBits() / DstTy.getSizeInBits();
|
||||||
|
|
||||||
for (int I = 0; I != NumUnmerge; ++I) {
|
for (int I = 0; I != NumUnmerge; ++I) {
|
||||||
|
@ -1635,6 +1644,22 @@ LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
|
||||||
|
|
||||||
MIB.addUse(Unmerge.getReg(I));
|
MIB.addUse(Unmerge.getReg(I));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
SmallVector<Register, 16> Parts;
|
||||||
|
for (int J = 0; J != NumUnmerge; ++J)
|
||||||
|
extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
|
||||||
|
|
||||||
|
SmallVector<Register, 8> RemergeParts;
|
||||||
|
for (int I = 0; I != NumDst; ++I) {
|
||||||
|
for (int J = 0; J < PartsPerRemerge; ++J) {
|
||||||
|
const int Idx = I * PartsPerRemerge + J;
|
||||||
|
RemergeParts.emplace_back(Parts[Idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
MIRBuilder.buildMerge(MI.getOperand(I).getReg(), RemergeParts);
|
||||||
|
RemergeParts.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MI.eraseFromParent();
|
MI.eraseFromParent();
|
||||||
return Legalized;
|
return Legalized;
|
||||||
|
|
|
@ -3135,4 +3135,48 @@ TEST_F(AArch64GISelMITest, FewerElementsInsertVectorElt) {
|
||||||
EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
|
EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test widen scalar of G_UNMERGE_VALUES
|
||||||
|
TEST_F(AArch64GISelMITest, widenScalarUnmerge) {
|
||||||
|
setUp();
|
||||||
|
if (!TM)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DefineLegalizerInfo(A, {});
|
||||||
|
|
||||||
|
LLT S96{LLT::scalar(96)};
|
||||||
|
LLT S64{LLT::scalar(64)};
|
||||||
|
LLT S48{LLT::scalar(48)};
|
||||||
|
|
||||||
|
auto Src = B.buildAnyExt(S96, Copies[0]);
|
||||||
|
auto Unmerge = B.buildUnmerge(S48, Src);
|
||||||
|
|
||||||
|
AInfo Info(MF->getSubtarget());
|
||||||
|
DummyGISelObserver Observer;
|
||||||
|
LegalizerHelper Helper(*MF, Info, Observer, B);
|
||||||
|
|
||||||
|
// Perform Legalization
|
||||||
|
B.setInsertPt(*EntryMBB, Unmerge->getIterator());
|
||||||
|
|
||||||
|
// This should create unmerges to a GCD type (S16), then remerge to S48
|
||||||
|
EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
|
||||||
|
Helper.widenScalar(*Unmerge, 0, S64));
|
||||||
|
|
||||||
|
const auto *CheckStr = R"(
|
||||||
|
CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY
|
||||||
|
CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY
|
||||||
|
CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY
|
||||||
|
CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[COPY0]]
|
||||||
|
CHECK: [[ANYEXT1:%[0-9]+]]:_(s192) = G_ANYEXT [[ANYEXT]]
|
||||||
|
CHECK: [[UNMERGE:%[0-9]+]]:_(s64), [[UNMERGE1:%[0-9]+]]:_(s64), [[UNMERGE2:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT1]]
|
||||||
|
CHECK: [[UNMERGE3:%[0-9]+]]:_(s16), [[UNMERGE4:%[0-9]+]]:_(s16), [[UNMERGE5:%[0-9]+]]:_(s16), [[UNMERGE6:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE]]
|
||||||
|
CHECK: [[UNMERGE7:%[0-9]+]]:_(s16), [[UNMERGE8:%[0-9]+]]:_(s16), [[UNMERGE9:%[0-9]+]]:_(s16), [[UNMERGE10:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE1]]
|
||||||
|
CHECK: [[UNMERGE11:%[0-9]+]]:_(s16), [[UNMERGE12:%[0-9]+]]:_(s16), [[UNMERGE13:%[0-9]+]]:_(s16), [[UNMERGE14:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE2]]
|
||||||
|
CHECK: [[MERGE:%[0-9]+]]:_(s48) = G_MERGE_VALUES [[UNMERGE3]]:_(s16), [[UNMERGE4]]:_(s16), [[UNMERGE5]]:_(s16)
|
||||||
|
CHECK: [[MERGE1:%[0-9]+]]:_(s48) = G_MERGE_VALUES [[UNMERGE6]]:_(s16), [[UNMERGE7]]:_(s16), [[UNMERGE8]]:_(s16)
|
||||||
|
)";
|
||||||
|
|
||||||
|
// Check
|
||||||
|
EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue