Skip to content

Commit 3448e9c

Browse files
authored
[AArch64][GlobalISel] Fix lowering of i64->f32 itofp. (llvm#132703)
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 f64->f16, that variant is lowered to build the two extends.
1 parent 9eb4fc7 commit 3448e9c

File tree

3 files changed

+654
-890
lines changed

3 files changed

+654
-890
lines changed

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7695,6 +7695,22 @@ LegalizerHelper::lowerU64ToF64BitFloatOps(MachineInstr &MI) {
76957695
return Legalized;
76967696
}
76977697

7698+
/// i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16. We cannot
7699+
/// convert fpround f64->f16 without double-rounding, so we manually perform the
7700+
/// lowering here where we know it is valid.
7701+
static LegalizerHelper::LegalizeResult
7702+
loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src,
7703+
LLT SrcTy, MachineIRBuilder &MIRBuilder) {
7704+
auto M1 = MI.getOpcode() == TargetOpcode::G_UITOFP
7705+
? MIRBuilder.buildUITOFP(SrcTy, Src)
7706+
: MIRBuilder.buildSITOFP(SrcTy, Src);
7707+
LLT S32Ty = SrcTy.changeElementSize(32);
7708+
auto M2 = MIRBuilder.buildFPTrunc(S32Ty, M1);
7709+
MIRBuilder.buildFPTrunc(Dst, M2);
7710+
MI.eraseFromParent();
7711+
return LegalizerHelper::Legalized;
7712+
}
7713+
76987714
LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
76997715
auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
77007716

@@ -7706,6 +7722,9 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
77067722
return Legalized;
77077723
}
77087724

7725+
if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
7726+
return loweri64tof16ITOFP(MI, Dst, DstTy, Src, SrcTy, MIRBuilder);
7727+
77097728
if (SrcTy != LLT::scalar(64))
77107729
return UnableToLegalize;
77117730

@@ -7737,6 +7756,9 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) {
77377756
return Legalized;
77387757
}
77397758

7759+
if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
7760+
return loweri64tof16ITOFP(MI, Dst, DstTy, Src, SrcTy, MIRBuilder);
7761+
77407762
if (SrcTy != S64)
77417763
return UnableToLegalize;
77427764

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -923,16 +923,28 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
923923
.moreElementsToNextPow2(1)
924924
.widenScalarOrEltToNextPow2OrMinSize(1)
925925
.minScalar(1, s32)
926+
.lowerIf([](const LegalityQuery &Query) {
927+
return Query.Types[1].isVector() &&
928+
Query.Types[1].getScalarSizeInBits() == 64 &&
929+
Query.Types[0].getScalarSizeInBits() == 16;
930+
})
926931
.widenScalarOrEltToNextPow2OrMinSize(0, /*MinSize=*/HasFP16 ? 16 : 32)
932+
.scalarizeIf(
933+
// v2i64->v2f32 needs to scalarize to avoid double-rounding issues.
934+
[](const LegalityQuery &Query) {
935+
return Query.Types[0].getScalarSizeInBits() == 32 &&
936+
Query.Types[1].getScalarSizeInBits() == 64;
937+
},
938+
0)
927939
.widenScalarIf(
928-
[=](const LegalityQuery &Query) {
940+
[](const LegalityQuery &Query) {
929941
return Query.Types[1].getScalarSizeInBits() <= 64 &&
930942
Query.Types[0].getScalarSizeInBits() <
931943
Query.Types[1].getScalarSizeInBits();
932944
},
933945
LegalizeMutations::changeElementSizeTo(0, 1))
934946
.widenScalarIf(
935-
[=](const LegalityQuery &Query) {
947+
[](const LegalityQuery &Query) {
936948
return Query.Types[0].getScalarSizeInBits() <= 64 &&
937949
Query.Types[0].getScalarSizeInBits() >
938950
Query.Types[1].getScalarSizeInBits();

0 commit comments

Comments
 (0)