Fix assertion failure with fp128 to unsigned i64 conversion
[oota-llvm.git] / test / CodeGen / X86 / scalar-fp-to-i64.ll
1 ; Check that scalar FP conversions to signed and unsigned int64 are using
2 ; reasonable sequences, across platforms and target switches.
3 ;
4 ; The signed case is straight forward, and the tests here basically
5 ; ensure successful compilation (f80 with avx512 was broken at one point).
6 ;
7 ; For the unsigned case there are many possible sequences, so to avoid
8 ; a fragile test we just check for the presence of a few key instructions.
9 ; AVX512 on Intel64 can use vcvtts[ds]2usi directly for float and double.
10 ; Otherwise the sequence will involve an FP subtract (fsub, subss or subsd),
11 ; and a truncating conversion (cvtts[ds]2si, fisttp, or fnstcw+fist).  When
12 ; both a subtract and fnstcw are needed, they can occur in either order.
13 ;
14 ; The interesting subtargets are AVX512F (vcvtts[ds]2usi), SSE3 (fisttp),
15 ; SSE2 (cvtts[ds]2si) and vanilla X87 (fnstcw+fist, 32-bit only).
16 ;
17 ; RUN: llc < %s -mtriple=i386-pc-windows-msvc     -mattr=+avx512f | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512_32
18 ; RUN: llc < %s -mtriple=i386-unknown-linux-gnu   -mattr=+avx512f | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512_32
19 ; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc   -mattr=+avx512f | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512_64
20 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+avx512f | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512_64
21 ; RUN: llc < %s -mtriple=i386-pc-windows-msvc     -mattr=+sse3 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE3_32
22 ; RUN: llc < %s -mtriple=i386-unknown-linux-gnu   -mattr=+sse3 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE3_32
23 ; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc   -mattr=+sse3 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE3_64
24 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+sse3 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE3_64
25 ; RUN: llc < %s -mtriple=i386-pc-windows-msvc     -mattr=+sse2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE2_32
26 ; RUN: llc < %s -mtriple=i386-unknown-linux-gnu   -mattr=+sse2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE2_32
27 ; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc   -mattr=+sse2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE2_64
28 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+sse2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE2_64
29 ; RUN: llc < %s -mtriple=i386-pc-windows-msvc     -mattr=-sse  | FileCheck %s --check-prefix=CHECK --check-prefix=X87
30 ; RUN: llc < %s -mtriple=i386-unknown-linux-gnu   -mattr=-sse  | FileCheck %s --check-prefix=CHECK --check-prefix=X87
31
32 ; CHECK-LABEL: f_to_u64
33 ; X87-DAG: fsub
34 ; X87-DAG: fnstcw
35 ; X87: fist
36 ; SSE2_32-DAG: {{subss|fsub}}
37 ; SSE2_32-DAG: fnstcw
38 ; SSE2_32: fist
39 ; SSE2_64: subss
40 ; SSE2_64: cvttss2si
41 ; SSE3_32: {{subss|fsub}}
42 ; SSE3_32: fistt
43 ; SSE3_64: subss
44 ; SSE3_64: cvttss2si
45 ; AVX512_32: {{subss|fsub}}
46 ; AVX512_32: fistt
47 ; AVX512_64: vcvttss2usi
48 ; CHECK: ret
49 define i64 @f_to_u64(float %a) nounwind {
50   %r = fptoui float %a to i64
51   ret i64 %r
52 }
53
54 ; CHECK-LABEL: f_to_s64
55 ; X87: fnstcw
56 ; X87: fist
57 ; SSE2_32: fnstcw
58 ; SSE2_32: fist
59 ; SSE2_64: cvttss2si
60 ; SSE3_32: fistt
61 ; SSE3_64: cvttss2si
62 ; AVX512_32: fistt
63 ; AVX512_64: vcvttss2si
64 ; CHECK: ret
65 define i64 @f_to_s64(float %a) nounwind {
66   %r = fptosi float %a to i64
67   ret i64 %r
68 }
69
70 ; CHECK-LABEL: d_to_u64
71 ; X87-DAG: fsub
72 ; X87-DAG: fnstcw
73 ; X87: fist
74 ; SSE2_32-DAG: {{subsd|fsub}}
75 ; SSE2_32-DAG: fnstcw
76 ; SSE2_32: fist
77 ; SSE2_64: subsd
78 ; SSE2_64: cvttsd2si
79 ; SSE3_32: {{subsd|fsub}}
80 ; SSE3_32: fistt
81 ; SSE3_64: subsd
82 ; SSE3_64: cvttsd2si
83 ; AVX512_32: {{subsd|fsub}}
84 ; AVX512_32: fistt
85 ; AVX512_64: vcvttsd2usi
86 ; CHECK: ret
87 define i64 @d_to_u64(double %a) nounwind {
88   %r = fptoui double %a to i64
89   ret i64 %r
90 }
91
92 ; CHECK-LABEL: d_to_s64
93 ; X87: fnstcw
94 ; X87: fist
95 ; SSE2_32: fnstcw
96 ; SSE2_32: fist
97 ; SSE2_64: cvttsd2si
98 ; SSE3_32: fistt
99 ; SSE3_64: cvttsd2si
100 ; AVX512_32: fistt
101 ; AVX512_64: vcvttsd2si
102 ; CHECK: ret
103 define i64 @d_to_s64(double %a) nounwind {
104   %r = fptosi double %a to i64
105   ret i64 %r
106 }
107
108 ; CHECK-LABEL: x_to_u64
109 ; CHECK-DAG: fsub
110 ; X87-DAG: fnstcw
111 ; SSE2_32-DAG: fnstcw
112 ; SSE2_64-DAG: fnstcw
113 ; CHECK: fist
114 ; CHECK: ret
115 define i64 @x_to_u64(x86_fp80 %a) nounwind {
116   %r = fptoui x86_fp80 %a to i64
117   ret i64 %r
118 }
119
120 ; CHECK-LABEL: x_to_s64
121 ; X87: fnstcw
122 ; X87: fist
123 ; SSE2_32: fnstcw
124 ; SSE2_32: fist
125 ; SSE2_64: fnstcw
126 ; SSE2_64: fist
127 ; SSE3_32: fistt
128 ; SSE3_64: fistt
129 ; AVX512_32: fistt
130 ; AVX512_64: fistt
131 ; CHECK: ret
132 define i64 @x_to_s64(x86_fp80 %a) nounwind {
133   %r = fptosi x86_fp80 %a to i64
134   ret i64 %r
135 }
136
137 ; CHECK-LABEL: t_to_u64
138 ; CHECK: __fixunstfdi
139 ; CHECK: ret
140 define i64 @t_to_u64(fp128 %a) nounwind {
141   %r = fptoui fp128 %a to i64
142   ret i64 %r
143 }
144
145 ; CHECK-LABEL: t_to_s64
146 ; CHECK: __fixtfdi
147 ; CHECK: ret
148 define i64 @t_to_s64(fp128 %a) nounwind {
149   %r = fptosi fp128 %a to i64
150   ret i64 %r
151 }