1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
3 ; Test that basic 64-bit floating-point comparison operations assemble as
6 target triple = "wasm32-unknown-unknown"
8 ; CHECK-LABEL: ord_f64:
9 ; CHECK-NEXT: .functype ord_f64 (f64, f64) -> (i32){{$}}
10 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
11 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 0{{$}}
12 ; CHECK-NEXT: f64.eq $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
13 ; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 1{{$}}
14 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1{{$}}
15 ; CHECK-NEXT: f64.eq $push[[NUM1:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}}
16 ; CHECK-NEXT: i32.and $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}}
17 ; CHECK-NEXT: return $pop[[NUM2]]{{$}}
18 define i32 @ord_f64(double %x, double %y) {
19 %a = fcmp ord double %x, %y
20 %b = zext i1 %a to i32
24 ; CHECK-LABEL: uno_f64:
25 ; CHECK-NEXT: .functype uno_f64 (f64, f64) -> (i32){{$}}
26 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
27 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 0{{$}}
28 ; CHECK-NEXT: f64.ne $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
29 ; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 1{{$}}
30 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1{{$}}
31 ; CHECK-NEXT: f64.ne $push[[NUM1:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}}
32 ; CHECK-NEXT: i32.or $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}}
33 ; CHECK-NEXT: return $pop[[NUM2]]{{$}}
34 define i32 @uno_f64(double %x, double %y) {
35 %a = fcmp uno double %x, %y
36 %b = zext i1 %a to i32
40 ; CHECK-LABEL: oeq_f64:
41 ; CHECK-NEXT: .functype oeq_f64 (f64, f64) -> (i32){{$}}
42 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
43 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
44 ; CHECK-NEXT: f64.eq $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
45 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
46 define i32 @oeq_f64(double %x, double %y) {
47 %a = fcmp oeq double %x, %y
48 %b = zext i1 %a to i32
52 ; CHECK-LABEL: une_f64:
53 ; CHECK: f64.ne $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
54 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
55 define i32 @une_f64(double %x, double %y) {
56 %a = fcmp une double %x, %y
57 %b = zext i1 %a to i32
61 ; CHECK-LABEL: olt_f64:
62 ; CHECK: f64.lt $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
63 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
64 define i32 @olt_f64(double %x, double %y) {
65 %a = fcmp olt double %x, %y
66 %b = zext i1 %a to i32
70 ; CHECK-LABEL: ole_f64:
71 ; CHECK: f64.le $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
72 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
73 define i32 @ole_f64(double %x, double %y) {
74 %a = fcmp ole double %x, %y
75 %b = zext i1 %a to i32
79 ; CHECK-LABEL: ogt_f64:
80 ; CHECK: f64.gt $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
81 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
82 define i32 @ogt_f64(double %x, double %y) {
83 %a = fcmp ogt double %x, %y
84 %b = zext i1 %a to i32
88 ; CHECK-LABEL: oge_f64:
89 ; CHECK: f64.ge $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
90 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
91 define i32 @oge_f64(double %x, double %y) {
92 %a = fcmp oge double %x, %y
93 %b = zext i1 %a to i32
97 ; Expanded comparisons, which also check for NaN.
99 ; CHECK-LABEL: ueq_f64:
100 ; CHECK-NEXT: .functype ueq_f64 (f64, f64) -> (i32){{$}}
101 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
102 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
103 ; CHECK-NEXT: f64.gt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
104 ; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 0{{$}}
105 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1{{$}}
106 ; CHECK-NEXT: f64.lt $push[[NUM1:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}}
107 ; CHECK-NEXT: i32.or $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}}
108 ; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1
109 ; CHECK-NEXT: i32.xor $push[[NUM3:[0-9]+]]=, $pop[[NUM2]], $pop[[C0]]{{$}}
110 ; CHECK-NEXT: return $pop[[NUM3]]{{$}}
111 define i32 @ueq_f64(double %x, double %y) {
112 %a = fcmp ueq double %x, %y
113 %b = zext i1 %a to i32
117 ; CHECK-LABEL: one_f64:
118 ; CHECK-NEXT: .functype one_f64 (f64, f64) -> (i32){{$}}
119 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
120 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
121 ; CHECK-NEXT: f64.gt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
122 ; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 0{{$}}
123 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1{{$}}
124 ; CHECK-NEXT: f64.lt $push[[NUM1:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}}
125 ; CHECK-NEXT: i32.or $push[[NUM4:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}}
126 ; CHECK-NEXT: return $pop[[NUM4]]
127 define i32 @one_f64(double %x, double %y) {
128 %a = fcmp one double %x, %y
129 %b = zext i1 %a to i32
133 ; CHECK-LABEL: ult_f64:
134 ; CHECK-NEXT: .functype ult_f64 (f64, f64) -> (i32){{$}}
135 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
136 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
137 ; CHECK-NEXT: f64.ge $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
138 ; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1
139 ; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}}
140 ; CHECK-NEXT: return $pop[[NUM2]]{{$}}
141 define i32 @ult_f64(double %x, double %y) {
142 %a = fcmp ult double %x, %y
143 %b = zext i1 %a to i32
147 ; CHECK-LABEL: ule_f64:
148 ; CHECK-NEXT: .functype ule_f64 (f64, f64) -> (i32){{$}}
149 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
150 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
151 ; CHECK-NEXT: f64.gt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
152 ; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1
153 ; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}}
154 ; CHECK-NEXT: return $pop[[NUM2]]{{$}}
155 define i32 @ule_f64(double %x, double %y) {
156 %a = fcmp ule double %x, %y
157 %b = zext i1 %a to i32
161 ; CHECK-LABEL: ugt_f64:
162 ; CHECK-NEXT: .functype ugt_f64 (f64, f64) -> (i32){{$}}
163 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
164 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
165 ; CHECK-NEXT: f64.le $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
166 ; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1
167 ; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}}
168 ; CHECK-NEXT: return $pop[[NUM2]]{{$}}
169 define i32 @ugt_f64(double %x, double %y) {
170 %a = fcmp ugt double %x, %y
171 %b = zext i1 %a to i32
175 ; CHECK-LABEL: uge_f64:
176 ; CHECK-NEXT: .functype uge_f64 (f64, f64) -> (i32){{$}}
177 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
178 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
179 ; CHECK-NEXT: f64.lt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
180 ; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1
181 ; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}}
182 ; CHECK-NEXT: return $pop[[NUM2]]{{$}}
183 define i32 @uge_f64(double %x, double %y) {
184 %a = fcmp uge double %x, %y
185 %b = zext i1 %a to i32
189 ; CHECK-LABEL: olt_f64_branch:
190 ; CHECK: local.get $push[[L0:[0-9]+]]=, 0
191 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1
192 ; CHECK-NEXT: f64.lt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]
193 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
194 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
195 ; CHECK-NEXT: call call1
196 define void @olt_f64_branch(double %a, double %b) {
198 %cmp = fcmp olt double %a, %b
199 br i1 %cmp, label %if.then, label %if.end
202 tail call void @call1()
209 ; CHECK-LABEL: ole_f64_branch:
210 ; CHECK: local.get $push[[L0:[0-9]+]]=, 0
211 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1
212 ; CHECK-NEXT: f64.le $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]
213 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
214 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
215 ; CHECK-NEXT: call call1
216 define void @ole_f64_branch(double %a, double %b) {
218 %cmp = fcmp ole double %a, %b
219 br i1 %cmp, label %if.then, label %if.end
222 tail call void @call1()
229 ; CHECK-LABEL: ugt_f64_branch:
230 ; CHECK: local.get $push[[L0:[0-9]+]]=, 0
231 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1
232 ; CHECK-NEXT: f64.le $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]
233 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
234 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
235 ; CHECK-NEXT: call call1
236 define void @ugt_f64_branch(double %a, double %b) {
238 %cmp = fcmp ugt double %a, %b
239 br i1 %cmp, label %if.end, label %if.then
242 tail call void @call1()
249 ; CHECK-LABEL: ogt_f64_branch:
250 ; CHECK: local.get $push[[L0:[0-9]+]]=, 0
251 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1
252 ; CHECK-NEXT: f64.gt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]
253 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
254 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
255 ; CHECK-NEXT: call call1
256 define void @ogt_f64_branch(double %a, double %b) {
258 %cmp = fcmp ogt double %a, %b
259 br i1 %cmp, label %if.then, label %if.end
262 tail call void @call1()
269 ; CHECK-LABEL: ult_f64_branch:
270 ; CHECK: local.get $push[[L0:[0-9]+]]=, 0
271 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1
272 ; CHECK-NEXT: f64.ge $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]
273 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
274 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
275 ; CHECK-NEXT: call call1
276 define void @ult_f64_branch(double %a, double %b) {
278 %cmp = fcmp ult double %a, %b
279 br i1 %cmp, label %if.end, label %if.then
282 tail call void @call1()
289 ; CHECK-LABEL: ule_f64_branch:
290 ; CHECK: local.get $push[[L0:[0-9]+]]=, 0
291 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1
292 ; CHECK-NEXT: f64.gt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]
293 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
294 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
295 ; CHECK-NEXT: call call1
296 define void @ule_f64_branch(double %a, double %b) {
298 %cmp = fcmp ule double %a, %b
299 br i1 %cmp, label %if.end, label %if.then
302 tail call void @call1()
309 ; CHECK-LABEL: xor_zext_switch
310 ; CHECK: i32.const $push[[L1:[0-9]+]]=, 0
311 ; CHECK-NEXT: br_if 0, $pop[[L1]]
314 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 0
315 ; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 1
316 ; CHECK-NEXT: f64.ge $push[[L0:[0-9]+]]=, $pop[[L3]], $pop[[L2]]
317 ; CHECK-NEXT: br_table $pop[[L0]], 0, 1, 0
318 define void @xor_zext_switch(double %a, double %b) {
320 %cmp = fcmp ult double %a, %b
321 %zext = zext i1 %cmp to i32
322 %xor = xor i32 %zext, 1
323 switch i32 %xor, label %exit [
324 i32 0, label %sw.bb.1
325 i32 1, label %sw.bb.2
329 tail call void @foo1()
333 tail call void @foo2()
340 ; CHECK-LABEL: xor_add_switch
341 ; CHECK: local.get $push[[L8:[0-9]+]]=, 0
342 ; CHECK-NEXT: local.get $push[[L7:[0-9]+]]=, 1
343 ; CHECK-NEXT: f64.ge $push[[L1:[0-9]+]]=, $pop[[L8]], $pop[[L7]]
344 ; CHECK-NEXT: i32.const $push[[L2:[0-9]+]]=, 1
345 ; CHECK-NEXT: i32.xor $push[[L3:[0-9]+]]=, $pop[[L1]], $pop[[L2]]
346 ; CHECK-NEXT: i32.const $push[[L6:[0-9]+]]=, 1
347 ; CHECK-NEXT: i32.add $push[[L4:[0-9]+]]=, $pop[[L3]], $pop[[L6]]
348 ; CHECK-NEXT: i32.const $push[[L5:[0-9]+]]=, 1
349 ; CHECK-NEXT: i32.xor $push[[L0:[0-9]+]]=, $pop[[L4]], $pop[[L5]]
350 ; CHECK-NEXT: br_table $pop[[L0]], 0, 1, 2, 3
351 define void @xor_add_switch(double %a, double %b) {
353 %cmp = fcmp ult double %a, %b
354 %zext = zext i1 %cmp to i32
355 %add = add nsw nuw i32 %zext, 1
356 %xor = xor i32 %add, 1
357 switch i32 %xor, label %exit [
358 i32 0, label %sw.bb.1
359 i32 1, label %sw.bb.2
360 i32 2, label %sw.bb.3
364 tail call void @foo1()
368 tail call void @foo2()
372 tail call void @foo3()
382 declare void @call1()