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

; CHECK-LABEL: f_to_u64
; X87-DAG: fsub
; X87-DAG: fnstcw
; X87: fist
; SSE2_32-DAG: {{subss|fsub}}
; SSE2_32-DAG: fnstcw
; SSE2_32: fist
; SSE2_64: subss
; SSE2_64: cvttss2si
; SSE3_32: {{subss|fsub}}
; SSE3_32: fistt
; SSE3_64: subss
; SSE3_64: cvttss2si
; AVX512_32: {{subss|fsub}}
; AVX512_32: fistt
; AVX512_64: vcvttss2usi
; CHECK: ret
define i64 @f_to_u64(float %a) nounwind {
  %r = fptoui float %a to i64
  ret i64 %r
}

; CHECK-LABEL: f_to_s64
; X87: fnstcw
; X87: fist
; SSE2_32: fnstcw
; SSE2_32: fist
; SSE2_64: cvttss2si
; SSE3_32: fistt
; SSE3_64: cvttss2si
; AVX512_32: fistt
; AVX512_64: vcvttss2si
; CHECK: ret
define i64 @f_to_s64(float %a) nounwind {
  %r = fptosi float %a to i64
  ret i64 %r
}

; CHECK-LABEL: d_to_u64
; X87-DAG: fsub
; X87-DAG: fnstcw
; X87: fist
; SSE2_32-DAG: {{subsd|fsub}}
; SSE2_32-DAG: fnstcw
; SSE2_32: fist
; SSE2_64: subsd
; SSE2_64: cvttsd2si
; SSE3_32: {{subsd|fsub}}
; SSE3_32: fistt
; SSE3_64: subsd
; SSE3_64: cvttsd2si
; AVX512_32: {{subsd|fsub}}
; AVX512_32: fistt
; AVX512_64: vcvttsd2usi
; CHECK: ret
define i64 @d_to_u64(double %a) nounwind {
  %r = fptoui double %a to i64
  ret i64 %r
}

; CHECK-LABEL: d_to_s64
; X87: fnstcw
; X87: fist
; SSE2_32: fnstcw
; SSE2_32: fist
; SSE2_64: cvttsd2si
; SSE3_32: fistt
; SSE3_64: cvttsd2si
; AVX512_32: fistt
; AVX512_64: vcvttsd2si
; CHECK: ret
define i64 @d_to_s64(double %a) nounwind {
  %r = fptosi double %a to i64
  ret i64 %r
}

; CHECK-LABEL: x_to_u64
; CHECK-DAG: fsub
; X87-DAG: fnstcw
; SSE2_32-DAG: fnstcw
; SSE2_64-DAG: fnstcw
; CHECK: fist
; CHECK: ret
define i64 @x_to_u64(x86_fp80 %a) nounwind {
  %r = fptoui x86_fp80 %a to i64
  ret i64 %r
}

; CHECK-LABEL: x_to_s64
; X87: fnstcw
; X87: fist
; SSE2_32: fnstcw
; SSE2_32: fist
; SSE2_64: fnstcw
; SSE2_64: fist
; SSE3_32: fistt
; SSE3_64: fistt
; AVX512_32: fistt
; AVX512_64: fistt
; CHECK: ret
define i64 @x_to_s64(x86_fp80 %a) nounwind {
  %r = fptosi x86_fp80 %a to i64
  ret i64 %r
}

; CHECK-LABEL: t_to_u64
; CHECK: __fixunstfdi
; CHECK: ret
define i64 @t_to_u64(fp128 %a) nounwind {
  %r = fptoui fp128 %a to i64
  ret i64 %r
}

; CHECK-LABEL: t_to_s64
; CHECK: __fixtfdi
; CHECK: ret
define i64 @t_to_s64(fp128 %a) nounwind {
  %r = fptosi fp128 %a to i64
  ret i64 %r
}