[llvm] [X86][GISEL] - Legalize G_FPTOUI for X87 (PR #155562)
Pawan Nirpal via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 26 23:31:04 PDT 2025
https://github.com/pawan-nirpal-031 created https://github.com/llvm/llvm-project/pull/155562
None
>From fbce4a478484cb88641053b8f756e96841a863cf Mon Sep 17 00:00:00 2001
From: Pawan Nirpal <pawan.anil.nirpal at intel.com>
Date: Wed, 27 Aug 2025 08:29:47 +0200
Subject: [PATCH] [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
More information about the llvm-commits
mailing list