1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+nontrapping-fptoint | FileCheck %s
2
3; Test that basic conversion operations assemble as expected.
4
5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6target triple = "wasm32-unknown-unknown"
7
8; CHECK-LABEL: i32_wrap_i64:
9; CHECK-NEXT: .functype i32_wrap_i64 (i64) -> (i32){{$}}
10; CHECK-NEXT: i32.wrap_i64 $push[[NUM:[0-9]+]]=, $0{{$}}
11; CHECK-NEXT: return $pop[[NUM]]{{$}}
12define i32 @i32_wrap_i64(i64 %x) {
13  %a = trunc i64 %x to i32
14  ret i32 %a
15}
16
17; CHECK-LABEL: i64_extend_s_i32:
18; CHECK-NEXT: .functype i64_extend_s_i32 (i32) -> (i64){{$}}
19; CHECK-NEXT: i64.extend_i32_s $push[[NUM:[0-9]+]]=, $0{{$}}
20; CHECK-NEXT: return $pop[[NUM]]{{$}}
21define i64 @i64_extend_s_i32(i32 %x) {
22  %a = sext i32 %x to i64
23  ret i64 %a
24}
25
26; CHECK-LABEL: i64_extend_u_i32:
27; CHECK-NEXT: .functype i64_extend_u_i32 (i32) -> (i64){{$}}
28; CHECK-NEXT: i64.extend_i32_u $push[[NUM:[0-9]+]]=, $0{{$}}
29; CHECK-NEXT: return $pop[[NUM]]{{$}}
30define i64 @i64_extend_u_i32(i32 %x) {
31  %a = zext i32 %x to i64
32  ret i64 %a
33}
34
35; CHECK-LABEL: i32_trunc_s_f32:
36; CHECK-NEXT: .functype i32_trunc_s_f32 (f32) -> (i32){{$}}
37; CHECK-NEXT: i32.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}}
38; CHECK-NEXT: return $pop[[NUM]]{{$}}
39define i32 @i32_trunc_s_f32(float %x) {
40  %a = fptosi float %x to i32
41  ret i32 %a
42}
43
44; CHECK-LABEL: i32_trunc_sat_s_f32:
45; CHECK-NEXT: .functype i32_trunc_sat_s_f32 (f32) -> (i32){{$}}
46; CHECK-NEXT: i32.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}}
47; CHECK-NEXT: return $pop[[NUM]]{{$}}
48declare i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float)
49define i32 @i32_trunc_sat_s_f32(float %x) {
50  %a = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %x)
51  ret i32 %a
52}
53
54; CHECK-LABEL: i32_trunc_u_f32:
55; CHECK-NEXT: .functype i32_trunc_u_f32 (f32) -> (i32){{$}}
56; CHECK-NEXT: i32.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}}
57; CHECK-NEXT: return $pop[[NUM]]{{$}}
58define i32 @i32_trunc_u_f32(float %x) {
59  %a = fptoui float %x to i32
60  ret i32 %a
61}
62
63; CHECK-LABEL: i32_trunc_sat_u_f32:
64; CHECK-NEXT: .functype i32_trunc_sat_u_f32 (f32) -> (i32){{$}}
65; CHECK-NEXT: i32.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}}
66; CHECK-NEXT: return $pop[[NUM]]{{$}}
67declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float)
68define i32 @i32_trunc_sat_u_f32(float %x) {
69  %a = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float %x)
70  ret i32 %a
71}
72
73; CHECK-LABEL: i32_trunc_s_f64:
74; CHECK-NEXT: .functype i32_trunc_s_f64 (f64) -> (i32){{$}}
75; CHECK-NEXT: i32.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}}
76; CHECK-NEXT: return $pop[[NUM]]{{$}}
77define i32 @i32_trunc_s_f64(double %x) {
78  %a = fptosi double %x to i32
79  ret i32 %a
80}
81
82; CHECK-LABEL: i32_trunc_sat_s_f64:
83; CHECK-NEXT: .functype i32_trunc_sat_s_f64 (f64) -> (i32){{$}}
84; CHECK-NEXT: i32.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}}
85; CHECK-NEXT: return $pop[[NUM]]{{$}}
86declare i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double)
87define i32 @i32_trunc_sat_s_f64(double %x) {
88  %a = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double %x)
89  ret i32 %a
90}
91
92; CHECK-LABEL: i32_trunc_u_f64:
93; CHECK-NEXT: .functype i32_trunc_u_f64 (f64) -> (i32){{$}}
94; CHECK-NEXT: i32.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}}
95; CHECK-NEXT: return $pop[[NUM]]{{$}}
96define i32 @i32_trunc_u_f64(double %x) {
97  %a = fptoui double %x to i32
98  ret i32 %a
99}
100
101; CHECK-LABEL: i32_trunc_sat_u_f64:
102; CHECK-NEXT: .functype i32_trunc_sat_u_f64 (f64) -> (i32){{$}}
103; CHECK-NEXT: i32.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}}
104; CHECK-NEXT: return $pop[[NUM]]{{$}}
105declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double)
106define i32 @i32_trunc_sat_u_f64(double %x) {
107  %a = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double %x)
108  ret i32 %a
109}
110
111; CHECK-LABEL: i64_trunc_s_f32:
112; CHECK-NEXT: .functype i64_trunc_s_f32 (f32) -> (i64){{$}}
113; CHECK-NEXT: i64.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}}
114; CHECK-NEXT: return $pop[[NUM]]{{$}}
115define i64 @i64_trunc_s_f32(float %x) {
116  %a = fptosi float %x to i64
117  ret i64 %a
118}
119
120; CHECK-LABEL: i64_trunc_sat_s_f32:
121; CHECK-NEXT: .functype i64_trunc_sat_s_f32 (f32) -> (i64){{$}}
122; CHECK-NEXT: i64.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}}
123; CHECK-NEXT: return $pop[[NUM]]{{$}}
124declare i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float)
125define i64 @i64_trunc_sat_s_f32(float %x) {
126  %a = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float %x)
127  ret i64 %a
128}
129
130; CHECK-LABEL: i64_trunc_u_f32:
131; CHECK-NEXT: .functype i64_trunc_u_f32 (f32) -> (i64){{$}}
132; CHECK-NEXT: i64.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}}
133; CHECK-NEXT: return $pop[[NUM]]{{$}}
134define i64 @i64_trunc_u_f32(float %x) {
135  %a = fptoui float %x to i64
136  ret i64 %a
137}
138
139; CHECK-LABEL: i64_trunc_sat_u_f32:
140; CHECK-NEXT: .functype i64_trunc_sat_u_f32 (f32) -> (i64){{$}}
141; CHECK-NEXT: i64.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}}
142; CHECK-NEXT: return $pop[[NUM]]{{$}}
143declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float)
144define i64 @i64_trunc_sat_u_f32(float %x) {
145  %a = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float %x)
146  ret i64 %a
147}
148
149; CHECK-LABEL: i64_trunc_s_f64:
150; CHECK-NEXT: .functype i64_trunc_s_f64 (f64) -> (i64){{$}}
151; CHECK-NEXT: i64.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}}
152; CHECK-NEXT: return $pop[[NUM]]{{$}}
153define i64 @i64_trunc_s_f64(double %x) {
154  %a = fptosi double %x to i64
155  ret i64 %a
156}
157
158; CHECK-LABEL: i64_trunc_sat_s_f64:
159; CHECK-NEXT: .functype i64_trunc_sat_s_f64 (f64) -> (i64){{$}}
160; CHECK-NEXT: i64.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}}
161; CHECK-NEXT: return $pop[[NUM]]{{$}}
162declare i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double)
163define i64 @i64_trunc_sat_s_f64(double %x) {
164  %a = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double %x)
165  ret i64 %a
166}
167
168; CHECK-LABEL: i64_trunc_u_f64:
169; CHECK-NEXT: .functype i64_trunc_u_f64 (f64) -> (i64){{$}}
170; CHECK-NEXT: i64.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}}
171; CHECK-NEXT: return $pop[[NUM]]{{$}}
172define i64 @i64_trunc_u_f64(double %x) {
173  %a = fptoui double %x to i64
174  ret i64 %a
175}
176
177; CHECK-LABEL: i64_trunc_sat_u_f64:
178; CHECK-NEXT: .functype i64_trunc_sat_u_f64 (f64) -> (i64){{$}}
179; CHECK-NEXT: i64.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}}
180; CHECK-NEXT: return $pop[[NUM]]{{$}}
181declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double)
182define i64 @i64_trunc_sat_u_f64(double %x) {
183  %a = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double %x)
184  ret i64 %a
185}
186
187; CHECK-LABEL: f32_convert_s_i32:
188; CHECK-NEXT: .functype f32_convert_s_i32 (i32) -> (f32){{$}}
189; CHECK-NEXT: f32.convert_i32_s $push[[NUM:[0-9]+]]=, $0{{$}}
190; CHECK-NEXT: return $pop[[NUM]]{{$}}
191define float @f32_convert_s_i32(i32 %x) {
192  %a = sitofp i32 %x to float
193  ret float %a
194}
195
196; CHECK-LABEL: f32_convert_u_i32:
197; CHECK-NEXT: .functype f32_convert_u_i32 (i32) -> (f32){{$}}
198; CHECK-NEXT: f32.convert_i32_u $push[[NUM:[0-9]+]]=, $0{{$}}
199; CHECK-NEXT: return $pop[[NUM]]{{$}}
200define float @f32_convert_u_i32(i32 %x) {
201  %a = uitofp i32 %x to float
202  ret float %a
203}
204
205; CHECK-LABEL: f64_convert_s_i32:
206; CHECK-NEXT: .functype f64_convert_s_i32 (i32) -> (f64){{$}}
207; CHECK-NEXT: f64.convert_i32_s $push[[NUM:[0-9]+]]=, $0{{$}}
208; CHECK-NEXT: return $pop[[NUM]]{{$}}
209define double @f64_convert_s_i32(i32 %x) {
210  %a = sitofp i32 %x to double
211  ret double %a
212}
213
214; CHECK-LABEL: f64_convert_u_i32:
215; CHECK-NEXT: .functype f64_convert_u_i32 (i32) -> (f64){{$}}
216; CHECK-NEXT: f64.convert_i32_u $push[[NUM:[0-9]+]]=, $0{{$}}
217; CHECK-NEXT: return $pop[[NUM]]{{$}}
218define double @f64_convert_u_i32(i32 %x) {
219  %a = uitofp i32 %x to double
220  ret double %a
221}
222
223; CHECK-LABEL: f32_convert_s_i64:
224; CHECK-NEXT: .functype f32_convert_s_i64 (i64) -> (f32){{$}}
225; CHECK-NEXT: f32.convert_i64_s $push[[NUM:[0-9]+]]=, $0{{$}}
226; CHECK-NEXT: return $pop[[NUM]]{{$}}
227define float @f32_convert_s_i64(i64 %x) {
228  %a = sitofp i64 %x to float
229  ret float %a
230}
231
232; CHECK-LABEL: f32_convert_u_i64:
233; CHECK-NEXT: .functype f32_convert_u_i64 (i64) -> (f32){{$}}
234; CHECK-NEXT: f32.convert_i64_u $push[[NUM:[0-9]+]]=, $0{{$}}
235; CHECK-NEXT: return $pop[[NUM]]{{$}}
236define float @f32_convert_u_i64(i64 %x) {
237  %a = uitofp i64 %x to float
238  ret float %a
239}
240
241; CHECK-LABEL: f64_convert_s_i64:
242; CHECK-NEXT: .functype f64_convert_s_i64 (i64) -> (f64){{$}}
243; CHECK-NEXT: f64.convert_i64_s $push[[NUM:[0-9]+]]=, $0{{$}}
244; CHECK-NEXT: return $pop[[NUM]]{{$}}
245define double @f64_convert_s_i64(i64 %x) {
246  %a = sitofp i64 %x to double
247  ret double %a
248}
249
250; CHECK-LABEL: f64_convert_u_i64:
251; CHECK-NEXT: .functype f64_convert_u_i64 (i64) -> (f64){{$}}
252; CHECK-NEXT: f64.convert_i64_u $push[[NUM:[0-9]+]]=, $0{{$}}
253; CHECK-NEXT: return $pop[[NUM]]{{$}}
254define double @f64_convert_u_i64(i64 %x) {
255  %a = uitofp i64 %x to double
256  ret double %a
257}
258
259; CHECK-LABEL: f64_promote_f32:
260; CHECK-NEXT: .functype f64_promote_f32 (f32) -> (f64){{$}}
261; CHECK-NEXT: f64.promote_f32 $push[[NUM:[0-9]+]]=, $0{{$}}
262; CHECK-NEXT: return $pop[[NUM]]{{$}}
263define double @f64_promote_f32(float %x) {
264  %a = fpext float %x to double
265  ret double %a
266}
267
268; CHECK-LABEL: f32_demote_f64:
269; CHECK-NEXT: .functype f32_demote_f64 (f64) -> (f32){{$}}
270; CHECK-NEXT: f32.demote_f64 $push[[NUM:[0-9]+]]=, $0{{$}}
271; CHECK-NEXT: return $pop[[NUM]]{{$}}
272define float @f32_demote_f64(double %x) {
273  %a = fptrunc double %x to float
274  ret float %a
275}
276
277; If the high its are unused, LLVM will optimize sext/zext into anyext, which
278; we need to patterm-match back to a specific instruction.
279
280; CHECK-LABEL: anyext:
281; CHECK: i64.extend_i32_u $push0=, $0{{$}}
282define i64 @anyext(i32 %x) {
283    %y = sext i32 %x to i64
284    %w = shl i64 %y, 32
285    ret i64 %w
286}
287
288; CHECK-LABEL: bitcast_i32_to_float:
289; CHECK: f32.reinterpret_i32   $push0=, $0{{$}}
290define float @bitcast_i32_to_float(i32 %a) {
291  %t = bitcast i32 %a to float
292  ret float %t
293}
294
295; CHECK-LABEL: bitcast_float_to_i32:
296; CHECK: i32.reinterpret_f32   $push0=, $0{{$}}
297define i32 @bitcast_float_to_i32(float %a) {
298  %t = bitcast float %a to i32
299  ret i32 %t
300}
301
302; CHECK-LABEL: bitcast_i64_to_double:
303; CHECK: f64.reinterpret_i64   $push0=, $0{{$}}
304define double @bitcast_i64_to_double(i64 %a) {
305  %t = bitcast i64 %a to double
306  ret double %t
307}
308
309; CHECK-LABEL: bitcast_double_to_i64:
310; CHECK: i64.reinterpret_f64   $push0=, $0{{$}}
311define i64 @bitcast_double_to_i64(double %a) {
312  %t = bitcast double %a to i64
313  ret i64 %t
314}
315