1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
3 ; Test that basic 32-bit floating-point comparison operations assemble as
6 target triple = "wasm32-unknown-unknown"
8 ; CHECK-LABEL: ord_f32:
9 ; CHECK-NEXT: .functype ord_f32 (f32, f32) -> (i32){{$}}
10 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
11 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 0{{$}}
12 ; CHECK-NEXT: f32.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: f32.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_f32(float %x, float %y) {
19 %a = fcmp ord float %x, %y
20 %b = zext i1 %a to i32
24 ; CHECK-LABEL: uno_f32:
25 ; CHECK-NEXT: .functype uno_f32 (f32, f32) -> (i32){{$}}
26 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
27 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 0{{$}}
28 ; CHECK-NEXT: f32.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: f32.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_f32(float %x, float %y) {
35 %a = fcmp uno float %x, %y
36 %b = zext i1 %a to i32
40 ; CHECK-LABEL: oeq_f32:
41 ; CHECK-NEXT: .functype oeq_f32 (f32, f32) -> (i32){{$}}
42 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
43 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
44 ; CHECK-NEXT: f32.eq $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
45 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
46 define i32 @oeq_f32(float %x, float %y) {
47 %a = fcmp oeq float %x, %y
48 %b = zext i1 %a to i32
52 ; CHECK-LABEL: une_f32:
53 ; CHECK: f32.ne $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
54 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
55 define i32 @une_f32(float %x, float %y) {
56 %a = fcmp une float %x, %y
57 %b = zext i1 %a to i32
61 ; CHECK-LABEL: olt_f32:
62 ; CHECK: f32.lt $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
63 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
64 define i32 @olt_f32(float %x, float %y) {
65 %a = fcmp olt float %x, %y
66 %b = zext i1 %a to i32
70 ; CHECK-LABEL: ole_f32:
71 ; CHECK: f32.le $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
72 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
73 define i32 @ole_f32(float %x, float %y) {
74 %a = fcmp ole float %x, %y
75 %b = zext i1 %a to i32
79 ; CHECK-LABEL: ogt_f32:
80 ; CHECK: f32.gt $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
81 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
82 define i32 @ogt_f32(float %x, float %y) {
83 %a = fcmp ogt float %x, %y
84 %b = zext i1 %a to i32
88 ; CHECK-LABEL: oge_f32:
89 ; CHECK: f32.ge $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
90 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
91 define i32 @oge_f32(float %x, float %y) {
92 %a = fcmp oge float %x, %y
93 %b = zext i1 %a to i32
97 ; Expanded comparisons, which also check for NaN.
98 ; These simply rely on SDAG's Expand cond code action.
100 ; CHECK-LABEL: ueq_f32:
101 ; CHECK-NEXT: .functype ueq_f32 (f32, f32) -> (i32){{$}}
102 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
103 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
104 ; CHECK-NEXT: f32.gt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
105 ; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 0{{$}}
106 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1{{$}}
107 ; CHECK-NEXT: f32.lt $push[[NUM1:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}}
108 ; CHECK-NEXT: i32.or $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}}
109 ; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1
110 ; CHECK-NEXT: i32.xor $push[[NUM3:[0-9]+]]=, $pop[[NUM2]], $pop[[C0]]{{$}}
111 ; CHECK-NEXT: return $pop[[NUM3]]{{$}}
112 define i32 @ueq_f32(float %x, float %y) {
113 %a = fcmp ueq float %x, %y
114 %b = zext i1 %a to i32
118 ; CHECK-LABEL: one_f32:
119 ; CHECK-NEXT: .functype one_f32 (f32, f32) -> (i32){{$}}
120 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
121 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
122 ; CHECK-NEXT: f32.gt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
123 ; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 0{{$}}
124 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1{{$}}
125 ; CHECK-NEXT: f32.lt $push[[NUM1:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}}
126 ; CHECK-NEXT: i32.or $push[[NUM4:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}}
127 ; CHECK-NEXT: return $pop[[NUM4]]
128 define i32 @one_f32(float %x, float %y) {
129 %a = fcmp one float %x, %y
130 %b = zext i1 %a to i32
134 ; CHECK-LABEL: ult_f32:
135 ; CHECK-NEXT: .functype ult_f32 (f32, f32) -> (i32){{$}}
136 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
137 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
138 ; CHECK-NEXT: f32.ge $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
139 ; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1
140 ; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}}
141 ; CHECK-NEXT: return $pop[[NUM2]]{{$}}
142 define i32 @ult_f32(float %x, float %y) {
143 %a = fcmp ult float %x, %y
144 %b = zext i1 %a to i32
148 ; CHECK-LABEL: ule_f32:
149 ; CHECK-NEXT: .functype ule_f32 (f32, f32) -> (i32){{$}}
150 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
151 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
152 ; CHECK-NEXT: f32.gt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
153 ; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1
154 ; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}}
155 ; CHECK-NEXT: return $pop[[NUM2]]{{$}}
156 define i32 @ule_f32(float %x, float %y) {
157 %a = fcmp ule float %x, %y
158 %b = zext i1 %a to i32
162 ; CHECK-LABEL: ugt_f32:
163 ; CHECK-NEXT: .functype ugt_f32 (f32, f32) -> (i32){{$}}
164 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
165 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
166 ; CHECK-NEXT: f32.le $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
167 ; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1
168 ; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}}
169 ; CHECK-NEXT: return $pop[[NUM2]]{{$}}
170 define i32 @ugt_f32(float %x, float %y) {
171 %a = fcmp ugt float %x, %y
172 %b = zext i1 %a to i32
176 ; CHECK-LABEL: uge_f32:
177 ; CHECK-NEXT: .functype uge_f32 (f32, f32) -> (i32){{$}}
178 ; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
179 ; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
180 ; CHECK-NEXT: f32.lt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
181 ; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1
182 ; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}}
183 ; CHECK-NEXT: return $pop[[NUM2]]{{$}}
184 define i32 @uge_f32(float %x, float %y) {
185 %a = fcmp uge float %x, %y
186 %b = zext i1 %a to i32
190 ; CHECK-LABEL: olt_f32_branch
191 ; CHECK: local.get $push[[L4:[0-9]+]]=, 0
192 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1
193 ; CHECK-NEXT: f32.lt $push[[NUM0:[0-9]+]]=, $pop[[L4]], $pop[[L3]]
194 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
195 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
196 ; CHECK-NEXT: call call1
197 define void @olt_f32_branch(float %a, float %b) {
199 %cmp = fcmp olt float %a, %b
200 br i1 %cmp, label %if.then, label %if.end
203 tail call void @call1()
210 ; CHECK-LABEL: ole_f32_branch
211 ; CHECK: local.get $push[[L4:[0-9]+]]=, 0
212 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1
213 ; CHECK-NEXT: f32.le $push[[NUM0:[0-9]+]]=, $pop[[L4]], $pop[[L3]]
214 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
215 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
216 ; CHECK-NEXT: call call1
217 define void @ole_f32_branch(float %a, float %b) {
219 %cmp = fcmp ole float %a, %b
220 br i1 %cmp, label %if.then, label %if.end
223 tail call void @call1()
230 ; CHECK-LABEL: ugt_f32_branch
231 ; CHECK: local.get $push[[L4:[0-9]+]]=, 0
232 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1
233 ; CHECK-NEXT: f32.le $push[[NUM0:[0-9]+]]=, $pop[[L4]], $pop[[L3]]
234 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
235 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
236 ; CHECK-NEXT: call call1
237 define void @ugt_f32_branch(float %a, float %b) {
239 %cmp = fcmp ugt float %a, %b
240 br i1 %cmp, label %if.end, label %if.then
243 tail call void @call1()
250 ; CHECK-LABEL: ogt_f32_branch
251 ; CHECK: local.get $push[[L4:[0-9]+]]=, 0
252 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1
253 ; CHECK-NEXT: f32.gt $push[[NUM0:[0-9]+]]=, $pop[[L4]], $pop[[L3]]
254 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
255 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
256 ; CHECK-NEXT: call call1
257 define void @ogt_f32_branch(float %a, float %b) {
259 %cmp = fcmp ogt float %a, %b
260 br i1 %cmp, label %if.then, label %if.end
263 tail call void @call1()
270 ; CHECK-LABEL: ult_f32_branch
271 ; CHECK: local.get $push[[L4:[0-9]+]]=, 0
272 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1
273 ; CHECK-NEXT: f32.ge $push[[NUM0:[0-9]+]]=, $pop[[L4]], $pop[[L3]]
274 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
275 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
276 ; CHECK-NEXT: call call1
277 define void @ult_f32_branch(float %a, float %b) {
279 %cmp = fcmp ult float %a, %b
280 br i1 %cmp, label %if.end, label %if.then
283 tail call void @call1()
290 ; CHECK-LABEL: ule_f32_branch
291 ; CHECK: local.get $push[[L4:[0-9]+]]=, 0
292 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1
293 ; CHECK-NEXT: f32.ge $push[[NUM0:[0-9]+]]=, $pop[[L4]], $pop[[L3]]
294 ; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]]
295 ; CHECK-NEXT: br_if 0, $pop[[NUM3]]
296 ; CHECK-NEXT: call call1
297 define void @ule_f32_branch(float %a, float %b) {
299 %cmp = fcmp ult float %a, %b
300 br i1 %cmp, label %if.end, label %if.then
303 tail call void @call1()
310 ; CHECK-LABEL: xor_zext_switch
311 ; CHECK: i32.const $push[[L1:[0-9]+]]=, 0
312 ; CHECK-NEXT: br_if 0, $pop[[L1]]
315 ; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 0
316 ; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 1
317 ; CHECK-NEXT: f32.ge $push[[L0:[0-9]+]]=, $pop[[L3]], $pop[[L2]]
318 ; CHECK-NEXT: br_table $pop[[L0]], 0, 1, 0
319 define void @xor_zext_switch(float %a, float %b) {
321 %cmp = fcmp ult float %a, %b
322 %zext = zext i1 %cmp to i32
323 %xor = xor i32 %zext, 1
324 switch i32 %xor, label %exit [
325 i32 0, label %sw.bb.1
326 i32 1, label %sw.bb.2
330 tail call void @foo1()
334 tail call void @foo2()
341 ; CHECK-LABEL: xor_add_switch
342 ; CHECK: local.get $push[[L8:[0-9]+]]=, 0
343 ; CHECK-NEXT: local.get $push[[L7:[0-9]+]]=, 1
344 ; CHECK-NEXT: f32.ge $push[[L1:[0-9]+]]=, $pop[[L8]], $pop[[L7]]
345 ; CHECK-NEXT: i32.const $push[[L2:[0-9]+]]=, 1
346 ; CHECK-NEXT: i32.xor $push[[L3:[0-9]+]]=, $pop[[L1]], $pop[[L2]]
347 ; CHECK-NEXT: i32.const $push[[L6:[0-9]+]]=, 1
348 ; CHECK-NEXT: i32.add $push[[L4:[0-9]+]]=, $pop[[L3]], $pop[[L6]]
349 ; CHECK-NEXT: i32.const $push[[L5:[0-9]+]]=, 1
350 ; CHECK-NEXT: i32.xor $push[[L0:[0-9]+]]=, $pop[[L4]], $pop[[L5]]
351 ; CHECK-NEXT: br_table $pop[[L0]], 0, 1, 2, 3
352 define void @xor_add_switch(float %a, float %b) {
354 %cmp = fcmp ult float %a, %b
355 %zext = zext i1 %cmp to i32
356 %add = add nsw nuw i32 %zext, 1
357 %xor = xor i32 %add, 1
358 switch i32 %xor, label %exit [
359 i32 0, label %sw.bb.1
360 i32 1, label %sw.bb.2
361 i32 2, label %sw.bb.3
365 tail call void @foo1()
369 tail call void @foo2()
373 tail call void @foo3()
383 declare void @call1()