; 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 }