1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-nontrapping-fptoint | FileCheck %s
3 ; Test that basic conversion operations assemble as expected using
4 ; the trapping opcodes and explicit code to suppress the trapping.
6 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
7 target triple = "wasm32-unknown-unknown"
9 ; CHECK-LABEL: i32_trunc_s_f32:
10 ; CHECK-NEXT: .functype i32_trunc_s_f32 (f32) -> (i32){{$}}
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]]{{$}}
20 ; CHECK-NEXT: end_block
21 ; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, -2147483648{{$}}
22 ; CHECK-NEXT: return $pop[[ALT]]{{$}}
23 define i32 @i32_trunc_s_f32(float %x) {
24 %a = fptosi float %x to i32
28 ; CHECK-LABEL: i32_trunc_u_f32:
29 ; CHECK-NEXT: .functype i32_trunc_u_f32 (f32) -> (i32){{$}}
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]]{{$}}
41 ; CHECK-NEXT: end_block
42 ; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, 0{{$}}
43 ; CHECK-NEXT: return $pop[[ALT]]{{$}}
44 define i32 @i32_trunc_u_f32(float %x) {
45 %a = fptoui float %x to i32
49 ; CHECK-LABEL: i32_trunc_s_f64:
50 ; CHECK-NEXT: .functype i32_trunc_s_f64 (f64) -> (i32){{$}}
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]]{{$}}
60 ; CHECK-NEXT: end_block
61 ; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, -2147483648{{$}}
62 ; CHECK-NEXT: return $pop[[ALT]]{{$}}
63 define i32 @i32_trunc_s_f64(double %x) {
64 %a = fptosi double %x to i32
68 ; CHECK-LABEL: i32_trunc_u_f64:
69 ; CHECK-NEXT: .functype i32_trunc_u_f64 (f64) -> (i32){{$}}
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]]{{$}}
81 ; CHECK-NEXT: end_block
82 ; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, 0{{$}}
83 ; CHECK-NEXT: return $pop[[ALT]]{{$}}
84 define i32 @i32_trunc_u_f64(double %x) {
85 %a = fptoui double %x to i32
89 ; CHECK-LABEL: i64_trunc_s_f32:
90 ; CHECK-NEXT: .functype i64_trunc_s_f32 (f32) -> (i64){{$}}
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]]{{$}}
100 ; CHECK-NEXT: end_block
101 ; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, -9223372036854775808{{$}}
102 ; CHECK-NEXT: return $pop[[ALT]]{{$}}
103 define i64 @i64_trunc_s_f32(float %x) {
104 %a = fptosi float %x to i64
108 ; CHECK-LABEL: i64_trunc_u_f32:
109 ; CHECK-NEXT: .functype i64_trunc_u_f32 (f32) -> (i64){{$}}
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]]{{$}}
121 ; CHECK-NEXT: end_block
122 ; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, 0{{$}}
123 ; CHECK-NEXT: return $pop[[ALT]]{{$}}
124 define i64 @i64_trunc_u_f32(float %x) {
125 %a = fptoui float %x to i64
129 ; CHECK-LABEL: i64_trunc_s_f64:
130 ; CHECK-NEXT: .functype i64_trunc_s_f64 (f64) -> (i64){{$}}
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]]{{$}}
140 ; CHECK-NEXT: end_block
141 ; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, -9223372036854775808{{$}}
142 ; CHECK-NEXT: return $pop[[ALT]]{{$}}
143 define i64 @i64_trunc_s_f64(double %x) {
144 %a = fptosi double %x to i64
148 ; CHECK-LABEL: i64_trunc_u_f64:
149 ; CHECK-NEXT: .functype i64_trunc_u_f64 (f64) -> (i64){{$}}
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]]{{$}}
161 ; CHECK-NEXT: end_block
162 ; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, 0{{$}}
163 ; CHECK-NEXT: return $pop[[ALT]]{{$}}
164 define i64 @i64_trunc_u_f64(double %x) {
165 %a = fptoui double %x to i64
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]]{{$}}
173 declare i32 @llvm.wasm.trunc.signed.i32.f32(float)
174 define i32 @llvm_wasm_trunc_signed_i32_f32(float %f) {
175 %a = call i32 @llvm.wasm.trunc.signed.i32.f32(float %f)
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]]{{$}}
183 declare i32 @llvm.wasm.trunc.unsigned.i32.f32(float)
184 define i32 @llvm_wasm_trunc_unsigned_i32_f32(float %f) {
185 %a = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float %f)
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]]{{$}}
193 declare i32 @llvm.wasm.trunc.signed.i32.f64(double)
194 define i32 @llvm_wasm_trunc_signed_i32_f64(double %f) {
195 %a = call i32 @llvm.wasm.trunc.signed.i32.f64(double %f)
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]]{{$}}
203 declare i32 @llvm.wasm.trunc.unsigned.i32.f64(double)
204 define i32 @llvm_wasm_trunc_unsigned_i32_f64(double %f) {
205 %a = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double %f)
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]]{{$}}
213 declare i64 @llvm.wasm.trunc.signed.i64.f32(float)
214 define i64 @llvm_wasm_trunc_signed_i64_f32(float %f) {
215 %a = call i64 @llvm.wasm.trunc.signed.i64.f32(float %f)
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]]{{$}}
223 declare i64 @llvm.wasm.trunc.unsigned.i64.f32(float)
224 define i64 @llvm_wasm_trunc_unsigned_i64_f32(float %f) {
225 %a = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float %f)
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]]{{$}}
233 declare i64 @llvm.wasm.trunc.signed.i64.f64(double)
234 define i64 @llvm_wasm_trunc_signed_i64_f64(double %f) {
235 %a = call i64 @llvm.wasm.trunc.signed.i64.f64(double %f)
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]]{{$}}
243 declare i64 @llvm.wasm.trunc.unsigned.i64.f64(double)
244 define i64 @llvm_wasm_trunc_unsigned_i64_f64(double %f) {
245 %a = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double %f)