[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / CodeGen / AArch64 / arm64-xaluo.ll
blob6ae5b355641366312d8c3b52b7d81f3b658bd196
1 ; RUN: llc < %s -mtriple=arm64-eabi -aarch64-enable-atomic-cfg-tidy=0 -disable-post-ra -verify-machineinstrs | FileCheck %s
2 ; RUN: llc < %s -mtriple=arm64-eabi -aarch64-enable-atomic-cfg-tidy=0 -fast-isel -fast-isel-abort=1 -disable-post-ra -verify-machineinstrs | FileCheck %s
3 ; RUN: llc < %s -mtriple=arm64-eabi -aarch64-enable-atomic-cfg-tidy=0 -global-isel -global-isel-abort=2 -pass-remarks-missed=gisel* -disable-post-ra -verify-machineinstrs | FileCheck %s --check-prefixes=GISEL,FALLBACK
6 ; Get the actual value of the overflow bit.
8 define zeroext i1 @saddo1.i32(i32 %v1, i32 %v2, i32* %res) {
9 entry:
10 ; CHECK-LABEL:  saddo1.i32
11 ; CHECK:        adds {{w[0-9]+}}, w0, w1
12 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
13   %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
14   %val = extractvalue {i32, i1} %t, 0
15   %obit = extractvalue {i32, i1} %t, 1
16   store i32 %val, i32* %res
17   ret i1 %obit
20 ; Test the immediate version.
21 define zeroext i1 @saddo2.i32(i32 %v1, i32* %res) {
22 entry:
23 ; CHECK-LABEL:  saddo2.i32
24 ; CHECK:        adds {{w[0-9]+}}, w0, #4
25 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
26   %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 4)
27   %val = extractvalue {i32, i1} %t, 0
28   %obit = extractvalue {i32, i1} %t, 1
29   store i32 %val, i32* %res
30   ret i1 %obit
33 ; Test negative immediates.
34 define zeroext i1 @saddo3.i32(i32 %v1, i32* %res) {
35 entry:
36 ; CHECK-LABEL:  saddo3.i32
37 ; CHECK:        subs {{w[0-9]+}}, w0, #4
38 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
39   %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 -4)
40   %val = extractvalue {i32, i1} %t, 0
41   %obit = extractvalue {i32, i1} %t, 1
42   store i32 %val, i32* %res
43   ret i1 %obit
46 ; Test immediates that are too large to be encoded.
47 define zeroext i1 @saddo4.i32(i32 %v1, i32* %res) {
48 entry:
49 ; CHECK-LABEL:  saddo4.i32
50 ; CHECK:        adds {{w[0-9]+}}, w0, {{w[0-9]+}}
51 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
52   %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 16777215)
53   %val = extractvalue {i32, i1} %t, 0
54   %obit = extractvalue {i32, i1} %t, 1
55   store i32 %val, i32* %res
56   ret i1 %obit
59 ; Test shift folding.
60 define zeroext i1 @saddo5.i32(i32 %v1, i32 %v2, i32* %res) {
61 entry:
62 ; CHECK-LABEL:  saddo5.i32
63 ; CHECK:        adds {{w[0-9]+}}, w0, w1
64 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
65   %lsl = shl i32 %v2, 16
66   %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %lsl)
67   %val = extractvalue {i32, i1} %t, 0
68   %obit = extractvalue {i32, i1} %t, 1
69   store i32 %val, i32* %res
70   ret i1 %obit
73 define zeroext i1 @saddo1.i64(i64 %v1, i64 %v2, i64* %res) {
74 entry:
75 ; CHECK-LABEL:  saddo1.i64
76 ; CHECK:        adds {{x[0-9]+}}, x0, x1
77 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
78   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2)
79   %val = extractvalue {i64, i1} %t, 0
80   %obit = extractvalue {i64, i1} %t, 1
81   store i64 %val, i64* %res
82   ret i1 %obit
85 define zeroext i1 @saddo2.i64(i64 %v1, i64* %res) {
86 entry:
87 ; CHECK-LABEL:  saddo2.i64
88 ; CHECK:        adds {{x[0-9]+}}, x0, #4
89 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
90   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 4)
91   %val = extractvalue {i64, i1} %t, 0
92   %obit = extractvalue {i64, i1} %t, 1
93   store i64 %val, i64* %res
94   ret i1 %obit
97 define zeroext i1 @saddo3.i64(i64 %v1, i64* %res) {
98 entry:
99 ; CHECK-LABEL:  saddo3.i64
100 ; CHECK:        subs {{x[0-9]+}}, x0, #4
101 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
102   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 -4)
103   %val = extractvalue {i64, i1} %t, 0
104   %obit = extractvalue {i64, i1} %t, 1
105   store i64 %val, i64* %res
106   ret i1 %obit
109 ; FALLBACK-NOT: remark{{.*}}uaddo.i32
110 define zeroext i1 @uaddo.i32(i32 %v1, i32 %v2, i32* %res) {
111 entry:
112 ; CHECK-LABEL:  uaddo.i32
113 ; CHECK:        adds {{w[0-9]+}}, w0, w1
114 ; CHECK-NEXT:   cset {{w[0-9]+}}, hs
115 ; GISEL-LABEL:  uaddo.i32
116 ; GISEL:        adds {{w[0-9]+}}, w0, w1
117 ; GISEL-NEXT:   cset {{w[0-9]+}}, hs
118   %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2)
119   %val = extractvalue {i32, i1} %t, 0
120   %obit = extractvalue {i32, i1} %t, 1
121   store i32 %val, i32* %res
122   ret i1 %obit
125 ; FALLBACK-NOT: remark{{.*}}uaddo.i64
126 define zeroext i1 @uaddo.i64(i64 %v1, i64 %v2, i64* %res) {
127 entry:
128 ; CHECK-LABEL:  uaddo.i64
129 ; CHECK:        adds {{x[0-9]+}}, x0, x1
130 ; CHECK-NEXT:   cset {{w[0-9]+}}, hs
131 ; GISEL-LABEL:  uaddo.i64
132 ; GISEL:        adds {{x[0-9]+}}, x0, x1
133 ; GISEL-NEXT:   cset {{w[0-9]+}}, hs
134   %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2)
135   %val = extractvalue {i64, i1} %t, 0
136   %obit = extractvalue {i64, i1} %t, 1
137   store i64 %val, i64* %res
138   ret i1 %obit
141 define zeroext i1 @ssubo1.i32(i32 %v1, i32 %v2, i32* %res) {
142 entry:
143 ; CHECK-LABEL:  ssubo1.i32
144 ; CHECK:        subs {{w[0-9]+}}, w0, w1
145 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
146   %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2)
147   %val = extractvalue {i32, i1} %t, 0
148   %obit = extractvalue {i32, i1} %t, 1
149   store i32 %val, i32* %res
150   ret i1 %obit
153 define zeroext i1 @ssubo2.i32(i32 %v1, i32* %res) {
154 entry:
155 ; CHECK-LABEL:  ssubo2.i32
156 ; CHECK:        adds {{w[0-9]+}}, w0, #4
157 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
158   %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 -4)
159   %val = extractvalue {i32, i1} %t, 0
160   %obit = extractvalue {i32, i1} %t, 1
161   store i32 %val, i32* %res
162   ret i1 %obit
165 define zeroext i1 @ssubo.i64(i64 %v1, i64 %v2, i64* %res) {
166 entry:
167 ; CHECK-LABEL:  ssubo.i64
168 ; CHECK:        subs {{x[0-9]+}}, x0, x1
169 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
170   %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2)
171   %val = extractvalue {i64, i1} %t, 0
172   %obit = extractvalue {i64, i1} %t, 1
173   store i64 %val, i64* %res
174   ret i1 %obit
177 define zeroext i1 @usubo.i32(i32 %v1, i32 %v2, i32* %res) {
178 entry:
179 ; CHECK-LABEL:  usubo.i32
180 ; CHECK:        subs {{w[0-9]+}}, w0, w1
181 ; CHECK-NEXT:   cset {{w[0-9]+}}, lo
182   %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2)
183   %val = extractvalue {i32, i1} %t, 0
184   %obit = extractvalue {i32, i1} %t, 1
185   store i32 %val, i32* %res
186   ret i1 %obit
189 define zeroext i1 @usubo.i64(i64 %v1, i64 %v2, i64* %res) {
190 entry:
191 ; CHECK-LABEL:  usubo.i64
192 ; CHECK:        subs {{x[0-9]+}}, x0, x1
193 ; CHECK-NEXT:   cset {{w[0-9]+}}, lo
194   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2)
195   %val = extractvalue {i64, i1} %t, 0
196   %obit = extractvalue {i64, i1} %t, 1
197   store i64 %val, i64* %res
198   ret i1 %obit
201 define zeroext i1 @smulo.i32(i32 %v1, i32 %v2, i32* %res) {
202 entry:
203 ; CHECK-LABEL:  smulo.i32
204 ; CHECK:        smull x[[MREG:[0-9]+]], w0, w1
205 ; CHECK-NEXT:   lsr x[[SREG:[0-9]+]], x[[MREG]], #32
206 ; CHECK-NEXT:   cmp w[[SREG]], w[[MREG]], asr #31
207 ; CHECK-NEXT:   cset {{w[0-9]+}}, ne
208   %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
209   %val = extractvalue {i32, i1} %t, 0
210   %obit = extractvalue {i32, i1} %t, 1
211   store i32 %val, i32* %res
212   ret i1 %obit
215 define zeroext i1 @smulo.i64(i64 %v1, i64 %v2, i64* %res) {
216 entry:
217 ; CHECK-LABEL:  smulo.i64
218 ; CHECK:        mul [[MREG:x[0-9]+]], x0, x1
219 ; CHECK-NEXT:   smulh [[HREG:x[0-9]+]], x0, x1
220 ; CHECK-NEXT:   cmp [[HREG]], [[MREG]], asr #63
221 ; CHECK-NEXT:   cset {{w[0-9]+}}, ne
222   %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2)
223   %val = extractvalue {i64, i1} %t, 0
224   %obit = extractvalue {i64, i1} %t, 1
225   store i64 %val, i64* %res
226   ret i1 %obit
229 define zeroext i1 @smulo2.i64(i64 %v1, i64* %res) {
230 entry:
231 ; CHECK-LABEL:  smulo2.i64
232 ; CHECK:        adds [[MREG:x[0-9]+]], x0, x0
233 ; CHECK-NEXT:   cset {{w[0-9]+}}, vs
234   %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 2)
235   %val = extractvalue {i64, i1} %t, 0
236   %obit = extractvalue {i64, i1} %t, 1
237   store i64 %val, i64* %res
238   ret i1 %obit
241 define zeroext i1 @umulo.i32(i32 %v1, i32 %v2, i32* %res) {
242 entry:
243 ; CHECK-LABEL:  umulo.i32
244 ; CHECK:        umull [[MREG:x[0-9]+]], w0, w1
245 ; CHECK-NEXT:   cmp xzr, [[MREG]], lsr #32
246 ; CHECK-NEXT:   cset {{w[0-9]+}}, ne
247   %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2)
248   %val = extractvalue {i32, i1} %t, 0
249   %obit = extractvalue {i32, i1} %t, 1
250   store i32 %val, i32* %res
251   ret i1 %obit
254 define zeroext i1 @umulo.i64(i64 %v1, i64 %v2, i64* %res) {
255 entry:
256 ; CHECK-LABEL:  umulo.i64
257 ; CHECK:        umulh [[MREG:x[0-9]+]], x0, x1
258 ; CHECK-NEXT:   cmp xzr, [[MREG]]
259 ; CHECK-NEXT:   cset {{w[0-9]+}}, ne
260   %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2)
261   %val = extractvalue {i64, i1} %t, 0
262   %obit = extractvalue {i64, i1} %t, 1
263   store i64 %val, i64* %res
264   ret i1 %obit
267 define zeroext i1 @umulo2.i64(i64 %v1, i64* %res) {
268 entry:
269 ; CHECK-LABEL:  umulo2.i64
270 ; CHECK:        adds [[MREG:x[0-9]+]], x0, x0
271 ; CHECK-NEXT:   cset {{w[0-9]+}}, hs
272   %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 2)
273   %val = extractvalue {i64, i1} %t, 0
274   %obit = extractvalue {i64, i1} %t, 1
275   store i64 %val, i64* %res
276   ret i1 %obit
281 ; Check the use of the overflow bit in combination with a select instruction.
283 define i32 @saddo.select.i32(i32 %v1, i32 %v2) {
284 entry:
285 ; CHECK-LABEL:  saddo.select.i32
286 ; CHECK:        cmn w0, w1
287 ; CHECK-NEXT:   csel w0, w0, w1, vs
288   %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
289   %obit = extractvalue {i32, i1} %t, 1
290   %ret = select i1 %obit, i32 %v1, i32 %v2
291   ret i32 %ret
294 define i1 @saddo.not.i32(i32 %v1, i32 %v2) {
295 entry:
296 ; CHECK-LABEL:  saddo.not.i32
297 ; CHECK:        cmn w0, w1
298 ; CHECK-NEXT:   cset w0, vc
299   %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
300   %obit = extractvalue {i32, i1} %t, 1
301   %ret = xor i1 %obit, true
302   ret i1 %ret
305 define i64 @saddo.select.i64(i64 %v1, i64 %v2) {
306 entry:
307 ; CHECK-LABEL:  saddo.select.i64
308 ; CHECK:        cmn x0, x1
309 ; CHECK-NEXT:   csel x0, x0, x1, vs
310   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2)
311   %obit = extractvalue {i64, i1} %t, 1
312   %ret = select i1 %obit, i64 %v1, i64 %v2
313   ret i64 %ret
316 define i1 @saddo.not.i64(i64 %v1, i64 %v2) {
317 entry:
318 ; CHECK-LABEL:  saddo.not.i64
319 ; CHECK:        cmn x0, x1
320 ; CHECK-NEXT:   cset w0, vc
321   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2)
322   %obit = extractvalue {i64, i1} %t, 1
323   %ret = xor i1 %obit, true
324   ret i1 %ret
327 define i32 @uaddo.select.i32(i32 %v1, i32 %v2) {
328 entry:
329 ; CHECK-LABEL:  uaddo.select.i32
330 ; CHECK:        cmn w0, w1
331 ; CHECK-NEXT:   csel w0, w0, w1, hs
332   %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2)
333   %obit = extractvalue {i32, i1} %t, 1
334   %ret = select i1 %obit, i32 %v1, i32 %v2
335   ret i32 %ret
338 define i1 @uaddo.not.i32(i32 %v1, i32 %v2) {
339 entry:
340 ; CHECK-LABEL:  uaddo.not.i32
341 ; CHECK:        cmn w0, w1
342 ; CHECK-NEXT:   cset w0, lo
343   %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2)
344   %obit = extractvalue {i32, i1} %t, 1
345   %ret = xor i1 %obit, true
346   ret i1 %ret
349 define i64 @uaddo.select.i64(i64 %v1, i64 %v2) {
350 entry:
351 ; CHECK-LABEL:  uaddo.select.i64
352 ; CHECK:        cmn x0, x1
353 ; CHECK-NEXT:   csel x0, x0, x1, hs
354   %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2)
355   %obit = extractvalue {i64, i1} %t, 1
356   %ret = select i1 %obit, i64 %v1, i64 %v2
357   ret i64 %ret
360 define i1 @uaddo.not.i64(i64 %v1, i64 %v2) {
361 entry:
362 ; CHECK-LABEL:  uaddo.not.i64
363 ; CHECK:        cmn x0, x1
364 ; CHECK-NEXT:   cset w0, lo
365   %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2)
366   %obit = extractvalue {i64, i1} %t, 1
367   %ret = xor i1 %obit, true
368   ret i1 %ret
371 define i32 @ssubo.select.i32(i32 %v1, i32 %v2) {
372 entry:
373 ; CHECK-LABEL:  ssubo.select.i32
374 ; CHECK:        cmp w0, w1
375 ; CHECK-NEXT:   csel w0, w0, w1, vs
376   %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2)
377   %obit = extractvalue {i32, i1} %t, 1
378   %ret = select i1 %obit, i32 %v1, i32 %v2
379   ret i32 %ret
382 define i1 @ssubo.not.i32(i32 %v1, i32 %v2) {
383 entry:
384 ; CHECK-LABEL:  ssubo.not.i32
385 ; CHECK:        cmp w0, w1
386 ; CHECK-NEXT:   cset w0, vc
387   %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2)
388   %obit = extractvalue {i32, i1} %t, 1
389   %ret = xor i1 %obit, true
390   ret i1 %ret
393 define i64 @ssubo.select.i64(i64 %v1, i64 %v2) {
394 entry:
395 ; CHECK-LABEL:  ssubo.select.i64
396 ; CHECK:        cmp x0, x1
397 ; CHECK-NEXT:   csel x0, x0, x1, vs
398   %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2)
399   %obit = extractvalue {i64, i1} %t, 1
400   %ret = select i1 %obit, i64 %v1, i64 %v2
401   ret i64 %ret
404 define i1 @ssub.not.i64(i64 %v1, i64 %v2) {
405 entry:
406 ; CHECK-LABEL:  ssub.not.i64
407 ; CHECK:        cmp x0, x1
408 ; CHECK-NEXT:   cset w0, vc
409   %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2)
410   %obit = extractvalue {i64, i1} %t, 1
411   %ret = xor i1 %obit, true
412   ret i1 %ret
415 define i32 @usubo.select.i32(i32 %v1, i32 %v2) {
416 entry:
417 ; CHECK-LABEL:  usubo.select.i32
418 ; CHECK:        cmp w0, w1
419 ; CHECK-NEXT:   csel w0, w0, w1, lo
420   %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2)
421   %obit = extractvalue {i32, i1} %t, 1
422   %ret = select i1 %obit, i32 %v1, i32 %v2
423   ret i32 %ret
426 define i1 @usubo.not.i32(i32 %v1, i32 %v2) {
427 entry:
428 ; CHECK-LABEL:  usubo.not.i32
429 ; CHECK:        cmp w0, w1
430 ; CHECK-NEXT:   cset w0, hs
431   %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2)
432   %obit = extractvalue {i32, i1} %t, 1
433   %ret = xor i1 %obit, true
434   ret i1 %ret
437 define i64 @usubo.select.i64(i64 %v1, i64 %v2) {
438 entry:
439 ; CHECK-LABEL:  usubo.select.i64
440 ; CHECK:        cmp x0, x1
441 ; CHECK-NEXT:   csel x0, x0, x1, lo
442   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2)
443   %obit = extractvalue {i64, i1} %t, 1
444   %ret = select i1 %obit, i64 %v1, i64 %v2
445   ret i64 %ret
448 define i1 @usubo.not.i64(i64 %v1, i64 %v2) {
449 entry:
450 ; CHECK-LABEL:  usubo.not.i64
451 ; CHECK:        cmp x0, x1
452 ; CHECK-NEXT:   cset w0, hs
453   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2)
454   %obit = extractvalue {i64, i1} %t, 1
455   %ret = xor i1 %obit, true
456   ret i1 %ret
459 define i32 @smulo.select.i32(i32 %v1, i32 %v2) {
460 entry:
461 ; CHECK-LABEL:  smulo.select.i32
462 ; CHECK:        smull   x[[MREG:[0-9]+]], w0, w1
463 ; CHECK-NEXT:   lsr     x[[SREG:[0-9]+]], x[[MREG]], #32
464 ; CHECK-NEXT:   cmp     w[[SREG]], w[[MREG]], asr #31
465 ; CHECK-NEXT:   csel    w0, w0, w1, ne
466   %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
467   %obit = extractvalue {i32, i1} %t, 1
468   %ret = select i1 %obit, i32 %v1, i32 %v2
469   ret i32 %ret
472 define i1 @smulo.not.i32(i32 %v1, i32 %v2) {
473 entry:
474 ; CHECK-LABEL:  smulo.not.i32
475 ; CHECK:        smull   x[[MREG:[0-9]+]], w0, w1
476 ; CHECK-NEXT:   lsr     x[[SREG:[0-9]+]], x[[MREG]], #32
477 ; CHECK-NEXT:   cmp     w[[SREG]], w[[MREG]], asr #31
478 ; CHECK-NEXT:   cset    w0, eq
479   %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
480   %obit = extractvalue {i32, i1} %t, 1
481   %ret = xor i1 %obit, true
482   ret i1 %ret
485 define i64 @smulo.select.i64(i64 %v1, i64 %v2) {
486 entry:
487 ; CHECK-LABEL:  smulo.select.i64
488 ; CHECK:        mul     [[MREG:x[0-9]+]], x0, x1
489 ; CHECK-NEXT:   smulh   [[HREG:x[0-9]+]], x0, x1
490 ; CHECK-NEXT:   cmp     [[HREG]], [[MREG]], asr #63
491 ; CHECK-NEXT:   csel    x0, x0, x1, ne
492   %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2)
493   %obit = extractvalue {i64, i1} %t, 1
494   %ret = select i1 %obit, i64 %v1, i64 %v2
495   ret i64 %ret
498 define i1 @smulo.not.i64(i64 %v1, i64 %v2) {
499 entry:
500 ; CHECK-LABEL:  smulo.not.i64
501 ; CHECK:        mul     [[MREG:x[0-9]+]], x0, x1
502 ; CHECK-NEXT:   smulh   [[HREG:x[0-9]+]], x0, x1
503 ; CHECK-NEXT:   cmp     [[HREG]], [[MREG]], asr #63
504 ; CHECK-NEXT:   cset    w0, eq
505   %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2)
506   %obit = extractvalue {i64, i1} %t, 1
507   %ret = xor i1 %obit, true
508   ret i1 %ret
511 define i32 @umulo.select.i32(i32 %v1, i32 %v2) {
512 entry:
513 ; CHECK-LABEL:  umulo.select.i32
514 ; CHECK:        umull   [[MREG:x[0-9]+]], w0, w1
515 ; CHECK-NEXT:   cmp     xzr, [[MREG]], lsr #32
516 ; CHECK-NEXT:   csel    w0, w0, w1, ne
517   %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2)
518   %obit = extractvalue {i32, i1} %t, 1
519   %ret = select i1 %obit, i32 %v1, i32 %v2
520   ret i32 %ret
523 define i1 @umulo.not.i32(i32 %v1, i32 %v2) {
524 entry:
525 ; CHECK-LABEL:  umulo.not.i32
526 ; CHECK:        umull   [[MREG:x[0-9]+]], w0, w1
527 ; CHECK-NEXT:   cmp     xzr, [[MREG]], lsr #32
528 ; CHECK-NEXT:   cset    w0, eq
529   %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2)
530   %obit = extractvalue {i32, i1} %t, 1
531   %ret = xor i1 %obit, true
532   ret i1 %ret
535 define i64 @umulo.select.i64(i64 %v1, i64 %v2) {
536 entry:
537 ; CHECK-LABEL:  umulo.select.i64
538 ; CHECK:        umulh   [[MREG:x[0-9]+]], x0, x1
539 ; CHECK-NEXT:   cmp     xzr, [[MREG]]
540 ; CHECK-NEXT:   csel    x0, x0, x1, ne
541   %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2)
542   %obit = extractvalue {i64, i1} %t, 1
543   %ret = select i1 %obit, i64 %v1, i64 %v2
544   ret i64 %ret
547 define i1 @umulo.not.i64(i64 %v1, i64 %v2) {
548 entry:
549 ; CHECK-LABEL:  umulo.not.i64
550 ; CHECK:        umulh   [[MREG:x[0-9]+]], x0, x1
551 ; CHECK-NEXT:   cmp     xzr, [[MREG]]
552 ; CHECK-NEXT:   cset    w0, eq
553   %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2)
554   %obit = extractvalue {i64, i1} %t, 1
555   %ret = xor i1 %obit, true
556   ret i1 %ret
561 ; Check the use of the overflow bit in combination with a branch instruction.
563 define zeroext i1 @saddo.br.i32(i32 %v1, i32 %v2) {
564 entry:
565 ; CHECK-LABEL:  saddo.br.i32
566 ; CHECK:        cmn w0, w1
567 ; CHECK-NEXT:   b.vc
568   %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
569   %val = extractvalue {i32, i1} %t, 0
570   %obit = extractvalue {i32, i1} %t, 1
571   br i1 %obit, label %overflow, label %continue
573 overflow:
574   ret i1 false
576 continue:
577   ret i1 true
580 define zeroext i1 @saddo.br.i64(i64 %v1, i64 %v2) {
581 entry:
582 ; CHECK-LABEL:  saddo.br.i64
583 ; CHECK:        cmn x0, x1
584 ; CHECK-NEXT:   b.vc
585   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2)
586   %val = extractvalue {i64, i1} %t, 0
587   %obit = extractvalue {i64, i1} %t, 1
588   br i1 %obit, label %overflow, label %continue
590 overflow:
591   ret i1 false
593 continue:
594   ret i1 true
597 define zeroext i1 @uaddo.br.i32(i32 %v1, i32 %v2) {
598 entry:
599 ; CHECK-LABEL:  uaddo.br.i32
600 ; CHECK:        cmn w0, w1
601 ; CHECK-NEXT:   b.lo
602   %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2)
603   %val = extractvalue {i32, i1} %t, 0
604   %obit = extractvalue {i32, i1} %t, 1
605   br i1 %obit, label %overflow, label %continue
607 overflow:
608   ret i1 false
610 continue:
611   ret i1 true
614 define zeroext i1 @uaddo.br.i64(i64 %v1, i64 %v2) {
615 entry:
616 ; CHECK-LABEL:  uaddo.br.i64
617 ; CHECK:        cmn x0, x1
618 ; CHECK-NEXT:   b.lo
619   %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2)
620   %val = extractvalue {i64, i1} %t, 0
621   %obit = extractvalue {i64, i1} %t, 1
622   br i1 %obit, label %overflow, label %continue
624 overflow:
625   ret i1 false
627 continue:
628   ret i1 true
631 define zeroext i1 @ssubo.br.i32(i32 %v1, i32 %v2) {
632 entry:
633 ; CHECK-LABEL:  ssubo.br.i32
634 ; CHECK:        cmp w0, w1
635 ; CHECK-NEXT:   b.vc
636   %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2)
637   %val = extractvalue {i32, i1} %t, 0
638   %obit = extractvalue {i32, i1} %t, 1
639   br i1 %obit, label %overflow, label %continue
641 overflow:
642   ret i1 false
644 continue:
645   ret i1 true
648 define zeroext i1 @ssubo.br.i64(i64 %v1, i64 %v2) {
649 entry:
650 ; CHECK-LABEL:  ssubo.br.i64
651 ; CHECK:        cmp x0, x1
652 ; CHECK-NEXT:   b.vc
653   %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2)
654   %val = extractvalue {i64, i1} %t, 0
655   %obit = extractvalue {i64, i1} %t, 1
656   br i1 %obit, label %overflow, label %continue
658 overflow:
659   ret i1 false
661 continue:
662   ret i1 true
665 define zeroext i1 @usubo.br.i32(i32 %v1, i32 %v2) {
666 entry:
667 ; CHECK-LABEL:  usubo.br.i32
668 ; CHECK:        cmp w0, w1
669 ; CHECK-NEXT:   b.hs
670   %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2)
671   %val = extractvalue {i32, i1} %t, 0
672   %obit = extractvalue {i32, i1} %t, 1
673   br i1 %obit, label %overflow, label %continue
675 overflow:
676   ret i1 false
678 continue:
679   ret i1 true
682 define zeroext i1 @usubo.br.i64(i64 %v1, i64 %v2) {
683 entry:
684 ; CHECK-LABEL:  usubo.br.i64
685 ; CHECK:        cmp x0, x1
686 ; CHECK-NEXT:   b.hs
687   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2)
688   %val = extractvalue {i64, i1} %t, 0
689   %obit = extractvalue {i64, i1} %t, 1
690   br i1 %obit, label %overflow, label %continue
692 overflow:
693   ret i1 false
695 continue:
696   ret i1 true
699 define zeroext i1 @smulo.br.i32(i32 %v1, i32 %v2) {
700 entry:
701 ; CHECK-LABEL:  smulo.br.i32
702 ; CHECK:        smull   x[[MREG:[0-9]+]], w0, w1
703 ; CHECK-NEXT:   lsr     x[[SREG:[0-9]+]], x8, #32
704 ; CHECK-NEXT:   cmp     w[[SREG]], w[[MREG]], asr #31
705 ; CHECK-NEXT:   b.eq
706   %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
707   %val = extractvalue {i32, i1} %t, 0
708   %obit = extractvalue {i32, i1} %t, 1
709   br i1 %obit, label %overflow, label %continue
711 overflow:
712   ret i1 false
714 continue:
715   ret i1 true
718 define zeroext i1 @smulo.br.i64(i64 %v1, i64 %v2) {
719 entry:
720 ; CHECK-LABEL:  smulo.br.i64
721 ; CHECK:        mul     [[MREG:x[0-9]+]], x0, x1
722 ; CHECK-NEXT:   smulh   [[HREG:x[0-9]+]], x0, x1
723 ; CHECK-NEXT:   cmp     [[HREG]], [[MREG]], asr #63
724 ; CHECK-NEXT:   b.eq
725   %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2)
726   %val = extractvalue {i64, i1} %t, 0
727   %obit = extractvalue {i64, i1} %t, 1
728   br i1 %obit, label %overflow, label %continue
730 overflow:
731   ret i1 false
733 continue:
734   ret i1 true
737 define zeroext i1 @smulo2.br.i64(i64 %v1) {
738 entry:
739 ; CHECK-LABEL:  smulo2.br.i64
740 ; CHECK:        cmn  x0, x0
741 ; CHECK-NEXT:   b.vc
742   %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 2)
743   %val = extractvalue {i64, i1} %t, 0
744   %obit = extractvalue {i64, i1} %t, 1
745   br i1 %obit, label %overflow, label %continue
747 overflow:
748   ret i1 false
750 continue:
751   ret i1 true
754 define zeroext i1 @umulo.br.i32(i32 %v1, i32 %v2) {
755 entry:
756 ; CHECK-LABEL:  umulo.br.i32
757 ; CHECK:        umull   [[MREG:x[0-9]+]], w0, w1
758 ; CHECK-NEXT:   cmp     xzr, [[MREG]], lsr #32
759 ; CHECK-NEXT:   b.eq
760   %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2)
761   %val = extractvalue {i32, i1} %t, 0
762   %obit = extractvalue {i32, i1} %t, 1
763   br i1 %obit, label %overflow, label %continue
765 overflow:
766   ret i1 false
768 continue:
769   ret i1 true
772 define zeroext i1 @umulo.br.i64(i64 %v1, i64 %v2) {
773 entry:
774 ; CHECK-LABEL:  umulo.br.i64
775 ; CHECK:        umulh   [[REG:x[0-9]+]], x0, x1
776 ; CHECK-NEXT:   {{cbz|cmp}}
777   %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2)
778   %val = extractvalue {i64, i1} %t, 0
779   %obit = extractvalue {i64, i1} %t, 1
780   br i1 %obit, label %overflow, label %continue
782 overflow:
783   ret i1 false
785 continue:
786   ret i1 true
789 define zeroext i1 @umulo2.br.i64(i64 %v1) {
790 entry:
791 ; CHECK-LABEL:  umulo2.br.i64
792 ; CHECK:        cmn  x0, x0
793 ; CHECK-NEXT:   b.lo
794   %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 2)
795   %val = extractvalue {i64, i1} %t, 0
796   %obit = extractvalue {i64, i1} %t, 1
797   br i1 %obit, label %overflow, label %continue
799 overflow:
800   ret i1 false
802 continue:
803   ret i1 true
806 declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
807 declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone
808 declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
809 declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone
810 declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone
811 declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone
812 declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone
813 declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone
814 declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
815 declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone
816 declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
817 declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone