• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc < %s -march=arm64 -aarch64-atomic-cfg-tidy=0 | FileCheck %s
2
3;
4; Get the actual value of the overflow bit.
5;
6define i1 @saddo.i32(i32 %v1, i32 %v2, i32* %res) {
7entry:
8; CHECK-LABEL:  saddo.i32
9; CHECK:        adds w8, w0, w1
10; CHECK-NEXT:   cset w0, vs
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
15  ret i1 %obit
16}
17
18define i1 @saddo.i64(i64 %v1, i64 %v2, i64* %res) {
19entry:
20; CHECK-LABEL:  saddo.i64
21; CHECK:        adds x8, x0, x1
22; CHECK-NEXT:   cset w0, vs
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
27  ret i1 %obit
28}
29
30define i1 @uaddo.i32(i32 %v1, i32 %v2, i32* %res) {
31entry:
32; CHECK-LABEL:  uaddo.i32
33; CHECK:        adds w8, w0, w1
34; CHECK-NEXT:   cset w0, hs
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
39  ret i1 %obit
40}
41
42define i1 @uaddo.i64(i64 %v1, i64 %v2, i64* %res) {
43entry:
44; CHECK-LABEL:  uaddo.i64
45; CHECK:        adds x8, x0, x1
46; CHECK-NEXT:   cset w0, hs
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
51  ret i1 %obit
52}
53
54define i1 @ssubo.i32(i32 %v1, i32 %v2, i32* %res) {
55entry:
56; CHECK-LABEL:  ssubo.i32
57; CHECK:        subs w8, w0, w1
58; CHECK-NEXT:   cset w0, vs
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
63  ret i1 %obit
64}
65
66define i1 @ssubo.i64(i64 %v1, i64 %v2, i64* %res) {
67entry:
68; CHECK-LABEL:  ssubo.i64
69; CHECK:        subs x8, x0, x1
70; CHECK-NEXT:   cset w0, vs
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
75  ret i1 %obit
76}
77
78define i1 @usubo.i32(i32 %v1, i32 %v2, i32* %res) {
79entry:
80; CHECK-LABEL:  usubo.i32
81; CHECK:        subs w8, w0, w1
82; CHECK-NEXT:   cset w0, lo
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
87  ret i1 %obit
88}
89
90define i1 @usubo.i64(i64 %v1, i64 %v2, i64* %res) {
91entry:
92; CHECK-LABEL:  usubo.i64
93; CHECK:        subs x8, x0, x1
94; CHECK-NEXT:   cset w0, lo
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
99  ret i1 %obit
100}
101
102define i1 @smulo.i32(i32 %v1, i32 %v2, i32* %res) {
103entry:
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:   cset w0, ne
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
113  ret i1 %obit
114}
115
116define i1 @smulo.i64(i64 %v1, i64 %v2, i64* %res) {
117entry:
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:   cset w0, ne
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
127  ret i1 %obit
128}
129
130define i1 @umulo.i32(i32 %v1, i32 %v2, i32* %res) {
131entry:
132; CHECK-LABEL:  umulo.i32
133; CHECK:        umull x8, w0, w1
134; CHECK-NEXT:   cmp xzr, x8, lsr #32
135; CHECK-NEXT:   cset w0, ne
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
140  ret i1 %obit
141}
142
143define i1 @umulo.i64(i64 %v1, i64 %v2, i64* %res) {
144entry:
145; CHECK-LABEL:  umulo.i64
146; CHECK:        umulh x8, x0, x1
147; CHECK-NEXT:   cmp xzr, x8
148; CHECK-NEXT:   cset w8, ne
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
154  ret i1 %obit
155}
156
157
158;
159; Check the use of the overflow bit in combination with a select instruction.
160;
161define i32 @saddo.select.i32(i32 %v1, i32 %v2) {
162entry:
163; CHECK-LABEL:  saddo.select.i32
164; CHECK:        cmn w0, w1
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
169  ret i32 %ret
170}
171
172define i64 @saddo.select.i64(i64 %v1, i64 %v2) {
173entry:
174; CHECK-LABEL:  saddo.select.i64
175; CHECK:        cmn x0, x1
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
180  ret i64 %ret
181}
182
183define i32 @uaddo.select.i32(i32 %v1, i32 %v2) {
184entry:
185; CHECK-LABEL:  uaddo.select.i32
186; CHECK:        cmn w0, w1
187; CHECK-NEXT:   csel w0, w0, w1, hs
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
191  ret i32 %ret
192}
193
194define i64 @uaddo.select.i64(i64 %v1, i64 %v2) {
195entry:
196; CHECK-LABEL:  uaddo.select.i64
197; CHECK:        cmn x0, x1
198; CHECK-NEXT:   csel x0, x0, x1, hs
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
202  ret i64 %ret
203}
204
205define i32 @ssubo.select.i32(i32 %v1, i32 %v2) {
206entry:
207; CHECK-LABEL:  ssubo.select.i32
208; CHECK:        cmp w0, w1
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
213  ret i32 %ret
214}
215
216define i64 @ssubo.select.i64(i64 %v1, i64 %v2) {
217entry:
218; CHECK-LABEL:  ssubo.select.i64
219; CHECK:        cmp x0, x1
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
224  ret i64 %ret
225}
226
227define i32 @usubo.select.i32(i32 %v1, i32 %v2) {
228entry:
229; CHECK-LABEL:  usubo.select.i32
230; CHECK:        cmp w0, w1
231; CHECK-NEXT:   csel w0, w0, w1, lo
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
235  ret i32 %ret
236}
237
238define i64 @usubo.select.i64(i64 %v1, i64 %v2) {
239entry:
240; CHECK-LABEL:  usubo.select.i64
241; CHECK:        cmp x0, x1
242; CHECK-NEXT:   csel x0, x0, x1, lo
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
246  ret i64 %ret
247}
248
249define i32 @smulo.select.i32(i32 %v1, i32 %v2) {
250entry:
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
259  ret i32 %ret
260}
261
262define i64 @smulo.select.i64(i64 %v1, i64 %v2) {
263entry:
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
272  ret i64 %ret
273}
274
275define i32 @umulo.select.i32(i32 %v1, i32 %v2) {
276entry:
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
284  ret i32 %ret
285}
286
287define i64 @umulo.select.i64(i64 %v1, i64 %v2) {
288entry:
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
296  ret i64 %ret
297}
298
299
300;
301; Check the use of the overflow bit in combination with a branch instruction.
302;
303define i1 @saddo.br.i32(i32 %v1, i32 %v2) {
304entry:
305; CHECK-LABEL:  saddo.br.i32
306; CHECK:        cmn w0, w1
307; CHECK-NEXT:   b.vc
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
312
313overflow:
314  ret i1 false
315
316continue:
317  ret i1 true
318}
319
320define i1 @saddo.br.i64(i64 %v1, i64 %v2) {
321entry:
322; CHECK-LABEL:  saddo.br.i64
323; CHECK:        cmn x0, x1
324; CHECK-NEXT:   b.vc
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
329
330overflow:
331  ret i1 false
332
333continue:
334  ret i1 true
335}
336
337define i1 @uaddo.br.i32(i32 %v1, i32 %v2) {
338entry:
339; CHECK-LABEL:  uaddo.br.i32
340; CHECK:        cmn w0, w1
341; CHECK-NEXT:   b.lo
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
346
347overflow:
348  ret i1 false
349
350continue:
351  ret i1 true
352}
353
354define i1 @uaddo.br.i64(i64 %v1, i64 %v2) {
355entry:
356; CHECK-LABEL:  uaddo.br.i64
357; CHECK:        cmn x0, x1
358; CHECK-NEXT:   b.lo
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
363
364overflow:
365  ret i1 false
366
367continue:
368  ret i1 true
369}
370
371define i1 @ssubo.br.i32(i32 %v1, i32 %v2) {
372entry:
373; CHECK-LABEL:  ssubo.br.i32
374; CHECK:        cmp w0, w1
375; CHECK-NEXT:   b.vc
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
380
381overflow:
382  ret i1 false
383
384continue:
385  ret i1 true
386}
387
388define i1 @ssubo.br.i64(i64 %v1, i64 %v2) {
389entry:
390; CHECK-LABEL:  ssubo.br.i64
391; CHECK:        cmp x0, x1
392; CHECK-NEXT:   b.vc
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
397
398overflow:
399  ret i1 false
400
401continue:
402  ret i1 true
403}
404
405define i1 @usubo.br.i32(i32 %v1, i32 %v2) {
406entry:
407; CHECK-LABEL:  usubo.br.i32
408; CHECK:        cmp w0, w1
409; CHECK-NEXT:   b.hs
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
414
415overflow:
416  ret i1 false
417
418continue:
419  ret i1 true
420}
421
422define i1 @usubo.br.i64(i64 %v1, i64 %v2) {
423entry:
424; CHECK-LABEL:  usubo.br.i64
425; CHECK:        cmp x0, x1
426; CHECK-NEXT:   b.hs
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
431
432overflow:
433  ret i1 false
434
435continue:
436  ret i1 true
437}
438
439define i1 @smulo.br.i32(i32 %v1, i32 %v2) {
440entry:
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
445; CHECK-NEXT:   b.eq
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
450
451overflow:
452  ret i1 false
453
454continue:
455  ret i1 true
456}
457
458define i1 @smulo.br.i64(i64 %v1, i64 %v2) {
459entry:
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
464; CHECK-NEXT:   b.eq
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
469
470overflow:
471  ret i1 false
472
473continue:
474  ret i1 true
475}
476
477define i1 @umulo.br.i32(i32 %v1, i32 %v2) {
478entry:
479; CHECK-LABEL:  umulo.br.i32
480; CHECK:        umull    x8, w0, w1
481; CHECK-NEXT:   cmp     xzr, x8, lsr #32
482; CHECK-NEXT:   b.eq
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
487
488overflow:
489  ret i1 false
490
491continue:
492  ret i1 true
493}
494
495define i1 @umulo.br.i64(i64 %v1, i64 %v2) {
496entry:
497; CHECK-LABEL:  umulo.br.i64
498; CHECK:        umulh   x8, x0, x1
499; CHECK-NEXT:   cbz
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
504
505overflow:
506  ret i1 false
507
508continue:
509  ret i1 true
510}
511
512declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
513declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone
514declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
515declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone
516declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone
517declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone
518declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone
519declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone
520declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
521declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone
522declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
523declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone
524
525