blob: 14591248f354ee5c37139451dbe518c0c0597602 [file] [log] [blame]
; RUN: llc < %s -mtriple=i686-pc-win32 -mcpu=generic | FileCheck %s -check-prefix=FTOL
; RUN: llc < %s -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=COMPILERRT
; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s -check-prefix=COMPILERRT
; RUN: llc < %s -mtriple=x86_64-pc-win32 | FileCheck %s -check-prefix=COMPILERRT
; RUN: llc < %s -mtriple=x86_64-pc-mingw32 | FileCheck %s -check-prefix=COMPILERRT
; RUN: llc < %s -mtriple=x86_64-pc-linux | FileCheck %s -check-prefix=COMPILERRT
; RUN: llc < %s -mattr=-sse -O0 -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=FTOL_2
; Win32 targets use the MSVCRT _ftol2 runtime function for fptoui to i64. This
; function has a nonstandard calling convention: the input value is expected on
; the x87 stack instead of the callstack. The input value is popped by the
; callee. Mingw32 uses normal cdecl compiler-rt functions.
define i64 @double_ui64(double %x) nounwind {
entry:
; COMPILERRT: @double_ui64
; COMPILERRT-NOT: calll __ftol2
; FTOL: @double_ui64
; FTOL: fldl
; FTOL: calll __ftol2
; FTOL-NOT: fstp
%0 = fptoui double %x to i64
ret i64 %0
}
define i64 @float_ui64(float %x) nounwind {
entry:
; COMPILERRT: @float_ui64
; COMPILERRT-NOT: calll __ftol2
; FTOL: @float_ui64
; FTOL: flds
; FTOL: calll __ftol2
; FTOL-NOT: fstp
%0 = fptoui float %x to i64
ret i64 %0
}
define i64 @double_ui64_2(double %x, double %y, double %z) nounwind {
; COMPILERRT: @double_ui64_2
; FTOL: @double_ui64_2
; FTOL_2: @double_ui64_2
;; stack is empty
; FTOL_2: fldl
;; stack is %z
; FTOL_2: fldl
;; stack is %y %z
; FTOL_2: fldl
;; stack is %x %y %z
; FTOL_2: fdiv %st(0), %st(1)
;; stack is %x %1 %z
; FTOL_2: fsubp %st(2)
;; stack is %1 %2
; FTOL_2: fxch
; FTOL_2-NOT: fld
; FTOL_2-NOT: fst
;; stack is %2 %1
; FTOL_2: calll __ftol2
; FTOL_2-NOT: fxch
; FTOL_2-NOT: fld
; FTOL_2-NOT: fst
; FTOL_2: calll __ftol2
;; stack is empty
%1 = fdiv double %x, %y
%2 = fsub double %x, %z
%3 = fptoui double %2 to i64
%4 = fptoui double %1 to i64
%5 = sub i64 %4, %3
ret i64 %5
}
define i64 @double_ui64_3(double %x, double %y, double %z) nounwind {
; COMPILERRT: @double_ui64_3
; FTOL: @double_ui64_3
; FTOL_2: @double_ui64_3
;; stack is empty
; FTOL_2: fldl
;; stack is %z
; FTOL_2: fldl
;; stack is %y %z
; FTOL_2: fldl
;; stack is %x %y %z
; FTOL_2: fdiv %st(0), %st(1)
;; stack is %x %1 %z
; FTOL_2: fsubp %st(2)
;; stack is %1 %2
; FTOL_2-NOT: fxch
; FTOL_2-NOT: fld
; FTOL_2-NOT: fst
;; stack is %1 %2 (still)
; FTOL_2: calll __ftol2
; FTOL_2-NOT: fxch
; FTOL_2-NOT: fld
; FTOL_2-NOT: fst
; FTOL_2: calll __ftol2
;; stack is empty
%1 = fdiv double %x, %y
%2 = fsub double %x, %z
%3 = fptoui double %1 to i64
%4 = fptoui double %2 to i64
%5 = sub i64 %4, %3
ret i64 %5
}
define {double, i64} @double_ui64_4(double %x, double %y) nounwind {
; COMPILERRT: @double_ui64_4
; FTOL: @double_ui64_4
; FTOL_2: @double_ui64_4
;; stack is empty
; FTOL_2: fldl
;; stack is %y
; FTOL_2: fldl
;; stack is %x %y
; FTOL_2: fxch
;; stack is %y %x
; FTOL_2: calll __ftol2
;; stack is %x
; FTOL_2: fld %st(0)
;; stack is %x %x
; FTOL_2: calll __ftol2
;; stack is %x
%1 = fptoui double %y to i64
%2 = fptoui double %x to i64
%3 = sub i64 %2, %1
%4 = insertvalue {double, i64} undef, double %x, 0
%5 = insertvalue {double, i64} %4, i64 %3, 1
ret {double, i64} %5
}
define i32 @double_ui32_5(double %X) {
; FTOL: @double_ui32_5
; FTOL: calll __ftol2
%tmp.1 = fptoui double %X to i32
ret i32 %tmp.1
}
define i64 @double_ui64_5(double %X) {
; FTOL: @double_ui64_5
; FTOL: calll __ftol2
%tmp.1 = fptoui double %X to i64
ret i64 %tmp.1
}