From fbce4a478484cb88641053b8f756e96841a863cf Mon Sep 17 00:00:00 2001 From: Pawan Nirpal Date: Wed, 27 Aug 2025 08:29:47 +0200 Subject: [PATCH 1/2] [X86][GISEL] - Legalize G_FPTOUI for X87 --- .../lib/Target/X86/GISel/X86LegalizerInfo.cpp | 80 ++- llvm/test/CodeGen/X86/isel-fp-to-int.ll | 111 ++--- llvm/test/CodeGen/X86/isel-fp-to-uint-x87.ll | 465 ++++++++++++++++++ 3 files changed, 587 insertions(+), 69 deletions(-) create mode 100644 llvm/test/CodeGen/X86/isel-fp-to-uint-x87.ll diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp index 7fe58539cd4ec..f15080d9f8739 100644 --- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp @@ -496,12 +496,17 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, .widenScalarToNextPow2(1); getActionDefinitionsBuilder(G_FPTOUI) - .legalFor(HasAVX512, {{s32, s32}, {s32, s64}, {s64, s32}, {s64, s64}}) + .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); + if (!HasAVX512 && (((typeIs(1, s32)(Query) && HasSSE1) || + (typeIs(1, s64)(Query) && HasSSE2)) && + scalarNarrowerThan(0, Is64Bit ? 64 : 32)(Query))) + return true; + return typeInSet(0, {s16, s32, s64})(Query) && + typeInSet(1, {s32, s64, s80})(Query); }) // TODO: replace with customized legalization using // specifics of cvttsd2si. The selection of this node requires @@ -513,7 +518,7 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, (HasSSE2 && typeIs(1, s64)(Query))) && (Is64Bit && typeIs(0, s64)(Query)); }) - .clampScalar(0, s32, sMaxScalar) + .clampScalar(0, s16, sMaxScalar) .widenScalarToNextPow2(0) .clampScalar(1, s32, HasSSE2 ? s64 : s32) .widenScalarToNextPow2(1); @@ -744,7 +749,68 @@ bool X86LegalizerInfo::legalizeFPTOUI(MachineInstr &MI, return true; } - return false; + MachineFunction &MF = *MI.getMF(); + TypeSize MemSize = DstTy.getSizeInBytes(); + MachinePointerInfo PtrInfo; + Align Alignmt = Helper.getStackTemporaryAlignment(DstTy); + auto SlotPointer = Helper.createStackTemporary(MemSize, Alignmt, PtrInfo); + + if (DstTy == s64) { + // As x87 cmov is unsupported at the momement, we need to use the following + // arithmatic algorithm to do fptoui computation. y_tmp = y - sint_max. + // y_res = fptosi(y - !sign(y_tmp)sint_max) + !sign(y_tmp)sint_max + + const LLT s1 = LLT::scalar(1); + const LLT s80 = LLT::scalar(80); + const llvm::fltSemantics &Sem = + (SrcTy != s80 ? getFltSemanticForLLT(SrcTy) + : APFloat::x87DoubleExtended()); + + APFloat SintMaxFP = APFloat::getZero(Sem); + SintMaxFP.convertFromAPInt(APInt::getOneBitSet(64, 63), false, + APFloat::rmNearestTiesToEven); + Register SintMax = MIRBuilder.buildFConstant(SrcTy, SintMaxFP).getReg(0); + + Register YTmp = MIRBuilder.buildFSub(SrcTy, Src, SintMax).getReg(0); + + APFloat ZeroFP = APFloat::getZero(Sem); + Register Zero = MIRBuilder.buildFConstant(SrcTy, ZeroFP).getReg(0); + Register Sign = + MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, s1, YTmp, Zero).getReg(0); + + Register One = MIRBuilder.buildConstant(s1, 1).getReg(0); + Register NSign = MIRBuilder.buildXor(s1, Sign, One).getReg(0); + + Register NSign64 = MIRBuilder.buildZExt(s64, NSign).getReg(0); + + Register NSignF = MIRBuilder.buildSITOFP(SrcTy, NSign64).getReg(0); + Register Offset = MIRBuilder.buildFMul(SrcTy, NSignF, SintMax).getReg(0); + + Register YAdj = MIRBuilder.buildFSub(SrcTy, Src, Offset).getReg(0); + + Register YAdjI = MIRBuilder.buildFPTOSI(s64, YAdj).getReg(0); + + Register OffsetI = MIRBuilder.buildFPTOSI(s64, Offset).getReg(0); + + Register Result = MIRBuilder.buildAdd(s64, YAdjI, OffsetI).getReg(0); + + MIRBuilder.buildCopy(Dst, Result); + MI.eraseFromParent(); + return true; + } + + MachineMemOperand *StoreMMO = MF.getMachineMemOperand( + PtrInfo, MachineMemOperand::MOStore, MemSize, Align(MemSize)); + + MIRBuilder.buildInstr(X86::G_FIST) + .addUse(Src) + .addUse(SlotPointer.getReg(0)) + .addMemOperand(StoreMMO); + + MIRBuilder.buildLoad(Dst, SlotPointer, PtrInfo, Align(MemSize)); + MI.eraseFromParent(); + + return true; } bool X86LegalizerInfo::legalizeUITOFP(MachineInstr &MI, diff --git a/llvm/test/CodeGen/X86/isel-fp-to-int.ll b/llvm/test/CodeGen/X86/isel-fp-to-int.ll index fae3db6ad0afa..407996bf6de88 100644 --- a/llvm/test/CodeGen/X86/isel-fp-to-int.ll +++ b/llvm/test/CodeGen/X86/isel-fp-to-int.ll @@ -18,18 +18,22 @@ define i64 @test_double_to_ui64(double %x) { ; ; 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: movsd {{.*#+}} xmm3 = [0.0E+0,0.0E+0] +; GISEL-X64-NEXT: ucomisd %xmm2, %xmm3 +; GISEL-X64-NEXT: seta %al +; GISEL-X64-NEXT: xorb $1, %al +; GISEL-X64-NEXT: movzbl %al, %eax +; GISEL-X64-NEXT: andq $1, %rax +; GISEL-X64-NEXT: xorps %xmm2, %xmm2 +; GISEL-X64-NEXT: cvtsi2sd %rax, %xmm2 +; GISEL-X64-NEXT: mulsd %xmm1, %xmm2 +; GISEL-X64-NEXT: subsd %xmm2, %xmm0 +; GISEL-X64-NEXT: cvttsd2si %xmm0, %rcx +; GISEL-X64-NEXT: cvttsd2si %xmm2, %rax +; GISEL-X64-NEXT: addq %rcx, %rax ; GISEL-X64-NEXT: retq ; ; AVX512-LABEL: test_double_to_ui64: @@ -64,17 +68,11 @@ define zeroext i16 @test_double_to_ui16(double %x) { ; 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 +; AVX512-LABEL: test_double_to_ui16: +; AVX512: # %bb.0: # %entry +; AVX512-NEXT: vcvttsd2si %xmm0, %eax +; AVX512-NEXT: # kill: def $ax killed $ax killed $eax +; AVX512-NEXT: retq entry: %conv = fptoui double %x to i16 ret i16 %conv @@ -87,17 +85,11 @@ define zeroext i8 @test_double_to_ui8(double %x) { ; 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 +; AVX512-LABEL: test_double_to_ui8: +; AVX512: # %bb.0: # %entry +; AVX512-NEXT: vcvttsd2si %xmm0, %eax +; AVX512-NEXT: # kill: def $al killed $al killed $eax +; AVX512-NEXT: retq entry: %conv = fptoui double %x to i8 ret i8 %conv @@ -117,18 +109,22 @@ define i64 @test_float_to_ui64(float %x) { ; ; 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: movss {{.*#+}} xmm3 = [0.0E+0,0.0E+0,0.0E+0,0.0E+0] +; GISEL-X64-NEXT: ucomiss %xmm2, %xmm3 +; GISEL-X64-NEXT: seta %al +; GISEL-X64-NEXT: xorb $1, %al +; GISEL-X64-NEXT: movzbl %al, %eax +; GISEL-X64-NEXT: andq $1, %rax +; GISEL-X64-NEXT: xorps %xmm2, %xmm2 +; GISEL-X64-NEXT: cvtsi2ss %rax, %xmm2 +; GISEL-X64-NEXT: mulss %xmm1, %xmm2 +; GISEL-X64-NEXT: subss %xmm2, %xmm0 +; GISEL-X64-NEXT: cvttss2si %xmm0, %rcx +; GISEL-X64-NEXT: cvttss2si %xmm2, %rax +; GISEL-X64-NEXT: addq %rcx, %rax ; GISEL-X64-NEXT: retq ; ; AVX512-LABEL: test_float_to_ui64: @@ -163,17 +159,11 @@ define zeroext i16 @test_float_to_ui16(float %x) { ; 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 +; AVX512-LABEL: test_float_to_ui16: +; AVX512: # %bb.0: # %entry +; AVX512-NEXT: vcvttss2si %xmm0, %eax +; AVX512-NEXT: # kill: def $ax killed $ax killed $eax +; AVX512-NEXT: retq entry: %conv = fptoui float %x to i16 ret i16 %conv @@ -186,17 +176,11 @@ define zeroext i8 @test_float_to_ui8(float %x) { ; 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 +; AVX512-LABEL: test_float_to_ui8: +; AVX512: # %bb.0: # %entry +; AVX512-NEXT: vcvttss2si %xmm0, %eax +; AVX512-NEXT: # kill: def $al killed $al killed $eax +; AVX512-NEXT: retq entry: %conv = fptoui float %x to i8 ret i8 %conv @@ -389,3 +373,6 @@ entry: %conv = fptosi float %x to i33 ret i33 %conv } +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; GISEL-AVX512: {{.*}} +; SDAG-AVX512: {{.*}} diff --git a/llvm/test/CodeGen/X86/isel-fp-to-uint-x87.ll b/llvm/test/CodeGen/X86/isel-fp-to-uint-x87.ll new file mode 100644 index 0000000000000..6a143d69e859b --- /dev/null +++ b/llvm/test/CodeGen/X86/isel-fp-to-uint-x87.ll @@ -0,0 +1,465 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse,-sse2 -global-isel=0 | FileCheck %s --check-prefixes X64,SDAG-X64 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse,-sse2 -global-isel -global-isel-abort=1 | FileCheck %s --check-prefixes X64,GISEL-X64 + +define void @test_float_to_uint64(float %f, ptr %result) { +; SDAG-X64-LABEL: test_float_to_uint64: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: flds {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}}(%rip) +; SDAG-X64-NEXT: xorl %eax, %eax +; SDAG-X64-NEXT: fucomi %st(1), %st +; SDAG-X64-NEXT: setbe %al +; SDAG-X64-NEXT: fldz +; SDAG-X64-NEXT: fcmovbe %st(1), %st +; SDAG-X64-NEXT: fstp %st(1) +; SDAG-X64-NEXT: fsubrp %st, %st(1) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx +; SDAG-X64-NEXT: orl $3072, %ecx # imm = 0xC00 +; SDAG-X64-NEXT: movw %cx, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: shlq $63, %rax +; SDAG-X64-NEXT: xorq -{{[0-9]+}}(%rsp), %rax +; SDAG-X64-NEXT: movq %rax, (%rdi) +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_float_to_uint64: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: flds {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}}(%rip) +; GISEL-X64-NEXT: fld %st(0) +; GISEL-X64-NEXT: fsubrs {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldz +; GISEL-X64-NEXT: fucompi %st(1), %st +; GISEL-X64-NEXT: fstp %st(0) +; GISEL-X64-NEXT: seta %al +; GISEL-X64-NEXT: xorb $1, %al +; GISEL-X64-NEXT: movzbl %al, %eax +; GISEL-X64-NEXT: andq $1, %rax +; GISEL-X64-NEXT: movq %rax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fildll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fmulp %st, %st(1) +; GISEL-X64-NEXT: fsubr %st, %st(1) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fxch %st(1) +; GISEL-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movq -{{[0-9]+}}(%rsp), %rax +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx +; GISEL-X64-NEXT: orl $3072, %ecx # imm = 0xC00 +; GISEL-X64-NEXT: movw %cx, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: addq -{{[0-9]+}}(%rsp), %rax +; GISEL-X64-NEXT: movq %rax, (%rdi) +; GISEL-X64-NEXT: retq +entry: + %conv = fptoui float %f to i64 + store i64 %conv, ptr %result, align 8 + ret void +} + +define void @test_double_to_uint64(double %d, ptr %result) { +; SDAG-X64-LABEL: test_double_to_uint64: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: fldl {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}}(%rip) +; SDAG-X64-NEXT: xorl %eax, %eax +; SDAG-X64-NEXT: fucomi %st(1), %st +; SDAG-X64-NEXT: setbe %al +; SDAG-X64-NEXT: fldz +; SDAG-X64-NEXT: fcmovbe %st(1), %st +; SDAG-X64-NEXT: fstp %st(1) +; SDAG-X64-NEXT: fsubrp %st, %st(1) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx +; SDAG-X64-NEXT: orl $3072, %ecx # imm = 0xC00 +; SDAG-X64-NEXT: movw %cx, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: shlq $63, %rax +; SDAG-X64-NEXT: xorq -{{[0-9]+}}(%rsp), %rax +; SDAG-X64-NEXT: movq %rax, (%rdi) +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_double_to_uint64: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: fldl {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldl {{\.?LCPI[0-9]+_[0-9]+}}(%rip) +; GISEL-X64-NEXT: fld %st(0) +; GISEL-X64-NEXT: fsubrl {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldz +; GISEL-X64-NEXT: fucompi %st(1), %st +; GISEL-X64-NEXT: fstp %st(0) +; GISEL-X64-NEXT: seta %al +; GISEL-X64-NEXT: xorb $1, %al +; GISEL-X64-NEXT: movzbl %al, %eax +; GISEL-X64-NEXT: andq $1, %rax +; GISEL-X64-NEXT: movq %rax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fildll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fmulp %st, %st(1) +; GISEL-X64-NEXT: fsubr %st, %st(1) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fxch %st(1) +; GISEL-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movq -{{[0-9]+}}(%rsp), %rax +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx +; GISEL-X64-NEXT: orl $3072, %ecx # imm = 0xC00 +; GISEL-X64-NEXT: movw %cx, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: addq -{{[0-9]+}}(%rsp), %rax +; GISEL-X64-NEXT: movq %rax, (%rdi) +; GISEL-X64-NEXT: retq +entry: + %conv = fptoui double %d to i64 + store i64 %conv, ptr %result, align 8 + ret void +} + +define void @test_long_double_to_uint64(x86_fp80 %ld, ptr %result) { +; SDAG-X64-LABEL: test_long_double_to_uint64: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}}(%rip) +; SDAG-X64-NEXT: xorl %eax, %eax +; SDAG-X64-NEXT: fucomi %st(1), %st +; SDAG-X64-NEXT: setbe %al +; SDAG-X64-NEXT: fldz +; SDAG-X64-NEXT: fcmovbe %st(1), %st +; SDAG-X64-NEXT: fstp %st(1) +; SDAG-X64-NEXT: fsubrp %st, %st(1) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx +; SDAG-X64-NEXT: orl $3072, %ecx # imm = 0xC00 +; SDAG-X64-NEXT: movw %cx, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: shlq $63, %rax +; SDAG-X64-NEXT: xorq -{{[0-9]+}}(%rsp), %rax +; SDAG-X64-NEXT: movq %rax, (%rdi) +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_long_double_to_uint64: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldt {{\.?LCPI[0-9]+_[0-9]+}}(%rip) +; GISEL-X64-NEXT: fld %st(1) +; GISEL-X64-NEXT: fsub %st(1), %st +; GISEL-X64-NEXT: fldz +; GISEL-X64-NEXT: fucompi %st(1), %st +; GISEL-X64-NEXT: fstp %st(0) +; GISEL-X64-NEXT: seta %al +; GISEL-X64-NEXT: xorb $1, %al +; GISEL-X64-NEXT: movzbl %al, %eax +; GISEL-X64-NEXT: andq $1, %rax +; GISEL-X64-NEXT: movq %rax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fildll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fmulp %st, %st(1) +; GISEL-X64-NEXT: fsubr %st, %st(1) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fxch %st(1) +; GISEL-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movq -{{[0-9]+}}(%rsp), %rax +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx +; GISEL-X64-NEXT: orl $3072, %ecx # imm = 0xC00 +; GISEL-X64-NEXT: movw %cx, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: addq -{{[0-9]+}}(%rsp), %rax +; GISEL-X64-NEXT: movq %rax, (%rdi) +; GISEL-X64-NEXT: retq +entry: + %conv = fptoui x86_fp80 %ld to i64 + store i64 %conv, ptr %result, align 8 + ret void +} + +define void @test_float_to_uint32(float %f, ptr %result) { +; SDAG-X64-LABEL: test_float_to_uint32: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: flds {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: movl %eax, (%rdi) +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_float_to_uint32: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: flds {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movq -{{[0-9]+}}(%rsp), %rax +; GISEL-X64-NEXT: movl %eax, (%rdi) +; GISEL-X64-NEXT: retq +entry: + %conv = fptoui float %f to i32 + store i32 %conv, ptr %result, align 4 + ret void +} + +define void @test_double_to_uint32(double %d, ptr %result) { +; SDAG-X64-LABEL: test_double_to_uint32: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: fldl {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: movl %eax, (%rdi) +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_double_to_uint32: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: fldl {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movq -{{[0-9]+}}(%rsp), %rax +; GISEL-X64-NEXT: movl %eax, (%rdi) +; GISEL-X64-NEXT: retq +entry: + %conv = fptoui double %d to i32 + store i32 %conv, ptr %result, align 4 + ret void +} + +define void @test_long_double_to_uint32(x86_fp80 %ld, ptr %result) { +; SDAG-X64-LABEL: test_long_double_to_uint32: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: movl %eax, (%rdi) +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_long_double_to_uint32: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistpll -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movq -{{[0-9]+}}(%rsp), %rax +; GISEL-X64-NEXT: movl %eax, (%rdi) +; GISEL-X64-NEXT: retq +entry: + %conv = fptoui x86_fp80 %ld to i32 + store i32 %conv, ptr %result, align 4 + ret void +} + +define void @test_float_to_uint16(float %f, ptr %result) { +; X64-LABEL: test_float_to_uint16: +; X64: # %bb.0: # %entry +; X64-NEXT: flds {{[0-9]+}}(%rsp) +; X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; X64-NEXT: orl $3072, %eax # imm = 0xC00 +; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; X64-NEXT: fistpl -{{[0-9]+}}(%rsp) +; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; X64-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; X64-NEXT: movw %ax, (%rdi) +; X64-NEXT: retq +entry: + %conv = fptoui float %f to i16 + store i16 %conv, ptr %result, align 2 + ret void +} + +define void @test_double_to_uint16(double %d, ptr %result) { +; X64-LABEL: test_double_to_uint16: +; X64: # %bb.0: # %entry +; X64-NEXT: fldl {{[0-9]+}}(%rsp) +; X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; X64-NEXT: orl $3072, %eax # imm = 0xC00 +; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; X64-NEXT: fistpl -{{[0-9]+}}(%rsp) +; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; X64-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; X64-NEXT: movw %ax, (%rdi) +; X64-NEXT: retq +entry: + %conv = fptoui double %d to i16 + store i16 %conv, ptr %result, align 2 + ret void +} + +define void @test_long_double_to_uint16(x86_fp80 %ld, ptr %result) { +; X64-LABEL: test_long_double_to_uint16: +; X64: # %bb.0: # %entry +; X64-NEXT: fldt {{[0-9]+}}(%rsp) +; X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; X64-NEXT: orl $3072, %eax # imm = 0xC00 +; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; X64-NEXT: fistpl -{{[0-9]+}}(%rsp) +; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; X64-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; X64-NEXT: movw %ax, (%rdi) +; X64-NEXT: retq +entry: + %conv = fptoui x86_fp80 %ld to i16 + store i16 %conv, ptr %result, align 2 + ret void +} + +define void @test_float_to_uint8(float %f, ptr %result) { +; SDAG-X64-LABEL: test_float_to_uint8: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: flds {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistps -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: movb %al, (%rdi) +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_float_to_uint8: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: flds {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistpl -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: movb %al, (%rdi) +; GISEL-X64-NEXT: retq +entry: + %conv = fptoui float %f to i8 + store i8 %conv, ptr %result, align 1 + ret void +} + +define void @test_double_to_uint8(double %d, ptr %result) { +; SDAG-X64-LABEL: test_double_to_uint8: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: fldl {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistps -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: movb %al, (%rdi) +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_double_to_uint8: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: fldl {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistpl -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: movb %al, (%rdi) +; GISEL-X64-NEXT: retq +entry: + %conv = fptoui double %d to i8 + store i8 %conv, ptr %result, align 1 + ret void +} + +define void @test_long_double_to_uint8(x86_fp80 %ld, ptr %result) { +; SDAG-X64-LABEL: test_long_double_to_uint8: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistps -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: movb %al, (%rdi) +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_long_double_to_uint8: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistpl -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: movb %al, (%rdi) +; GISEL-X64-NEXT: retq +entry: + %conv = fptoui x86_fp80 %ld to i8 + store i8 %conv, ptr %result, align 1 + ret void +} \ No newline at end of file From 9bf22ad26cbb036af07aaa5e0cf100ca63d19b4e Mon Sep 17 00:00:00 2001 From: Pawan Nirpal Date: Mon, 1 Sep 2025 19:28:18 +0200 Subject: [PATCH 2/2] [X86][GISEL] - Legalize G_UITOFP in X87 mode --- .../lib/Target/X86/GISel/X86LegalizerInfo.cpp | 18 ++- llvm/test/CodeGen/X86/isel-uint-to-fp-x87.ll | 132 ++++++++++++++++++ 2 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 llvm/test/CodeGen/X86/isel-uint-to-fp-x87.ll diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp index f15080d9f8739..1f23c7fe33251 100644 --- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp @@ -478,10 +478,13 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, getActionDefinitionsBuilder(G_UITOFP) .legalFor(HasAVX512, {{s32, s32}, {s32, s64}, {s64, s32}, {s64, s64}}) .customIf([=](const LegalityQuery &Query) { - return !HasAVX512 && - ((HasSSE1 && typeIs(0, s32)(Query)) || - (HasSSE2 && typeIs(0, s64)(Query))) && - scalarNarrowerThan(1, Is64Bit ? 64 : 32)(Query); + if (!HasAVX512 && + ((HasSSE1 && typeIs(0, s32)(Query)) || + (HasSSE2 && typeIs(0, s64)(Query))) && + scalarNarrowerThan(1, Is64Bit ? 64 : 32)(Query)) + return true; + return typeInSet(0, {s32, s64, s80})(Query) && + typeInSet(1, {s8, s16, s32, s64})(Query); }) .lowerIf([=](const LegalityQuery &Query) { // Lower conversions from s64 @@ -823,7 +826,12 @@ bool X86LegalizerInfo::legalizeUITOFP(MachineInstr &MI, // Simply reuse SITOFP when it is possible to widen the type if (SrcTy.getSizeInBits() <= 32) { - auto Ext = MIRBuilder.buildZExt(SrcTy == s32 ? s64 : s32, Src); + const LLT s8 = LLT::scalar(8); + const LLT s16 = LLT::scalar(16); + auto Ext = MIRBuilder.buildZExt((SrcTy == s8 ? s16 + : SrcTy == s32 ? s64 + : s32), + Src); MIRBuilder.buildSITOFP(Dst, Ext); MI.eraseFromParent(); return true; diff --git a/llvm/test/CodeGen/X86/isel-uint-to-fp-x87.ll b/llvm/test/CodeGen/X86/isel-uint-to-fp-x87.ll new file mode 100644 index 0000000000000..0d3d33933d786 --- /dev/null +++ b/llvm/test/CodeGen/X86/isel-uint-to-fp-x87.ll @@ -0,0 +1,132 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse,-sse2 -global-isel=0 | FileCheck %s --check-prefixes X64,SDAG-X64 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse,-sse2 -global-isel -global-isel-abort=1 | FileCheck %s --check-prefixes X64,GISEL-X64 + +define void @test_ui32_to_fp(i32 %x, ptr %p) { +; X64-LABEL: test_ui32_to_fp: +; X64: # %bb.0: # %entry +; X64-NEXT: movl %edi, %eax +; X64-NEXT: movq %rax, -{{[0-9]+}}(%rsp) +; X64-NEXT: fildll -{{[0-9]+}}(%rsp) +; X64-NEXT: fstps (%rsi) +; X64-NEXT: retq +entry: + %conv = uitofp i32 %x to float + store float %conv, ptr %p, align 4 + ret void +} + +define void @test_ui32_to_fp_double(i32 %x, ptr %p) { +; X64-LABEL: test_ui32_to_fp_double: +; X64: # %bb.0: # %entry +; X64-NEXT: movl %edi, %eax +; X64-NEXT: movq %rax, -{{[0-9]+}}(%rsp) +; X64-NEXT: fildll -{{[0-9]+}}(%rsp) +; X64-NEXT: fstpl (%rsi) +; X64-NEXT: retq +entry: + %conv = uitofp i32 %x to double + store double %conv, ptr %p, align 8 + ret void +} + +define void @test_ui32_to_fp_x86_fp80(i32 %x, ptr %p) { +; X64-LABEL: test_ui32_to_fp_x86_fp80: +; X64: # %bb.0: # %entry +; X64-NEXT: movl %edi, %eax +; X64-NEXT: movq %rax, -{{[0-9]+}}(%rsp) +; X64-NEXT: fildll -{{[0-9]+}}(%rsp) +; X64-NEXT: fstpt (%rsi) +; X64-NEXT: retq +entry: + %conv = uitofp i32 %x to x86_fp80 + store x86_fp80 %conv, ptr %p, align 16 + ret void +} + +define void @test_ui16_to_fp(i16 %x, ptr %p) { +; X64-LABEL: test_ui16_to_fp: +; X64: # %bb.0: # %entry +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: movl %eax, -{{[0-9]+}}(%rsp) +; X64-NEXT: fildl -{{[0-9]+}}(%rsp) +; X64-NEXT: fstps (%rsi) +; X64-NEXT: retq +entry: + %conv = uitofp i16 %x to float + store float %conv, ptr %p, align 4 + ret void +} + +define void @test_ui16_to_fp_double(i16 %x, ptr %p) { +; X64-LABEL: test_ui16_to_fp_double: +; X64: # %bb.0: # %entry +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: movl %eax, -{{[0-9]+}}(%rsp) +; X64-NEXT: fildl -{{[0-9]+}}(%rsp) +; X64-NEXT: fstpl (%rsi) +; X64-NEXT: retq +entry: + %conv = uitofp i16 %x to double + store double %conv, ptr %p, align 8 + ret void +} + +define void @test_ui16_to_fp_x86_fp80(i16 %x, ptr %p) { +; X64-LABEL: test_ui16_to_fp_x86_fp80: +; X64: # %bb.0: # %entry +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: movl %eax, -{{[0-9]+}}(%rsp) +; X64-NEXT: fildl -{{[0-9]+}}(%rsp) +; X64-NEXT: fstpt (%rsi) +; X64-NEXT: retq +entry: + %conv = uitofp i16 %x to x86_fp80 + store x86_fp80 %conv, ptr %p, align 16 + ret void +} + +define void @test_ui8_to_fp(i8 %x, ptr %p) { +; X64-LABEL: test_ui8_to_fp: +; X64: # %bb.0: # %entry +; X64-NEXT: movzbl %dil, %eax +; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; X64-NEXT: filds -{{[0-9]+}}(%rsp) +; X64-NEXT: fstps (%rsi) +; X64-NEXT: retq +entry: + %conv = uitofp i8 %x to float + store float %conv, ptr %p, align 4 + ret void +} + +define void @test_ui8_to_fp_double(i8 %x, ptr %p) { +; X64-LABEL: test_ui8_to_fp_double: +; X64: # %bb.0: # %entry +; X64-NEXT: movzbl %dil, %eax +; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; X64-NEXT: filds -{{[0-9]+}}(%rsp) +; X64-NEXT: fstpl (%rsi) +; X64-NEXT: retq +entry: + %conv = uitofp i8 %x to double + store double %conv, ptr %p, align 8 + ret void +} + +define void @test_ui8_to_fp_x86_fp80(i8 %x, ptr %p) { +; X64-LABEL: test_ui8_to_fp_x86_fp80: +; X64: # %bb.0: # %entry +; X64-NEXT: movzbl %dil, %eax +; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; X64-NEXT: filds -{{[0-9]+}}(%rsp) +; X64-NEXT: fstpt (%rsi) +; X64-NEXT: retq +entry: + %conv = uitofp i8 %x to x86_fp80 + store x86_fp80 %conv, ptr %p, align 16 + ret void +} +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; GISEL-X64: {{.*}} +; SDAG-X64: {{.*}}