Skip to content

Commit 31ba237

Browse files
committed
[AArch64][GlobalISel] Fix lowering of i64->f32 itofp.
This is a GISel equivalent of llvm#130665, preventing a double-rounding issue in sitofp/uitofp by scalarizing i64->f32 converts. Most of the changes are made in the ActionDefinitionsBuilder for G_SITOFP/G_UITOFP. Because it is legal to convert i64->f16 itofp without double-rounding, but not a fpround i64->f16, that variant is lowered to build the two extends.
1 parent 849e5ea commit 31ba237

File tree

3 files changed

+736
-882
lines changed

3 files changed

+736
-882
lines changed

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7620,6 +7620,18 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
76207620
return Legalized;
76217621
}
76227622

7623+
// i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16. We cannot
7624+
// just convert fpround f64->f16 without double-rounding, so we manually
7625+
// perform the lowering here where we know it is valid.
7626+
if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64) {
7627+
auto M1 = MIRBuilder.buildUITOFP(SrcTy, Src);
7628+
LLT S32Ty = SrcTy.changeElementSize(32);
7629+
auto M2 = MIRBuilder.buildFPTrunc(S32Ty, M1);
7630+
MIRBuilder.buildFPTrunc(Dst, M2);
7631+
MI.eraseFromParent();
7632+
return Legalized;
7633+
}
7634+
76237635
if (SrcTy != LLT::scalar(64))
76247636
return UnableToLegalize;
76257637

@@ -7651,6 +7663,18 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) {
76517663
return Legalized;
76527664
}
76537665

7666+
// i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16. We cannot
7667+
// just convert fpround f64->f16 without double-rounding, so we manually
7668+
// perform the lowering here where we know it is valid.
7669+
if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64) {
7670+
auto M1 = MIRBuilder.buildSITOFP(SrcTy, Src);
7671+
LLT S32Ty = SrcTy.changeElementSize(32);
7672+
auto M2 = MIRBuilder.buildFPTrunc(S32Ty, M1);
7673+
MIRBuilder.buildFPTrunc(Dst, M2);
7674+
MI.eraseFromParent();
7675+
return Legalized;
7676+
}
7677+
76547678
if (SrcTy != S64)
76557679
return UnableToLegalize;
76567680

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -917,16 +917,28 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
917917
.moreElementsToNextPow2(1)
918918
.widenScalarOrEltToNextPow2OrMinSize(1)
919919
.minScalar(1, s32)
920+
.lowerIf([](const LegalityQuery &Query) {
921+
return Query.Types[1].isVector() &&
922+
Query.Types[1].getScalarSizeInBits() == 64 &&
923+
Query.Types[0].getScalarSizeInBits() == 16;
924+
})
920925
.widenScalarOrEltToNextPow2OrMinSize(0, /*MinSize=*/HasFP16 ? 16 : 32)
926+
.scalarizeIf(
927+
// v2i64->v2f32 needs to scalarize to avoid double-rounding issues.
928+
[](const LegalityQuery &Query) {
929+
return Query.Types[0].getScalarSizeInBits() == 32 &&
930+
Query.Types[1].getScalarSizeInBits() == 64;
931+
},
932+
0)
921933
.widenScalarIf(
922-
[=](const LegalityQuery &Query) {
934+
[](const LegalityQuery &Query) {
923935
return Query.Types[1].getScalarSizeInBits() <= 64 &&
924936
Query.Types[0].getScalarSizeInBits() <
925937
Query.Types[1].getScalarSizeInBits();
926938
},
927939
LegalizeMutations::changeElementSizeTo(0, 1))
928940
.widenScalarIf(
929-
[=](const LegalityQuery &Query) {
941+
[](const LegalityQuery &Query) {
930942
return Query.Types[0].getScalarSizeInBits() <= 64 &&
931943
Query.Types[0].getScalarSizeInBits() >
932944
Query.Types[1].getScalarSizeInBits();

0 commit comments

Comments
 (0)