[llvm] e9cb440 - [X86][GlobalISel] Enable scalar versions of G_UITOFP and G_FPTOUI (#100079)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 25 07:15:42 PDT 2024
Author: Evgenii Kudriashov
Date: 2024-09-25T16:15:36+02:00
New Revision: e9cb44090ff7b3feda386ca1ee1252ab47c0617e
URL: https://github.com/llvm/llvm-project/commit/e9cb44090ff7b3feda386ca1ee1252ab47c0617e
DIFF: https://github.com/llvm/llvm-project/commit/e9cb44090ff7b3feda386ca1ee1252ab47c0617e.diff
LOG: [X86][GlobalISel] Enable scalar versions of G_UITOFP and G_FPTOUI (#100079)
Also add tests for G_SITOFP and G_FPTOSI
Added:
llvm/test/CodeGen/X86/isel-fp-to-int.ll
llvm/test/CodeGen/X86/isel-int-to-fp.ll
Modified:
llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 5360850deeffd8..ecade6b5caed6e 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -394,6 +394,8 @@ class LegalizerHelper {
LegalizeResult lowerRotate(MachineInstr &MI);
LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI);
+ LegalizeResult lowerU64ToF32WithSITOFP(MachineInstr &MI);
+ LegalizeResult lowerU64ToF64BitFloatOps(MachineInstr &MI);
LegalizeResult lowerUITOFP(MachineInstr &MI);
LegalizeResult lowerSITOFP(MachineInstr &MI);
LegalizeResult lowerFPTOUI(MachineInstr &MI);
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index e64d3f51a01111..c3b6b3033cf5c4 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -7169,6 +7169,78 @@ LegalizerHelper::lowerU64ToF32BitOps(MachineInstr &MI) {
return Legalized;
}
+// Expand s32 = G_UITOFP s64 to an IEEE float representation using bit
+// operations and G_SITOFP
+LegalizerHelper::LegalizeResult
+LegalizerHelper::lowerU64ToF32WithSITOFP(MachineInstr &MI) {
+ auto [Dst, Src] = MI.getFirst2Regs();
+ const LLT S64 = LLT::scalar(64);
+ const LLT S32 = LLT::scalar(32);
+ const LLT S1 = LLT::scalar(1);
+
+ assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S32);
+
+ // For i64 < INT_MAX we simply reuse SITOFP.
+ // Otherwise, divide i64 by 2, round result by ORing with the lowest bit
+ // saved before division, convert to float by SITOFP, multiply the result
+ // by 2.
+ auto One = MIRBuilder.buildConstant(S64, 1);
+ auto Zero = MIRBuilder.buildConstant(S64, 0);
+ // Result if Src < INT_MAX
+ auto SmallResult = MIRBuilder.buildSITOFP(S32, Src);
+ // Result if Src >= INT_MAX
+ auto Halved = MIRBuilder.buildLShr(S64, Src, One);
+ auto LowerBit = MIRBuilder.buildAnd(S64, Src, One);
+ auto RoundedHalved = MIRBuilder.buildOr(S64, Halved, LowerBit);
+ auto HalvedFP = MIRBuilder.buildSITOFP(S32, RoundedHalved);
+ auto LargeResult = MIRBuilder.buildFAdd(S32, HalvedFP, HalvedFP);
+ // Check if the original value is larger than INT_MAX by comparing with
+ // zero to pick one of the two conversions.
+ auto IsLarge =
+ MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_SLT, S1, Src, Zero);
+ MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
+
+ MI.eraseFromParent();
+ return Legalized;
+}
+
+// Expand s64 = G_UITOFP s64 using bit and float arithmetic operations to an
+// IEEE double representation.
+LegalizerHelper::LegalizeResult
+LegalizerHelper::lowerU64ToF64BitFloatOps(MachineInstr &MI) {
+ auto [Dst, Src] = MI.getFirst2Regs();
+ const LLT S64 = LLT::scalar(64);
+ const LLT S32 = LLT::scalar(32);
+
+ assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S64);
+
+ // We create double value from 32 bit parts with 32 exponent
diff erence.
+ // Note that + and - are float operations that adjust the implicit leading
+ // one, the bases 2^52 and 2^84 are for illustrative purposes.
+ //
+ // X = 2^52 * 1.0...LowBits
+ // Y = 2^84 * 1.0...HighBits
+ // Scratch = 2^84 * 1.0...HighBits - 2^84 * 1.0 - 2^52 * 1.0
+ // = - 2^52 * 1.0...HighBits
+ // Result = - 2^52 * 1.0...HighBits + 2^52 * 1.0...LowBits
+ auto TwoP52 = MIRBuilder.buildConstant(S64, UINT64_C(0x4330000000000000));
+ auto TwoP84 = MIRBuilder.buildConstant(S64, UINT64_C(0x4530000000000000));
+ auto TwoP52P84 = llvm::bit_cast<double>(UINT64_C(0x4530000000100000));
+ auto TwoP52P84FP = MIRBuilder.buildFConstant(S64, TwoP52P84);
+ auto HalfWidth = MIRBuilder.buildConstant(S64, 32);
+
+ auto LowBits = MIRBuilder.buildTrunc(S32, Src);
+ LowBits = MIRBuilder.buildZExt(S64, LowBits);
+ auto LowBitsFP = MIRBuilder.buildOr(S64, TwoP52, LowBits);
+ auto HighBits = MIRBuilder.buildLShr(S64, Src, HalfWidth);
+ auto HighBitsFP = MIRBuilder.buildOr(S64, TwoP84, HighBits);
+ auto Scratch = MIRBuilder.buildFSub(S64, HighBitsFP, TwoP52P84FP);
+ MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
+
+ MI.eraseFromParent();
+ return Legalized;
+}
+
LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
@@ -7183,13 +7255,15 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
if (SrcTy != LLT::scalar(64))
return UnableToLegalize;
- if (DstTy == LLT::scalar(32)) {
+ if (DstTy == LLT::scalar(32))
// TODO: SelectionDAG has several alternative expansions to port which may
- // be more reasonble depending on the available instructions. If a target
- // has sitofp, does not have CTLZ, or can efficiently use f64 as an
- // intermediate type, this is probably worse.
- return lowerU64ToF32BitOps(MI);
- }
+ // be more reasonable depending on the available instructions. We also need
+ // a more advanced mechanism to choose an optimal version depending on
+ // target features such as sitofp or CTLZ availability.
+ return lowerU64ToF32WithSITOFP(MI);
+
+ if (DstTy == LLT::scalar(64))
+ return lowerU64ToF64BitFloatOps(MI);
return UnableToLegalize;
}
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index 7169d588548b05..bab7fe9d25e441 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -498,6 +498,62 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
.clampScalar(0, s32, sMaxScalar)
.widenScalarToNextPow2(1);
+ // For G_UITOFP and G_FPTOUI without AVX512, we have to custom legalize types
+ // <= s32 manually. Otherwise, in custom handler there is no way to
+ // understand whether s32 is an original type and we need to promote it to
+ // s64 or s32 is obtained after widening and we shouldn't widen it to s64.
+ //
+ // For AVX512 we simply widen types as there is direct mapping from opcodes
+ // to asm instructions.
+ getActionDefinitionsBuilder(G_UITOFP)
+ .legalIf([=](const LegalityQuery &Query) {
+ return HasAVX512 && typeInSet(0, {s32, s64})(Query) &&
+ typeInSet(1, {s32, s64})(Query);
+ })
+ .customIf([=](const LegalityQuery &Query) {
+ return !HasAVX512 &&
+ ((HasSSE1 && typeIs(0, s32)(Query)) ||
+ (HasSSE2 && typeIs(0, s64)(Query))) &&
+ scalarNarrowerThan(1, Is64Bit ? 64 : 32)(Query);
+ })
+ .lowerIf([=](const LegalityQuery &Query) {
+ // Lower conversions from s64
+ return !HasAVX512 &&
+ ((HasSSE1 && typeIs(0, s32)(Query)) ||
+ (HasSSE2 && typeIs(0, s64)(Query))) &&
+ (Is64Bit && typeIs(1, s64)(Query));
+ })
+ .clampScalar(0, s32, HasSSE2 ? s64 : s32)
+ .widenScalarToNextPow2(0)
+ .clampScalar(1, s32, sMaxScalar)
+ .widenScalarToNextPow2(1);
+
+ getActionDefinitionsBuilder(G_FPTOUI)
+ .legalIf([=](const LegalityQuery &Query) {
+ return HasAVX512 && typeInSet(0, {s32, s64})(Query) &&
+ typeInSet(1, {s32, s64})(Query);
+ })
+ .customIf([=](const LegalityQuery &Query) {
+ return !HasAVX512 &&
+ ((HasSSE1 && typeIs(1, s32)(Query)) ||
+ (HasSSE2 && typeIs(1, s64)(Query))) &&
+ scalarNarrowerThan(0, Is64Bit ? 64 : 32)(Query);
+ })
+ // TODO: replace with customized legalization using
+ // specifics of cvttsd2si. The selection of this node requires
+ // a vector type. Either G_SCALAR_TO_VECTOR is needed or more advanced
+ // support of G_BUILD_VECTOR/G_INSERT_VECTOR_ELT is required beforehand.
+ .lowerIf([=](const LegalityQuery &Query) {
+ return !HasAVX512 &&
+ ((HasSSE1 && typeIs(1, s32)(Query)) ||
+ (HasSSE2 && typeIs(1, s64)(Query))) &&
+ (Is64Bit && typeIs(0, s64)(Query));
+ })
+ .clampScalar(0, s32, sMaxScalar)
+ .widenScalarToNextPow2(0)
+ .clampScalar(1, s32, HasSSE2 ? s64 : s32)
+ .widenScalarToNextPow2(1);
+
// vector ops
getActionDefinitionsBuilder(G_BUILD_VECTOR)
.customIf([=](const LegalityQuery &Query) {
@@ -590,6 +646,10 @@ bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
return false;
case TargetOpcode::G_BUILD_VECTOR:
return legalizeBuildVector(MI, MRI, Helper);
+ case TargetOpcode::G_FPTOUI:
+ return legalizeFPTOUI(MI, MRI, Helper);
+ case TargetOpcode::G_UITOFP:
+ return legalizeUITOFP(MI, MRI, Helper);
}
llvm_unreachable("expected switch to return");
}
@@ -645,6 +705,45 @@ bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI,
return true;
}
+bool X86LegalizerInfo::legalizeFPTOUI(MachineInstr &MI,
+ MachineRegisterInfo &MRI,
+ LegalizerHelper &Helper) const {
+ MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
+ auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
+ unsigned DstSizeInBits = DstTy.getScalarSizeInBits();
+ const LLT s32 = LLT::scalar(32);
+ const LLT s64 = LLT::scalar(64);
+
+ // Simply reuse FPTOSI when it is possible to widen the type
+ if (DstSizeInBits <= 32) {
+ auto Casted = MIRBuilder.buildFPTOSI(DstTy == s32 ? s64 : s32, Src);
+ MIRBuilder.buildTrunc(Dst, Casted);
+ MI.eraseFromParent();
+ return true;
+ }
+
+ return false;
+}
+
+bool X86LegalizerInfo::legalizeUITOFP(MachineInstr &MI,
+ MachineRegisterInfo &MRI,
+ LegalizerHelper &Helper) const {
+ MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
+ auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
+ const LLT s32 = LLT::scalar(32);
+ const LLT s64 = LLT::scalar(64);
+
+ // Simply reuse SITOFP when it is possible to widen the type
+ if (SrcTy.getSizeInBits() <= 32) {
+ auto Ext = MIRBuilder.buildZExt(SrcTy == s32 ? s64 : s32, Src);
+ MIRBuilder.buildSITOFP(Dst, Ext);
+ MI.eraseFromParent();
+ return true;
+ }
+
+ return false;
+}
+
bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
MachineInstr &MI) const {
return true;
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
index 229a58986903d4..39bd9892e2f16e 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
@@ -39,6 +39,12 @@ class X86LegalizerInfo : public LegalizerInfo {
private:
bool legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI,
LegalizerHelper &Helper) const;
+
+ bool legalizeFPTOUI(MachineInstr &MI, MachineRegisterInfo &MRI,
+ LegalizerHelper &Helper) const;
+
+ bool legalizeUITOFP(MachineInstr &MI, MachineRegisterInfo &MRI,
+ LegalizerHelper &Helper) const;
};
} // namespace llvm
#endif
diff --git a/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp b/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
index 61633a09d93cf0..43c0145ec8e2ad 100644
--- a/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
@@ -296,7 +296,9 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);
break;
case TargetOpcode::G_SITOFP:
- case TargetOpcode::G_FPTOSI: {
+ case TargetOpcode::G_FPTOSI:
+ case TargetOpcode::G_UITOFP:
+ case TargetOpcode::G_FPTOUI: {
// Some of the floating-point instructions have mixed GPR and FP
// operands: fine-tune the computed mapping.
auto &Op0 = MI.getOperand(0);
@@ -304,10 +306,10 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
const LLT Ty0 = MRI.getType(Op0.getReg());
const LLT Ty1 = MRI.getType(Op1.getReg());
- bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
- bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
+ bool FirstArgIsFP =
+ Opc == TargetOpcode::G_SITOFP || Opc == TargetOpcode::G_UITOFP;
OpRegBankIdx[0] = getPartialMappingIdx(MI, Ty0, /* isFP= */ FirstArgIsFP);
- OpRegBankIdx[1] = getPartialMappingIdx(MI, Ty1, /* isFP= */ SecondArgIsFP);
+ OpRegBankIdx[1] = getPartialMappingIdx(MI, Ty1, /* isFP= */ !FirstArgIsFP);
break;
}
case TargetOpcode::G_FCMP: {
diff --git a/llvm/test/CodeGen/X86/isel-fp-to-int.ll b/llvm/test/CodeGen/X86/isel-fp-to-int.ll
new file mode 100644
index 00000000000000..fae3db6ad0afa0
--- /dev/null
+++ b/llvm/test/CodeGen/X86/isel-fp-to-int.ll
@@ -0,0 +1,391 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=x86_64-- -verify-machineinstrs | FileCheck %s --check-prefixes X64,SDAG-X64
+; RUN: llc < %s -global-isel -global-isel-abort=1 -mtriple=x86_64-- -verify-machineinstrs | FileCheck %s --check-prefixes X64,GISEL-X64
+; RUN: llc < %s -mattr=+avx512f -mtriple=x86_64-- -verify-machineinstrs | FileCheck %s --check-prefixes AVX512,SDAG-AVX512
+; RUN: llc < %s -global-isel -global-isel-abort=1 -mattr=+avx512f -mtriple=x86_64-- -verify-machineinstrs | FileCheck %s --check-prefixes AVX512,GISEL-AVX512
+
+define i64 @test_double_to_ui64(double %x) {
+; SDAG-X64-LABEL: test_double_to_ui64:
+; SDAG-X64: # %bb.0: # %entry
+; SDAG-X64-NEXT: cvttsd2si %xmm0, %rcx
+; SDAG-X64-NEXT: movq %rcx, %rdx
+; SDAG-X64-NEXT: sarq $63, %rdx
+; SDAG-X64-NEXT: subsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SDAG-X64-NEXT: cvttsd2si %xmm0, %rax
+; SDAG-X64-NEXT: andq %rdx, %rax
+; SDAG-X64-NEXT: orq %rcx, %rax
+; SDAG-X64-NEXT: retq
+;
+; GISEL-X64-LABEL: test_double_to_ui64:
+; GISEL-X64: # %bb.0: # %entry
+; GISEL-X64-NEXT: cvttsd2si %xmm0, %rcx
+; GISEL-X64-NEXT: movsd {{.*#+}} xmm1 = [9.2233720368547758E+18,0.0E+0]
+; GISEL-X64-NEXT: movapd %xmm0, %xmm2
+; GISEL-X64-NEXT: subsd %xmm1, %xmm2
+; GISEL-X64-NEXT: cvttsd2si %xmm2, %rdx
+; GISEL-X64-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000
+; GISEL-X64-NEXT: xorq %rdx, %rax
+; GISEL-X64-NEXT: xorl %edx, %edx
+; GISEL-X64-NEXT: ucomisd %xmm1, %xmm0
+; GISEL-X64-NEXT: setb %dl
+; GISEL-X64-NEXT: andl $1, %edx
+; GISEL-X64-NEXT: cmovneq %rcx, %rax
+; GISEL-X64-NEXT: retq
+;
+; AVX512-LABEL: test_double_to_ui64:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttsd2usi %xmm0, %rax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptoui double %x to i64
+ ret i64 %conv
+}
+
+define i32 @test_double_to_ui32(double %x) {
+; X64-LABEL: test_double_to_ui32:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttsd2si %xmm0, %rax
+; X64-NEXT: # kill: def $eax killed $eax killed $rax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_double_to_ui32:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttsd2usi %xmm0, %eax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptoui double %x to i32
+ ret i32 %conv
+}
+
+define zeroext i16 @test_double_to_ui16(double %x) {
+; X64-LABEL: test_double_to_ui16:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttsd2si %xmm0, %eax
+; X64-NEXT: # kill: def $ax killed $ax killed $eax
+; X64-NEXT: retq
+;
+; SDAG-AVX512-LABEL: test_double_to_ui16:
+; SDAG-AVX512: # %bb.0: # %entry
+; SDAG-AVX512-NEXT: vcvttsd2si %xmm0, %eax
+; SDAG-AVX512-NEXT: # kill: def $ax killed $ax killed $eax
+; SDAG-AVX512-NEXT: retq
+;
+; GISEL-AVX512-LABEL: test_double_to_ui16:
+; GISEL-AVX512: # %bb.0: # %entry
+; GISEL-AVX512-NEXT: vcvttsd2usi %xmm0, %eax
+; GISEL-AVX512-NEXT: # kill: def $ax killed $ax killed $eax
+; GISEL-AVX512-NEXT: retq
+entry:
+ %conv = fptoui double %x to i16
+ ret i16 %conv
+}
+
+define zeroext i8 @test_double_to_ui8(double %x) {
+; X64-LABEL: test_double_to_ui8:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttsd2si %xmm0, %eax
+; X64-NEXT: # kill: def $al killed $al killed $eax
+; X64-NEXT: retq
+;
+; SDAG-AVX512-LABEL: test_double_to_ui8:
+; SDAG-AVX512: # %bb.0: # %entry
+; SDAG-AVX512-NEXT: vcvttsd2si %xmm0, %eax
+; SDAG-AVX512-NEXT: # kill: def $al killed $al killed $eax
+; SDAG-AVX512-NEXT: retq
+;
+; GISEL-AVX512-LABEL: test_double_to_ui8:
+; GISEL-AVX512: # %bb.0: # %entry
+; GISEL-AVX512-NEXT: vcvttsd2usi %xmm0, %eax
+; GISEL-AVX512-NEXT: # kill: def $al killed $al killed $eax
+; GISEL-AVX512-NEXT: retq
+entry:
+ %conv = fptoui double %x to i8
+ ret i8 %conv
+}
+
+define i64 @test_float_to_ui64(float %x) {
+; SDAG-X64-LABEL: test_float_to_ui64:
+; SDAG-X64: # %bb.0: # %entry
+; SDAG-X64-NEXT: cvttss2si %xmm0, %rcx
+; SDAG-X64-NEXT: movq %rcx, %rdx
+; SDAG-X64-NEXT: sarq $63, %rdx
+; SDAG-X64-NEXT: subss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; SDAG-X64-NEXT: cvttss2si %xmm0, %rax
+; SDAG-X64-NEXT: andq %rdx, %rax
+; SDAG-X64-NEXT: orq %rcx, %rax
+; SDAG-X64-NEXT: retq
+;
+; GISEL-X64-LABEL: test_float_to_ui64:
+; GISEL-X64: # %bb.0: # %entry
+; GISEL-X64-NEXT: cvttss2si %xmm0, %rcx
+; GISEL-X64-NEXT: movss {{.*#+}} xmm1 = [9.22337203E+18,0.0E+0,0.0E+0,0.0E+0]
+; GISEL-X64-NEXT: movaps %xmm0, %xmm2
+; GISEL-X64-NEXT: subss %xmm1, %xmm2
+; GISEL-X64-NEXT: cvttss2si %xmm2, %rdx
+; GISEL-X64-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000
+; GISEL-X64-NEXT: xorq %rdx, %rax
+; GISEL-X64-NEXT: xorl %edx, %edx
+; GISEL-X64-NEXT: ucomiss %xmm1, %xmm0
+; GISEL-X64-NEXT: setb %dl
+; GISEL-X64-NEXT: andl $1, %edx
+; GISEL-X64-NEXT: cmovneq %rcx, %rax
+; GISEL-X64-NEXT: retq
+;
+; AVX512-LABEL: test_float_to_ui64:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttss2usi %xmm0, %rax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptoui float %x to i64
+ ret i64 %conv
+}
+
+define i32 @test_float_to_ui32(float %x) {
+; X64-LABEL: test_float_to_ui32:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttss2si %xmm0, %rax
+; X64-NEXT: # kill: def $eax killed $eax killed $rax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_float_to_ui32:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttss2usi %xmm0, %eax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptoui float %x to i32
+ ret i32 %conv
+}
+
+define zeroext i16 @test_float_to_ui16(float %x) {
+; X64-LABEL: test_float_to_ui16:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttss2si %xmm0, %eax
+; X64-NEXT: # kill: def $ax killed $ax killed $eax
+; X64-NEXT: retq
+;
+; SDAG-AVX512-LABEL: test_float_to_ui16:
+; SDAG-AVX512: # %bb.0: # %entry
+; SDAG-AVX512-NEXT: vcvttss2si %xmm0, %eax
+; SDAG-AVX512-NEXT: # kill: def $ax killed $ax killed $eax
+; SDAG-AVX512-NEXT: retq
+;
+; GISEL-AVX512-LABEL: test_float_to_ui16:
+; GISEL-AVX512: # %bb.0: # %entry
+; GISEL-AVX512-NEXT: vcvttss2usi %xmm0, %eax
+; GISEL-AVX512-NEXT: # kill: def $ax killed $ax killed $eax
+; GISEL-AVX512-NEXT: retq
+entry:
+ %conv = fptoui float %x to i16
+ ret i16 %conv
+}
+
+define zeroext i8 @test_float_to_ui8(float %x) {
+; X64-LABEL: test_float_to_ui8:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttss2si %xmm0, %eax
+; X64-NEXT: # kill: def $al killed $al killed $eax
+; X64-NEXT: retq
+;
+; SDAG-AVX512-LABEL: test_float_to_ui8:
+; SDAG-AVX512: # %bb.0: # %entry
+; SDAG-AVX512-NEXT: vcvttss2si %xmm0, %eax
+; SDAG-AVX512-NEXT: # kill: def $al killed $al killed $eax
+; SDAG-AVX512-NEXT: retq
+;
+; GISEL-AVX512-LABEL: test_float_to_ui8:
+; GISEL-AVX512: # %bb.0: # %entry
+; GISEL-AVX512-NEXT: vcvttss2usi %xmm0, %eax
+; GISEL-AVX512-NEXT: # kill: def $al killed $al killed $eax
+; GISEL-AVX512-NEXT: retq
+entry:
+ %conv = fptoui float %x to i8
+ ret i8 %conv
+}
+
+define i64 @test_double_to_si64(double %x) {
+; X64-LABEL: test_double_to_si64:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttsd2si %xmm0, %rax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_double_to_si64:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttsd2si %xmm0, %rax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi double %x to i64
+ ret i64 %conv
+}
+
+define i32 @test_double_to_si32(double %x) {
+; X64-LABEL: test_double_to_si32:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttsd2si %xmm0, %eax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_double_to_si32:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttsd2si %xmm0, %eax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi double %x to i32
+ ret i32 %conv
+}
+
+define signext i16 @test_double_to_si16(double %x) {
+; X64-LABEL: test_double_to_si16:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttsd2si %xmm0, %eax
+; X64-NEXT: # kill: def $ax killed $ax killed $eax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_double_to_si16:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttsd2si %xmm0, %eax
+; AVX512-NEXT: # kill: def $ax killed $ax killed $eax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi double %x to i16
+ ret i16 %conv
+}
+
+define signext i8 @test_double_to_si8(double %x) {
+; X64-LABEL: test_double_to_si8:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttsd2si %xmm0, %eax
+; X64-NEXT: # kill: def $al killed $al killed $eax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_double_to_si8:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttsd2si %xmm0, %eax
+; AVX512-NEXT: # kill: def $al killed $al killed $eax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi double %x to i8
+ ret i8 %conv
+}
+
+define i31 @test_double_to_si31(double %x) {
+; X64-LABEL: test_double_to_si31:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttsd2si %xmm0, %eax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_double_to_si31:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttsd2si %xmm0, %eax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi double %x to i31
+ ret i31 %conv
+}
+
+define i33 @test_double_to_si33(double %x) {
+; X64-LABEL: test_double_to_si33:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttsd2si %xmm0, %rax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_double_to_si33:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttsd2si %xmm0, %rax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi double %x to i33
+ ret i33 %conv
+}
+
+define i64 @test_float_to_si64(float %x) {
+; X64-LABEL: test_float_to_si64:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttss2si %xmm0, %rax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_float_to_si64:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttss2si %xmm0, %rax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi float %x to i64
+ ret i64 %conv
+}
+
+define i32 @test_float_to_si32(float %x) {
+; X64-LABEL: test_float_to_si32:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttss2si %xmm0, %eax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_float_to_si32:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttss2si %xmm0, %eax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi float %x to i32
+ ret i32 %conv
+}
+
+define signext i16 @test_float_to_si16(float %x) {
+; X64-LABEL: test_float_to_si16:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttss2si %xmm0, %eax
+; X64-NEXT: # kill: def $ax killed $ax killed $eax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_float_to_si16:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttss2si %xmm0, %eax
+; AVX512-NEXT: # kill: def $ax killed $ax killed $eax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi float %x to i16
+ ret i16 %conv
+}
+
+define signext i8 @test_float_to_si8(float %x) {
+; X64-LABEL: test_float_to_si8:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttss2si %xmm0, %eax
+; X64-NEXT: # kill: def $al killed $al killed $eax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_float_to_si8:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttss2si %xmm0, %eax
+; AVX512-NEXT: # kill: def $al killed $al killed $eax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi float %x to i8
+ ret i8 %conv
+}
+
+define i31 @test_float_to_si31(float %x) {
+; X64-LABEL: test_float_to_si31:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttss2si %xmm0, %eax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_float_to_si31:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttss2si %xmm0, %eax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi float %x to i31
+ ret i31 %conv
+}
+
+define i33 @test_float_to_si33(float %x) {
+; X64-LABEL: test_float_to_si33:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvttss2si %xmm0, %rax
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_float_to_si33:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvttss2si %xmm0, %rax
+; AVX512-NEXT: retq
+entry:
+ %conv = fptosi float %x to i33
+ ret i33 %conv
+}
diff --git a/llvm/test/CodeGen/X86/isel-int-to-fp.ll b/llvm/test/CodeGen/X86/isel-int-to-fp.ll
new file mode 100644
index 00000000000000..fc99ff95788f3c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/isel-int-to-fp.ll
@@ -0,0 +1,395 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=x86_64-- -verify-machineinstrs | FileCheck %s --check-prefixes X64,SDAG-X64
+; RUN: llc < %s -global-isel -global-isel-abort=1 -mtriple=x86_64-- -verify-machineinstrs | FileCheck %s --check-prefixes X64,GISEL-X64
+; RUN: llc < %s -mattr=+avx512f -mtriple=x86_64-- -verify-machineinstrs | FileCheck %s --check-prefixes AVX512,SDAG-AVX512
+; RUN: llc < %s -global-isel -global-isel-abort=1 -mattr=+avx512f -mtriple=x86_64-- -verify-machineinstrs | FileCheck %s --check-prefixes AVX512,GISEL-AVX512
+
+define double @test_ui64_to_double(i64 %x) {
+; SDAG-X64-LABEL: test_ui64_to_double:
+; SDAG-X64: # %bb.0: # %entry
+; SDAG-X64-NEXT: movq %rdi, %xmm1
+; SDAG-X64-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
+; SDAG-X64-NEXT: subpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; SDAG-X64-NEXT: movapd %xmm1, %xmm0
+; SDAG-X64-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1],xmm1[1]
+; SDAG-X64-NEXT: addsd %xmm1, %xmm0
+; SDAG-X64-NEXT: retq
+;
+; GISEL-X64-LABEL: test_ui64_to_double:
+; GISEL-X64: # %bb.0: # %entry
+; GISEL-X64-NEXT: movabsq $4841369599423283200, %rax # imm = 0x4330000000000000
+; GISEL-X64-NEXT: movabsq $4985484787499139072, %rcx # imm = 0x4530000000000000
+; GISEL-X64-NEXT: movsd {{.*#+}} xmm0 = [1.9342813118337666E+25,0.0E+0]
+; GISEL-X64-NEXT: movl $4294967295, %edx # imm = 0xFFFFFFFF
+; GISEL-X64-NEXT: andq %rdi, %rdx
+; GISEL-X64-NEXT: orq %rax, %rdx
+; GISEL-X64-NEXT: shrq $32, %rdi
+; GISEL-X64-NEXT: orq %rdi, %rcx
+; GISEL-X64-NEXT: movq %rcx, %xmm1
+; GISEL-X64-NEXT: subsd %xmm0, %xmm1
+; GISEL-X64-NEXT: movq %rdx, %xmm0
+; GISEL-X64-NEXT: addsd %xmm1, %xmm0
+; GISEL-X64-NEXT: retq
+;
+; AVX512-LABEL: test_ui64_to_double:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtusi2sd %rdi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = uitofp i64 %x to double
+ ret double %conv
+}
+
+define double @test_ui32_to_double(i32 %x) {
+; X64-LABEL: test_ui32_to_double:
+; X64: # %bb.0: # %entry
+; X64-NEXT: movl %edi, %eax
+; X64-NEXT: cvtsi2sd %rax, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_ui32_to_double:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtusi2sd %edi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = uitofp i32 %x to double
+ ret double %conv
+}
+
+define double @test_ui16_to_double(i16 zeroext %x) {
+; X64-LABEL: test_ui16_to_double:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2sd %edi, %xmm0
+; X64-NEXT: retq
+;
+; SDAG-AVX512-LABEL: test_ui16_to_double:
+; SDAG-AVX512: # %bb.0: # %entry
+; SDAG-AVX512-NEXT: vcvtsi2sd %edi, %xmm0, %xmm0
+; SDAG-AVX512-NEXT: retq
+;
+; GISEL-AVX512-LABEL: test_ui16_to_double:
+; GISEL-AVX512: # %bb.0: # %entry
+; GISEL-AVX512-NEXT: vcvtusi2sd %edi, %xmm0, %xmm0
+; GISEL-AVX512-NEXT: retq
+entry:
+ %conv = uitofp i16 %x to double
+ ret double %conv
+}
+
+define double @test_ui8_to_double(i8 zeroext %x) {
+; X64-LABEL: test_ui8_to_double:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2sd %edi, %xmm0
+; X64-NEXT: retq
+;
+; SDAG-AVX512-LABEL: test_ui8_to_double:
+; SDAG-AVX512: # %bb.0: # %entry
+; SDAG-AVX512-NEXT: vcvtsi2sd %edi, %xmm0, %xmm0
+; SDAG-AVX512-NEXT: retq
+;
+; GISEL-AVX512-LABEL: test_ui8_to_double:
+; GISEL-AVX512: # %bb.0: # %entry
+; GISEL-AVX512-NEXT: vcvtusi2sd %edi, %xmm0, %xmm0
+; GISEL-AVX512-NEXT: retq
+entry:
+ %conv = uitofp i8 %x to double
+ ret double %conv
+}
+
+define float @test_ui64_to_float(i64 %x) {
+; SDAG-X64-LABEL: test_ui64_to_float:
+; SDAG-X64: # %bb.0: # %entry
+; SDAG-X64-NEXT: testq %rdi, %rdi
+; SDAG-X64-NEXT: js .LBB4_1
+; SDAG-X64-NEXT: # %bb.2: # %entry
+; SDAG-X64-NEXT: cvtsi2ss %rdi, %xmm0
+; SDAG-X64-NEXT: retq
+; SDAG-X64-NEXT: .LBB4_1:
+; SDAG-X64-NEXT: movq %rdi, %rax
+; SDAG-X64-NEXT: shrq %rax
+; SDAG-X64-NEXT: andl $1, %edi
+; SDAG-X64-NEXT: orq %rax, %rdi
+; SDAG-X64-NEXT: cvtsi2ss %rdi, %xmm0
+; SDAG-X64-NEXT: addss %xmm0, %xmm0
+; SDAG-X64-NEXT: retq
+;
+; GISEL-X64-LABEL: test_ui64_to_float:
+; GISEL-X64: # %bb.0: # %entry
+; GISEL-X64-NEXT: cvtsi2ss %rdi, %xmm0
+; GISEL-X64-NEXT: movq %rdi, %rax
+; GISEL-X64-NEXT: shrq %rax
+; GISEL-X64-NEXT: movq %rdi, %rcx
+; GISEL-X64-NEXT: andq $1, %rcx
+; GISEL-X64-NEXT: orq %rax, %rcx
+; GISEL-X64-NEXT: cvtsi2ss %rcx, %xmm1
+; GISEL-X64-NEXT: addss %xmm1, %xmm1
+; GISEL-X64-NEXT: xorl %eax, %eax
+; GISEL-X64-NEXT: cmpq $0, %rdi
+; GISEL-X64-NEXT: setl %al
+; GISEL-X64-NEXT: andl $1, %eax
+; GISEL-X64-NEXT: movd %xmm1, %eax
+; GISEL-X64-NEXT: movd %xmm0, %ecx
+; GISEL-X64-NEXT: cmovnel %eax, %ecx
+; GISEL-X64-NEXT: movd %ecx, %xmm0
+; GISEL-X64-NEXT: retq
+;
+; AVX512-LABEL: test_ui64_to_float:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtusi2ss %rdi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = uitofp i64 %x to float
+ ret float %conv
+}
+
+define float @test_ui32_to_float(i32 %x) {
+; X64-LABEL: test_ui32_to_float:
+; X64: # %bb.0: # %entry
+; X64-NEXT: movl %edi, %eax
+; X64-NEXT: cvtsi2ss %rax, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_ui32_to_float:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtusi2ss %edi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = uitofp i32 %x to float
+ ret float %conv
+}
+
+define float @test_ui16_to_float(i16 zeroext %x) {
+; X64-LABEL: test_ui16_to_float:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2ss %edi, %xmm0
+; X64-NEXT: retq
+;
+; SDAG-AVX512-LABEL: test_ui16_to_float:
+; SDAG-AVX512: # %bb.0: # %entry
+; SDAG-AVX512-NEXT: vcvtsi2ss %edi, %xmm0, %xmm0
+; SDAG-AVX512-NEXT: retq
+;
+; GISEL-AVX512-LABEL: test_ui16_to_float:
+; GISEL-AVX512: # %bb.0: # %entry
+; GISEL-AVX512-NEXT: vcvtusi2ss %edi, %xmm0, %xmm0
+; GISEL-AVX512-NEXT: retq
+entry:
+ %conv = uitofp i16 %x to float
+ ret float %conv
+}
+
+define float @test_ui8_to_float(i8 zeroext %x) {
+; X64-LABEL: test_ui8_to_float:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2ss %edi, %xmm0
+; X64-NEXT: retq
+;
+; SDAG-AVX512-LABEL: test_ui8_to_float:
+; SDAG-AVX512: # %bb.0: # %entry
+; SDAG-AVX512-NEXT: vcvtsi2ss %edi, %xmm0, %xmm0
+; SDAG-AVX512-NEXT: retq
+;
+; GISEL-AVX512-LABEL: test_ui8_to_float:
+; GISEL-AVX512: # %bb.0: # %entry
+; GISEL-AVX512-NEXT: vcvtusi2ss %edi, %xmm0, %xmm0
+; GISEL-AVX512-NEXT: retq
+entry:
+ %conv = uitofp i8 %x to float
+ ret float %conv
+}
+
+define double @test_si64_to_double(i64 %x) {
+; X64-LABEL: test_si64_to_double:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2sd %rdi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si64_to_double:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtsi2sd %rdi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i64 %x to double
+ ret double %conv
+}
+
+define double @test_si32_to_double(i32 %x) {
+; X64-LABEL: test_si32_to_double:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2sd %edi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si32_to_double:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtsi2sd %edi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i32 %x to double
+ ret double %conv
+}
+
+define double @test_si16_to_double(i16 signext %x) {
+; X64-LABEL: test_si16_to_double:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2sd %edi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si16_to_double:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtsi2sd %edi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i16 %x to double
+ ret double %conv
+}
+
+define double @test_si8_to_double(i8 signext %x) {
+; X64-LABEL: test_si8_to_double:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2sd %edi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si8_to_double:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtsi2sd %edi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i8 %x to double
+ ret double %conv
+}
+
+define double @test_si31_to_double(i31 %x) {
+; X64-LABEL: test_si31_to_double:
+; X64: # %bb.0: # %entry
+; X64-NEXT: addl %edi, %edi
+; X64-NEXT: sarl %edi
+; X64-NEXT: cvtsi2sd %edi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si31_to_double:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: addl %edi, %edi
+; AVX512-NEXT: sarl %edi
+; AVX512-NEXT: vcvtsi2sd %edi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i31 %x to double
+ ret double %conv
+}
+
+define double @test_si33_to_double(i33 %x) {
+; X64-LABEL: test_si33_to_double:
+; X64: # %bb.0: # %entry
+; X64-NEXT: shlq $31, %rdi
+; X64-NEXT: sarq $31, %rdi
+; X64-NEXT: cvtsi2sd %rdi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si33_to_double:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: shlq $31, %rdi
+; AVX512-NEXT: sarq $31, %rdi
+; AVX512-NEXT: vcvtsi2sd %rdi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i33 %x to double
+ ret double %conv
+}
+
+define float @test_si64_to_float(i64 %x) {
+; X64-LABEL: test_si64_to_float:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2ss %rdi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si64_to_float:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtsi2ss %rdi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i64 %x to float
+ ret float %conv
+}
+
+define float @test_si32_to_float(i32 %x) {
+; X64-LABEL: test_si32_to_float:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2ss %edi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si32_to_float:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtsi2ss %edi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i32 %x to float
+ ret float %conv
+}
+
+define float @test_si16_to_float(i16 signext %x) {
+; X64-LABEL: test_si16_to_float:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2ss %edi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si16_to_float:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtsi2ss %edi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i16 %x to float
+ ret float %conv
+}
+
+define float @test_si8_to_float(i8 signext %x) {
+; X64-LABEL: test_si8_to_float:
+; X64: # %bb.0: # %entry
+; X64-NEXT: cvtsi2ss %edi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si8_to_float:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: vcvtsi2ss %edi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i8 %x to float
+ ret float %conv
+}
+
+define float @test_si31_to_float(i31 %x) {
+; X64-LABEL: test_si31_to_float:
+; X64: # %bb.0: # %entry
+; X64-NEXT: addl %edi, %edi
+; X64-NEXT: sarl %edi
+; X64-NEXT: cvtsi2ss %edi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si31_to_float:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: addl %edi, %edi
+; AVX512-NEXT: sarl %edi
+; AVX512-NEXT: vcvtsi2ss %edi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i31 %x to float
+ ret float %conv
+}
+
+define float @test_si33_to_float(i33 %x) {
+; X64-LABEL: test_si33_to_float:
+; X64: # %bb.0: # %entry
+; X64-NEXT: shlq $31, %rdi
+; X64-NEXT: sarq $31, %rdi
+; X64-NEXT: cvtsi2ss %rdi, %xmm0
+; X64-NEXT: retq
+;
+; AVX512-LABEL: test_si33_to_float:
+; AVX512: # %bb.0: # %entry
+; AVX512-NEXT: shlq $31, %rdi
+; AVX512-NEXT: sarq $31, %rdi
+; AVX512-NEXT: vcvtsi2ss %rdi, %xmm0, %xmm0
+; AVX512-NEXT: retq
+entry:
+ %conv = sitofp i33 %x to float
+ ret float %conv
+}
More information about the llvm-commits
mailing list