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 using
4; the trapping opcodes and explicit code to suppress the trapping.
5
6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
7target triple = "wasm32-unknown-unknown"
8
9; CHECK-LABEL: i32_trunc_s_f32:
10; CHECK-NEXT: .functype i32_trunc_s_f32 (f32) -> (i32){{$}}
11; CHECK-NEXT: block
12; CHECK-NEXT: f32.abs $push[[ABS:[0-9]+]]=, $0{{$}}
13; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p31{{$}}
14; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
15; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]
16; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
17; CHECK-NEXT: i32.trunc_f32_s $push[[NUM:[0-9]+]]=, $0{{$}}
18; CHECK-NEXT: return $pop[[NUM]]{{$}}
19; CHECK-NEXT: BB
20; CHECK-NEXT: end_block
21; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, -2147483648{{$}}
22; CHECK-NEXT: return $pop[[ALT]]{{$}}
23define i32 @i32_trunc_s_f32(float %x) {
24  %a = fptosi float %x to i32
25  ret i32 %a
26}
27
28; CHECK-LABEL: i32_trunc_u_f32:
29; CHECK-NEXT: .functype i32_trunc_u_f32 (f32) -> (i32){{$}}
30; CHECK-NEXT: block
31; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p32{{$}}
32; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
33; CHECK-NEXT: f32.const $push[[ZERO:[0-9]+]]=, 0x0p0{{$}}
34; CHECK-NEXT: f32.ge $push[[GE:[0-9]+]]=, $0, $pop[[ZERO]]{{$}}
35; CHECK-NEXT: i32.and $push[[AND:[0-9]+]]=, $pop[[LT]], $pop[[GE]]{{$}}
36; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[AND]]
37; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
38; CHECK-NEXT: i32.trunc_f32_u $push[[NUM:[0-9]+]]=, $0{{$}}
39; CHECK-NEXT: return $pop[[NUM]]{{$}}
40; CHECK-NEXT: BB
41; CHECK-NEXT: end_block
42; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, 0{{$}}
43; CHECK-NEXT: return $pop[[ALT]]{{$}}
44define i32 @i32_trunc_u_f32(float %x) {
45  %a = fptoui float %x to i32
46  ret i32 %a
47}
48
49; CHECK-LABEL: i32_trunc_s_f64:
50; CHECK-NEXT: .functype i32_trunc_s_f64 (f64) -> (i32){{$}}
51; CHECK-NEXT: block
52; CHECK-NEXT: f64.abs $push[[ABS:[0-9]+]]=, $0{{$}}
53; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p31{{$}}
54; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
55; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]
56; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
57; CHECK-NEXT: i32.trunc_f64_s $push[[NUM:[0-9]+]]=, $0{{$}}
58; CHECK-NEXT: return $pop[[NUM]]{{$}}
59; CHECK-NEXT: BB
60; CHECK-NEXT: end_block
61; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, -2147483648{{$}}
62; CHECK-NEXT: return $pop[[ALT]]{{$}}
63define i32 @i32_trunc_s_f64(double %x) {
64  %a = fptosi double %x to i32
65  ret i32 %a
66}
67
68; CHECK-LABEL: i32_trunc_u_f64:
69; CHECK-NEXT: .functype i32_trunc_u_f64 (f64) -> (i32){{$}}
70; CHECK-NEXT: block
71; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p32{{$}}
72; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
73; CHECK-NEXT: f64.const $push[[ZERO:[0-9]+]]=, 0x0p0{{$}}
74; CHECK-NEXT: f64.ge $push[[GE:[0-9]+]]=, $0, $pop[[ZERO]]{{$}}
75; CHECK-NEXT: i32.and $push[[AND:[0-9]+]]=, $pop[[LT]], $pop[[GE]]{{$}}
76; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[AND]]
77; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
78; CHECK-NEXT: i32.trunc_f64_u $push[[NUM:[0-9]+]]=, $0{{$}}
79; CHECK-NEXT: return $pop[[NUM]]{{$}}
80; CHECK-NEXT: BB
81; CHECK-NEXT: end_block
82; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, 0{{$}}
83; CHECK-NEXT: return $pop[[ALT]]{{$}}
84define i32 @i32_trunc_u_f64(double %x) {
85  %a = fptoui double %x to i32
86  ret i32 %a
87}
88
89; CHECK-LABEL: i64_trunc_s_f32:
90; CHECK-NEXT: .functype i64_trunc_s_f32 (f32) -> (i64){{$}}
91; CHECK-NEXT: block
92; CHECK-NEXT: f32.abs $push[[ABS:[0-9]+]]=, $0{{$}}
93; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p63{{$}}
94; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
95; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]
96; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
97; CHECK-NEXT: i64.trunc_f32_s $push[[NUM:[0-9]+]]=, $0{{$}}
98; CHECK-NEXT: return $pop[[NUM]]{{$}}
99; CHECK-NEXT: BB
100; CHECK-NEXT: end_block
101; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, -9223372036854775808{{$}}
102; CHECK-NEXT: return $pop[[ALT]]{{$}}
103define i64 @i64_trunc_s_f32(float %x) {
104  %a = fptosi float %x to i64
105  ret i64 %a
106}
107
108; CHECK-LABEL: i64_trunc_u_f32:
109; CHECK-NEXT: .functype i64_trunc_u_f32 (f32) -> (i64){{$}}
110; CHECK-NEXT: block
111; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p64{{$}}
112; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
113; CHECK-NEXT: f32.const $push[[ZERO:[0-9]+]]=, 0x0p0{{$}}
114; CHECK-NEXT: f32.ge $push[[GE:[0-9]+]]=, $0, $pop[[ZERO]]{{$}}
115; CHECK-NEXT: i32.and $push[[AND:[0-9]+]]=, $pop[[LT]], $pop[[GE]]{{$}}
116; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[AND]]
117; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
118; CHECK-NEXT: i64.trunc_f32_u $push[[NUM:[0-9]+]]=, $0{{$}}
119; CHECK-NEXT: return $pop[[NUM]]{{$}}
120; CHECK-NEXT: BB
121; CHECK-NEXT: end_block
122; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, 0{{$}}
123; CHECK-NEXT: return $pop[[ALT]]{{$}}
124define i64 @i64_trunc_u_f32(float %x) {
125  %a = fptoui float %x to i64
126  ret i64 %a
127}
128
129; CHECK-LABEL: i64_trunc_s_f64:
130; CHECK-NEXT: .functype i64_trunc_s_f64 (f64) -> (i64){{$}}
131; CHECK-NEXT: block
132; CHECK-NEXT: f64.abs $push[[ABS:[0-9]+]]=, $0{{$}}
133; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p63{{$}}
134; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
135; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]
136; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
137; CHECK-NEXT: i64.trunc_f64_s $push[[NUM:[0-9]+]]=, $0{{$}}
138; CHECK-NEXT: return $pop[[NUM]]{{$}}
139; CHECK-NEXT: BB
140; CHECK-NEXT: end_block
141; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, -9223372036854775808{{$}}
142; CHECK-NEXT: return $pop[[ALT]]{{$}}
143define i64 @i64_trunc_s_f64(double %x) {
144  %a = fptosi double %x to i64
145  ret i64 %a
146}
147
148; CHECK-LABEL: i64_trunc_u_f64:
149; CHECK-NEXT: .functype i64_trunc_u_f64 (f64) -> (i64){{$}}
150; CHECK-NEXT: block
151; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p64{{$}}
152; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
153; CHECK-NEXT: f64.const $push[[ZERO:[0-9]+]]=, 0x0p0{{$}}
154; CHECK-NEXT: f64.ge $push[[GE:[0-9]+]]=, $0, $pop[[ZERO]]{{$}}
155; CHECK-NEXT: i32.and $push[[AND:[0-9]+]]=, $pop[[LT]], $pop[[GE]]{{$}}
156; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[AND]]
157; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
158; CHECK-NEXT: i64.trunc_f64_u $push[[NUM:[0-9]+]]=, $0{{$}}
159; CHECK-NEXT: return $pop[[NUM]]{{$}}
160; CHECK-NEXT: BB
161; CHECK-NEXT: end_block
162; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, 0{{$}}
163; CHECK-NEXT: return $pop[[ALT]]{{$}}
164define i64 @i64_trunc_u_f64(double %x) {
165  %a = fptoui double %x to i64
166  ret i64 %a
167}
168
169; CHECK-LABEL: llvm_wasm_trunc_signed_i32_f32:
170; CHECK-NEXT: .functype llvm_wasm_trunc_signed_i32_f32 (f32) -> (i32)
171; CHECK-NEXT: i32.trunc_f32_s $push[[L0:[0-9]+]]=, $0{{$}}
172; CHECK-NEXT: return $pop[[L0]]{{$}}
173declare i32 @llvm.wasm.trunc.signed.i32.f32(float)
174define i32 @llvm_wasm_trunc_signed_i32_f32(float %f) {
175  %a = call i32 @llvm.wasm.trunc.signed.i32.f32(float %f)
176  ret i32 %a
177}
178
179; CHECK-LABEL: llvm_wasm_trunc_unsigned_i32_f32:
180; CHECK-NEXT: .functype llvm_wasm_trunc_unsigned_i32_f32 (f32) -> (i32)
181; CHECK-NEXT: i32.trunc_f32_u $push[[L0:[0-9]+]]=, $0{{$}}
182; CHECK-NEXT: return $pop[[L0]]{{$}}
183declare i32 @llvm.wasm.trunc.unsigned.i32.f32(float)
184define i32 @llvm_wasm_trunc_unsigned_i32_f32(float %f) {
185  %a = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float %f)
186  ret i32 %a
187}
188
189; CHECK-LABEL: llvm_wasm_trunc_signed_i32_f64:
190; CHECK-NEXT: .functype llvm_wasm_trunc_signed_i32_f64 (f64) -> (i32)
191; CHECK-NEXT: i32.trunc_f64_s $push[[L0:[0-9]+]]=, $0{{$}}
192; CHECK-NEXT: return $pop[[L0]]{{$}}
193declare i32 @llvm.wasm.trunc.signed.i32.f64(double)
194define i32 @llvm_wasm_trunc_signed_i32_f64(double %f) {
195  %a = call i32 @llvm.wasm.trunc.signed.i32.f64(double %f)
196  ret i32 %a
197}
198
199; CHECK-LABEL: llvm_wasm_trunc_unsigned_i32_f64:
200; CHECK-NEXT: .functype llvm_wasm_trunc_unsigned_i32_f64 (f64) -> (i32)
201; CHECK-NEXT: i32.trunc_f64_u $push[[L0:[0-9]+]]=, $0{{$}}
202; CHECK-NEXT: return $pop[[L0]]{{$}}
203declare i32 @llvm.wasm.trunc.unsigned.i32.f64(double)
204define i32 @llvm_wasm_trunc_unsigned_i32_f64(double %f) {
205  %a = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double %f)
206  ret i32 %a
207}
208
209; CHECK-LABEL: llvm_wasm_trunc_signed_i64_f32:
210; CHECK-NEXT: .functype llvm_wasm_trunc_signed_i64_f32 (f32) -> (i64)
211; CHECK-NEXT: i64.trunc_f32_s $push[[L0:[0-9]+]]=, $0{{$}}
212; CHECK-NEXT: return $pop[[L0]]{{$}}
213declare i64 @llvm.wasm.trunc.signed.i64.f32(float)
214define i64 @llvm_wasm_trunc_signed_i64_f32(float %f) {
215  %a = call i64 @llvm.wasm.trunc.signed.i64.f32(float %f)
216  ret i64 %a
217}
218
219; CHECK-LABEL: llvm_wasm_trunc_unsigned_i64_f32:
220; CHECK-NEXT: .functype llvm_wasm_trunc_unsigned_i64_f32 (f32) -> (i64)
221; CHECK-NEXT: i64.trunc_f32_u $push[[L0:[0-9]+]]=, $0{{$}}
222; CHECK-NEXT: return $pop[[L0]]{{$}}
223declare i64 @llvm.wasm.trunc.unsigned.i64.f32(float)
224define i64 @llvm_wasm_trunc_unsigned_i64_f32(float %f) {
225  %a = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float %f)
226  ret i64 %a
227}
228
229; CHECK-LABEL: llvm_wasm_trunc_signed_i64_f64:
230; CHECK-NEXT: .functype llvm_wasm_trunc_signed_i64_f64 (f64) -> (i64)
231; CHECK-NEXT: i64.trunc_f64_s $push[[L0:[0-9]+]]=, $0{{$}}
232; CHECK-NEXT: return $pop[[L0]]{{$}}
233declare i64 @llvm.wasm.trunc.signed.i64.f64(double)
234define i64 @llvm_wasm_trunc_signed_i64_f64(double %f) {
235  %a = call i64 @llvm.wasm.trunc.signed.i64.f64(double %f)
236  ret i64 %a
237}
238
239; CHECK-LABEL: llvm_wasm_trunc_unsigned_i64_f64:
240; CHECK-NEXT: .functype llvm_wasm_trunc_unsigned_i64_f64 (f64) -> (i64)
241; CHECK-NEXT: i64.trunc_f64_u $push[[L0:[0-9]+]]=, $0{{$}}
242; CHECK-NEXT: return $pop[[L0]]{{$}}
243declare i64 @llvm.wasm.trunc.unsigned.i64.f64(double)
244define i64 @llvm_wasm_trunc_unsigned_i64_f64(double %f) {
245  %a = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double %f)
246  ret i64 %a
247}
248