1 ; RUN: llc < %s -march=arm64 | FileCheck %s
4 ; Get the actual value of the overflow bit.
6 define i1 @saddo.i32(i32 %v1, i32 %v2, i32* %res) {
8 ; CHECK-LABEL: saddo.i32
9 ; CHECK: adds w8, w0, w1
10 ; CHECK-NEXT: csinc w0, wzr, wzr, vc
11 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
12 %val = extractvalue {i32, i1} %t, 0
13 %obit = extractvalue {i32, i1} %t, 1
14 store i32 %val, i32* %res
18 define i1 @saddo.i64(i64 %v1, i64 %v2, i64* %res) {
20 ; CHECK-LABEL: saddo.i64
21 ; CHECK: adds x8, x0, x1
22 ; CHECK-NEXT: csinc w0, wzr, wzr, vc
23 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2)
24 %val = extractvalue {i64, i1} %t, 0
25 %obit = extractvalue {i64, i1} %t, 1
26 store i64 %val, i64* %res
30 define i1 @uaddo.i32(i32 %v1, i32 %v2, i32* %res) {
32 ; CHECK-LABEL: uaddo.i32
33 ; CHECK: adds w8, w0, w1
34 ; CHECK-NEXT: csinc w0, wzr, wzr, cc
35 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2)
36 %val = extractvalue {i32, i1} %t, 0
37 %obit = extractvalue {i32, i1} %t, 1
38 store i32 %val, i32* %res
42 define i1 @uaddo.i64(i64 %v1, i64 %v2, i64* %res) {
44 ; CHECK-LABEL: uaddo.i64
45 ; CHECK: adds x8, x0, x1
46 ; CHECK-NEXT: csinc w0, wzr, wzr, cc
47 %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2)
48 %val = extractvalue {i64, i1} %t, 0
49 %obit = extractvalue {i64, i1} %t, 1
50 store i64 %val, i64* %res
54 define i1 @ssubo.i32(i32 %v1, i32 %v2, i32* %res) {
56 ; CHECK-LABEL: ssubo.i32
57 ; CHECK: subs w8, w0, w1
58 ; CHECK-NEXT: csinc w0, wzr, wzr, vc
59 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2)
60 %val = extractvalue {i32, i1} %t, 0
61 %obit = extractvalue {i32, i1} %t, 1
62 store i32 %val, i32* %res
66 define i1 @ssubo.i64(i64 %v1, i64 %v2, i64* %res) {
68 ; CHECK-LABEL: ssubo.i64
69 ; CHECK: subs x8, x0, x1
70 ; CHECK-NEXT: csinc w0, wzr, wzr, vc
71 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2)
72 %val = extractvalue {i64, i1} %t, 0
73 %obit = extractvalue {i64, i1} %t, 1
74 store i64 %val, i64* %res
78 define i1 @usubo.i32(i32 %v1, i32 %v2, i32* %res) {
80 ; CHECK-LABEL: usubo.i32
81 ; CHECK: subs w8, w0, w1
82 ; CHECK-NEXT: csinc w0, wzr, wzr, cs
83 %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2)
84 %val = extractvalue {i32, i1} %t, 0
85 %obit = extractvalue {i32, i1} %t, 1
86 store i32 %val, i32* %res
90 define i1 @usubo.i64(i64 %v1, i64 %v2, i64* %res) {
92 ; CHECK-LABEL: usubo.i64
93 ; CHECK: subs x8, x0, x1
94 ; CHECK-NEXT: csinc w0, wzr, wzr, cs
95 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2)
96 %val = extractvalue {i64, i1} %t, 0
97 %obit = extractvalue {i64, i1} %t, 1
98 store i64 %val, i64* %res
102 define i1 @smulo.i32(i32 %v1, i32 %v2, i32* %res) {
104 ; CHECK-LABEL: smulo.i32
105 ; CHECK: smull x8, w0, w1
106 ; CHECK-NEXT: lsr x9, x8, #32
107 ; CHECK-NEXT: cmp w9, w8, asr #31
108 ; CHECK-NEXT: csinc w0, wzr, wzr, eq
109 %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
110 %val = extractvalue {i32, i1} %t, 0
111 %obit = extractvalue {i32, i1} %t, 1
112 store i32 %val, i32* %res
116 define i1 @smulo.i64(i64 %v1, i64 %v2, i64* %res) {
118 ; CHECK-LABEL: smulo.i64
119 ; CHECK: mul x8, x0, x1
120 ; CHECK-NEXT: smulh x9, x0, x1
121 ; CHECK-NEXT: cmp x9, x8, asr #63
122 ; CHECK-NEXT: csinc w0, wzr, wzr, eq
123 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2)
124 %val = extractvalue {i64, i1} %t, 0
125 %obit = extractvalue {i64, i1} %t, 1
126 store i64 %val, i64* %res
130 define i1 @umulo.i32(i32 %v1, i32 %v2, i32* %res) {
132 ; CHECK-LABEL: umulo.i32
133 ; CHECK: umull x8, w0, w1
134 ; CHECK-NEXT: cmp xzr, x8, lsr #32
135 ; CHECK-NEXT: csinc w0, wzr, wzr, eq
136 %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2)
137 %val = extractvalue {i32, i1} %t, 0
138 %obit = extractvalue {i32, i1} %t, 1
139 store i32 %val, i32* %res
143 define i1 @umulo.i64(i64 %v1, i64 %v2, i64* %res) {
145 ; CHECK-LABEL: umulo.i64
146 ; CHECK: umulh x8, x0, x1
147 ; CHECK-NEXT: cmp xzr, x8
148 ; CHECK-NEXT: csinc w8, wzr, wzr, eq
149 ; CHECK-NEXT: mul x9, x0, x1
150 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2)
151 %val = extractvalue {i64, i1} %t, 0
152 %obit = extractvalue {i64, i1} %t, 1
153 store i64 %val, i64* %res
159 ; Check the use of the overflow bit in combination with a select instruction.
161 define i32 @saddo.select.i32(i32 %v1, i32 %v2) {
163 ; CHECK-LABEL: saddo.select.i32
165 ; CHECK-NEXT: csel w0, w0, w1, vs
166 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
167 %obit = extractvalue {i32, i1} %t, 1
168 %ret = select i1 %obit, i32 %v1, i32 %v2
172 define i64 @saddo.select.i64(i64 %v1, i64 %v2) {
174 ; CHECK-LABEL: saddo.select.i64
176 ; CHECK-NEXT: csel x0, x0, x1, vs
177 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2)
178 %obit = extractvalue {i64, i1} %t, 1
179 %ret = select i1 %obit, i64 %v1, i64 %v2
183 define i32 @uaddo.select.i32(i32 %v1, i32 %v2) {
185 ; CHECK-LABEL: uaddo.select.i32
187 ; CHECK-NEXT: csel w0, w0, w1, cs
188 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2)
189 %obit = extractvalue {i32, i1} %t, 1
190 %ret = select i1 %obit, i32 %v1, i32 %v2
194 define i64 @uaddo.select.i64(i64 %v1, i64 %v2) {
196 ; CHECK-LABEL: uaddo.select.i64
198 ; CHECK-NEXT: csel x0, x0, x1, cs
199 %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2)
200 %obit = extractvalue {i64, i1} %t, 1
201 %ret = select i1 %obit, i64 %v1, i64 %v2
205 define i32 @ssubo.select.i32(i32 %v1, i32 %v2) {
207 ; CHECK-LABEL: ssubo.select.i32
209 ; CHECK-NEXT: csel w0, w0, w1, vs
210 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2)
211 %obit = extractvalue {i32, i1} %t, 1
212 %ret = select i1 %obit, i32 %v1, i32 %v2
216 define i64 @ssubo.select.i64(i64 %v1, i64 %v2) {
218 ; CHECK-LABEL: ssubo.select.i64
220 ; CHECK-NEXT: csel x0, x0, x1, vs
221 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2)
222 %obit = extractvalue {i64, i1} %t, 1
223 %ret = select i1 %obit, i64 %v1, i64 %v2
227 define i32 @usubo.select.i32(i32 %v1, i32 %v2) {
229 ; CHECK-LABEL: usubo.select.i32
231 ; CHECK-NEXT: csel w0, w0, w1, cc
232 %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2)
233 %obit = extractvalue {i32, i1} %t, 1
234 %ret = select i1 %obit, i32 %v1, i32 %v2
238 define i64 @usubo.select.i64(i64 %v1, i64 %v2) {
240 ; CHECK-LABEL: usubo.select.i64
242 ; CHECK-NEXT: csel x0, x0, x1, cc
243 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2)
244 %obit = extractvalue {i64, i1} %t, 1
245 %ret = select i1 %obit, i64 %v1, i64 %v2
249 define i32 @smulo.select.i32(i32 %v1, i32 %v2) {
251 ; CHECK-LABEL: smulo.select.i32
252 ; CHECK: smull x8, w0, w1
253 ; CHECK-NEXT: lsr x9, x8, #32
254 ; CHECK-NEXT: cmp w9, w8, asr #31
255 ; CHECK-NEXT: csel w0, w0, w1, ne
256 %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
257 %obit = extractvalue {i32, i1} %t, 1
258 %ret = select i1 %obit, i32 %v1, i32 %v2
262 define i64 @smulo.select.i64(i64 %v1, i64 %v2) {
264 ; CHECK-LABEL: smulo.select.i64
265 ; CHECK: mul x8, x0, x1
266 ; CHECK-NEXT: smulh x9, x0, x1
267 ; CHECK-NEXT: cmp x9, x8, asr #63
268 ; CHECK-NEXT: csel x0, x0, x1, ne
269 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2)
270 %obit = extractvalue {i64, i1} %t, 1
271 %ret = select i1 %obit, i64 %v1, i64 %v2
275 define i32 @umulo.select.i32(i32 %v1, i32 %v2) {
277 ; CHECK-LABEL: umulo.select.i32
278 ; CHECK: umull x8, w0, w1
279 ; CHECK-NEXT: cmp xzr, x8, lsr #32
280 ; CHECK-NEXT: csel w0, w0, w1, ne
281 %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2)
282 %obit = extractvalue {i32, i1} %t, 1
283 %ret = select i1 %obit, i32 %v1, i32 %v2
287 define i64 @umulo.select.i64(i64 %v1, i64 %v2) {
289 ; CHECK-LABEL: umulo.select.i64
290 ; CHECK: umulh x8, x0, x1
291 ; CHECK-NEXT: cmp xzr, x8
292 ; CHECK-NEXT: csel x0, x0, x1, ne
293 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2)
294 %obit = extractvalue {i64, i1} %t, 1
295 %ret = select i1 %obit, i64 %v1, i64 %v2
301 ; Check the use of the overflow bit in combination with a branch instruction.
303 define i1 @saddo.br.i32(i32 %v1, i32 %v2) {
305 ; CHECK-LABEL: saddo.br.i32
308 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
309 %val = extractvalue {i32, i1} %t, 0
310 %obit = extractvalue {i32, i1} %t, 1
311 br i1 %obit, label %overflow, label %continue
320 define i1 @saddo.br.i64(i64 %v1, i64 %v2) {
322 ; CHECK-LABEL: saddo.br.i64
325 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2)
326 %val = extractvalue {i64, i1} %t, 0
327 %obit = extractvalue {i64, i1} %t, 1
328 br i1 %obit, label %overflow, label %continue
337 define i1 @uaddo.br.i32(i32 %v1, i32 %v2) {
339 ; CHECK-LABEL: uaddo.br.i32
342 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2)
343 %val = extractvalue {i32, i1} %t, 0
344 %obit = extractvalue {i32, i1} %t, 1
345 br i1 %obit, label %overflow, label %continue
354 define i1 @uaddo.br.i64(i64 %v1, i64 %v2) {
356 ; CHECK-LABEL: uaddo.br.i64
359 %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2)
360 %val = extractvalue {i64, i1} %t, 0
361 %obit = extractvalue {i64, i1} %t, 1
362 br i1 %obit, label %overflow, label %continue
371 define i1 @ssubo.br.i32(i32 %v1, i32 %v2) {
373 ; CHECK-LABEL: ssubo.br.i32
376 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2)
377 %val = extractvalue {i32, i1} %t, 0
378 %obit = extractvalue {i32, i1} %t, 1
379 br i1 %obit, label %overflow, label %continue
388 define i1 @ssubo.br.i64(i64 %v1, i64 %v2) {
390 ; CHECK-LABEL: ssubo.br.i64
393 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2)
394 %val = extractvalue {i64, i1} %t, 0
395 %obit = extractvalue {i64, i1} %t, 1
396 br i1 %obit, label %overflow, label %continue
405 define i1 @usubo.br.i32(i32 %v1, i32 %v2) {
407 ; CHECK-LABEL: usubo.br.i32
410 %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2)
411 %val = extractvalue {i32, i1} %t, 0
412 %obit = extractvalue {i32, i1} %t, 1
413 br i1 %obit, label %overflow, label %continue
422 define i1 @usubo.br.i64(i64 %v1, i64 %v2) {
424 ; CHECK-LABEL: usubo.br.i64
427 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2)
428 %val = extractvalue {i64, i1} %t, 0
429 %obit = extractvalue {i64, i1} %t, 1
430 br i1 %obit, label %overflow, label %continue
439 define i1 @smulo.br.i32(i32 %v1, i32 %v2) {
441 ; CHECK-LABEL: smulo.br.i32
442 ; CHECK: smull x8, w0, w1
443 ; CHECK-NEXT: lsr x9, x8, #32
444 ; CHECK-NEXT: cmp w9, w8, asr #31
446 %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
447 %val = extractvalue {i32, i1} %t, 0
448 %obit = extractvalue {i32, i1} %t, 1
449 br i1 %obit, label %overflow, label %continue
458 define i1 @smulo.br.i64(i64 %v1, i64 %v2) {
460 ; CHECK-LABEL: smulo.br.i64
461 ; CHECK: mul x8, x0, x1
462 ; CHECK-NEXT: smulh x9, x0, x1
463 ; CHECK-NEXT: cmp x9, x8, asr #63
465 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2)
466 %val = extractvalue {i64, i1} %t, 0
467 %obit = extractvalue {i64, i1} %t, 1
468 br i1 %obit, label %overflow, label %continue
477 define i1 @umulo.br.i32(i32 %v1, i32 %v2) {
479 ; CHECK-LABEL: umulo.br.i32
480 ; CHECK: umull x8, w0, w1
481 ; CHECK-NEXT: cmp xzr, x8, lsr #32
483 %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2)
484 %val = extractvalue {i32, i1} %t, 0
485 %obit = extractvalue {i32, i1} %t, 1
486 br i1 %obit, label %overflow, label %continue
495 define i1 @umulo.br.i64(i64 %v1, i64 %v2) {
497 ; CHECK-LABEL: umulo.br.i64
498 ; CHECK: umulh x8, x0, x1
500 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2)
501 %val = extractvalue {i64, i1} %t, 0
502 %obit = extractvalue {i64, i1} %t, 1
503 br i1 %obit, label %overflow, label %continue
512 declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
513 declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone
514 declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
515 declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone
516 declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone
517 declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone
518 declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone
519 declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone
520 declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
521 declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone
522 declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
523 declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone