1; RUN: llc < %s -mtriple=i686-pc-win32 -mcpu=generic | FileCheck %s -check-prefix=FTOL
2; RUN: llc < %s -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=COMPILERRT
3; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s -check-prefix=COMPILERRT
4; RUN: llc < %s -mtriple=x86_64-pc-win32 | FileCheck %s -check-prefix=COMPILERRT
5; RUN: llc < %s -mtriple=x86_64-pc-mingw32 | FileCheck %s -check-prefix=COMPILERRT
6; RUN: llc < %s -mtriple=x86_64-pc-linux | FileCheck %s -check-prefix=COMPILERRT
7; RUN: llc < %s -mattr=-sse -O0 -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=FTOL_2
8
9; Win32 targets use the MSVCRT _ftol2 runtime function for fptoui to i64. This
10; function has a nonstandard calling convention: the input value is expected on
11; the x87 stack instead of the callstack. The input value is popped by the
12; callee. Mingw32 uses normal cdecl compiler-rt functions.
13
14define i64 @double_ui64(double %x) nounwind {
15entry:
16; COMPILERRT: @double_ui64
17; COMPILERRT-NOT: calll __ftol2
18; FTOL: @double_ui64
19; FTOL: fldl
20; FTOL: calll __ftol2
21; FTOL-NOT: fstp
22  %0 = fptoui double %x to i64
23  ret i64 %0
24}
25
26define i64 @float_ui64(float %x) nounwind {
27entry:
28; COMPILERRT: @float_ui64
29; COMPILERRT-NOT: calll __ftol2
30; FTOL: @float_ui64
31; FTOL: flds
32; FTOL: calll __ftol2
33; FTOL-NOT: fstp
34  %0 = fptoui float %x to i64
35  ret i64 %0
36}
37
38define i64 @double_ui64_2(double %x, double %y, double %z) nounwind {
39; COMPILERRT: @double_ui64_2
40; FTOL: @double_ui64_2
41; FTOL_2: @double_ui64_2
42;; stack is empty
43; FTOL_2: fldl
44;; stack is %z
45; FTOL_2: fldl
46;; stack is %y %z
47; FTOL_2: fldl
48;; stack is %x %y %z
49; FTOL_2: fdiv %st(0), %st(1)
50;; stack is %x %1 %z
51; FTOL_2: fsubp %st(2)
52;; stack is %1 %2
53; FTOL_2: fxch
54; FTOL_2-NOT: fld
55; FTOL_2-NOT: fst
56;; stack is %2 %1
57; FTOL_2: calll __ftol2
58; FTOL_2-NOT: fxch
59; FTOL_2-NOT: fld
60; FTOL_2-NOT: fst
61; FTOL_2: calll __ftol2
62;; stack is empty
63
64  %1 = fdiv double %x, %y
65  %2 = fsub double %x, %z
66  %3 = fptoui double %2 to i64
67  %4 = fptoui double %1 to i64
68  %5 = sub i64 %4, %3
69  ret i64 %5
70}
71
72define i64 @double_ui64_3(double %x, double %y, double %z) nounwind {
73; COMPILERRT: @double_ui64_3
74; FTOL: @double_ui64_3
75; FTOL_2: @double_ui64_3
76;; stack is empty
77; FTOL_2: fldl
78;; stack is %z
79; FTOL_2: fldl
80;; stack is %y %z
81; FTOL_2: fldl
82;; stack is %x %y %z
83; FTOL_2: fdiv %st(0), %st(1)
84;; stack is %x %1 %z
85; FTOL_2: fsubp %st(2)
86;; stack is %1 %2
87; FTOL_2-NOT: fxch
88; FTOL_2-NOT: fld
89; FTOL_2-NOT: fst
90;; stack is %1 %2 (still)
91; FTOL_2: calll __ftol2
92; FTOL_2-NOT: fxch
93; FTOL_2-NOT: fld
94; FTOL_2-NOT: fst
95; FTOL_2: calll __ftol2
96;; stack is empty
97
98  %1 = fdiv double %x, %y
99  %2 = fsub double %x, %z
100  %3 = fptoui double %1 to i64
101  %4 = fptoui double %2 to i64
102  %5 = sub i64 %4, %3
103  ret i64 %5
104}
105
106define {double, i64} @double_ui64_4(double %x, double %y) nounwind {
107; COMPILERRT: @double_ui64_4
108; FTOL: @double_ui64_4
109; FTOL_2: @double_ui64_4
110;; stack is empty
111; FTOL_2: fldl
112;; stack is %y
113; FTOL_2: fldl
114;; stack is %x %y
115; FTOL_2: fxch
116;; stack is %y %x
117; FTOL_2: calll __ftol2
118;; stack is %x
119; FTOL_2: fld %st(0)
120;; stack is %x %x
121; FTOL_2: calll __ftol2
122;; stack is %x
123
124  %1 = fptoui double %y to i64
125  %2 = fptoui double %x to i64
126  %3 = sub i64 %2, %1
127  %4 = insertvalue {double, i64} undef, double %x, 0
128  %5 = insertvalue {double, i64} %4, i64 %3, 1
129  ret {double, i64} %5
130}
131
132define i32 @double_ui32_5(double %X) {
133; FTOL: @double_ui32_5
134; FTOL: calll __ftol2
135  %tmp.1 = fptoui double %X to i32
136  ret i32 %tmp.1
137}
138
139define i64 @double_ui64_5(double %X) {
140; FTOL: @double_ui64_5
141; FTOL: calll __ftol2
142  %tmp.1 = fptoui double %X to i64
143  ret i64 %tmp.1
144}
145