• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
49define 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
65define 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
87define 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
103define 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
115define 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
132define 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
140define 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
148define i64 @t_to_s64(fp128 %a) nounwind {
149  %r = fptosi fp128 %a to i64
150  ret i64 %r
151}
152