xref: /llvm-project/llvm/test/CodeGen/AArch64/overflow.ll (revision 28064bfad12cfce959d74fa6d099312e19703f26)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=arm64-eabi -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-SD
3; RUN: llc < %s -mtriple=arm64-eabi -global-isel -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-GI
4
5define zeroext i1 @saddo1.i32.unused(i32 %v1, i32 %v2, ptr %res) {
6; CHECK-LABEL: saddo1.i32.unused:
7; CHECK:       // %bb.0: // %entry
8; CHECK-NEXT:    add w8, w0, w1
9; CHECK-NEXT:    mov w0, #1 // =0x1
10; CHECK-NEXT:    str w8, [x2]
11; CHECK-NEXT:    ret
12entry:
13  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
14  %obit = extractvalue {i32, i1} %t, 1
15  %val = extractvalue {i32, i1} %t, 0
16  store i32 %val, ptr %res
17  ret i1 1
18}
19
20define zeroext i1 @saddo1.i32.fold(i32 %v1, i32 %v2, ptr %res) {
21; CHECK-LABEL: saddo1.i32.fold:
22; CHECK:       // %bb.0: // %entry
23; CHECK-NEXT:    mov w8, #20 // =0x14
24; CHECK-NEXT:    mov w0, wzr
25; CHECK-NEXT:    str w8, [x2]
26; CHECK-NEXT:    ret
27entry:
28  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 9, i32 11)
29  %val = extractvalue {i32, i1} %t, 0
30  %obit = extractvalue {i32, i1} %t, 1
31  store i32 %val, ptr %res
32  ret i1 %obit
33}
34
35define zeroext i1 @saddo1.i32.addzero(i32 %v1, i32 %v2, ptr %res) {
36; CHECK-LABEL: saddo1.i32.addzero:
37; CHECK:       // %bb.0: // %entry
38; CHECK-NEXT:    mov w8, w0
39; CHECK-NEXT:    mov w0, wzr
40; CHECK-NEXT:    str w8, [x2]
41; CHECK-NEXT:    ret
42entry:
43  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 0)
44  %val = extractvalue {i32, i1} %t, 0
45  %obit = extractvalue {i32, i1} %t, 1
46  store i32 %val, ptr %res
47  ret i1 %obit
48}
49
50define zeroext i1 @uaddo1.i32.addzero(i32 %v1, i32 %v2, ptr %res) {
51; CHECK-LABEL: uaddo1.i32.addzero:
52; CHECK:       // %bb.0: // %entry
53; CHECK-NEXT:    mov w8, w0
54; CHECK-NEXT:    mov w0, wzr
55; CHECK-NEXT:    str w8, [x2]
56; CHECK-NEXT:    ret
57entry:
58  %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 0)
59  %val = extractvalue {i32, i1} %t, 0
60  %obit = extractvalue {i32, i1} %t, 1
61  store i32 %val, ptr %res
62  ret i1 %obit
63}
64
65define i32 @saddo.select.i64(i32 %v1, i32 %v2, i1 %v3, i64 %v4, i64 %v5) {
66; CHECK-LABEL: saddo.select.i64:
67; CHECK:       // %bb.0: // %entry
68; CHECK-NEXT:    mov w0, w1
69; CHECK-NEXT:    ret
70entry:
71  %lhs = and i64 %v4, 12
72  %rhs = and i64 %v5, 13
73  %t = call {i64, i1} @llvm.sadd.with.overflow.64(i64 %lhs, i64 %rhs)
74  %obit = extractvalue {i64, i1} %t, 1
75  %ret = select i1 %obit, i32 %v1, i32 %v2
76  ret i32 %ret
77}
78
79define i32 @uaddo.select.i64(i32 %v1, i32 %v2, i1 %v3, i64 %v4, i64 %v5) {
80; CHECK-LABEL: uaddo.select.i64:
81; CHECK:       // %bb.0: // %entry
82; CHECK-NEXT:    mov w0, w1
83; CHECK-NEXT:    ret
84entry:
85  %lhs = and i64 %v4, 9
86  %rhs = and i64 %v5, 10
87  %t = call {i64, i1} @llvm.uadd.with.overflow.64(i64 %lhs, i64 %rhs)
88  %obit = extractvalue {i64, i1} %t, 1
89  %ret = select i1 %obit, i32 %v1, i32 %v2
90  ret i32 %ret
91}
92
93define zeroext i1 @saddo.canon.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
94; CHECK-LABEL: saddo.canon.i32:
95; CHECK:       // %bb.0: // %entry
96; CHECK-NEXT:    mov w0, wzr
97; CHECK-NEXT:    str w4, [x5]
98; CHECK-NEXT:    ret
99entry:
100  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 0, i32 %v5)
101  %val = extractvalue {i32, i1} %t, 0
102  %obit = extractvalue {i32, i1} %t, 1
103  store i32 %val, ptr %res
104  ret i1 %obit
105}
106define zeroext i1 @saddo.add.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
107; CHECK-SD-LABEL: saddo.add.i32:
108; CHECK-SD:       // %bb.0: // %entry
109; CHECK-SD-NEXT:    add w8, w4, #100
110; CHECK-SD-NEXT:    subs w8, w8, #100
111; CHECK-SD-NEXT:    cset w0, vs
112; CHECK-SD-NEXT:    str w8, [x5]
113; CHECK-SD-NEXT:    ret
114;
115; CHECK-GI-LABEL: saddo.add.i32:
116; CHECK-GI:       // %bb.0: // %entry
117; CHECK-GI-NEXT:    mov w0, wzr
118; CHECK-GI-NEXT:    str w4, [x5]
119; CHECK-GI-NEXT:    ret
120entry:
121  %lhs = add nsw i32 %v5, 100
122  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %lhs, i32 -100)
123  %val = extractvalue {i32, i1} %t, 0
124  %obit = extractvalue {i32, i1} %t, 1
125  store i32 %val, ptr %res
126  ret i1 %obit
127}
128
129define zeroext i1 @uaddo.add.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
130; CHECK-SD-LABEL: uaddo.add.i32:
131; CHECK-SD:       // %bb.0: // %entry
132; CHECK-SD-NEXT:    add w8, w4, #5
133; CHECK-SD-NEXT:    adds w8, w8, #5
134; CHECK-SD-NEXT:    cset w0, hs
135; CHECK-SD-NEXT:    str w8, [x5]
136; CHECK-SD-NEXT:    ret
137;
138; CHECK-GI-LABEL: uaddo.add.i32:
139; CHECK-GI:       // %bb.0: // %entry
140; CHECK-GI-NEXT:    adds w8, w4, #10
141; CHECK-GI-NEXT:    cset w0, hs
142; CHECK-GI-NEXT:    str w8, [x5]
143; CHECK-GI-NEXT:    ret
144entry:
145  %lhs = add nuw i32 %v5, 5
146  %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %lhs, i32 5)
147  %val = extractvalue {i32, i1} %t, 0
148  %obit = extractvalue {i32, i1} %t, 1
149  store i32 %val, ptr %res
150  ret i1 %obit
151}
152
153define zeroext i1 @uaddo.negative.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
154; CHECK-LABEL: uaddo.negative.i32:
155; CHECK:       // %bb.0: // %entry
156; CHECK-NEXT:    adds w8, w3, #5
157; CHECK-NEXT:    cset w0, hs
158; CHECK-NEXT:    str w8, [x5]
159; CHECK-NEXT:    ret
160entry:
161  %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v4, i32 5)
162  %val = extractvalue {i32, i1} %t, 0
163  %obit = extractvalue {i32, i1} %t, 1
164  store i32 %val, ptr %res
165  ret i1 %obit
166}
167
168define i32 @saddo.always.i8(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
169; CHECK-LABEL: saddo.always.i8:
170; CHECK:       // %bb.0: // %entry
171; CHECK-NEXT:    mov w0, w1
172; CHECK-NEXT:    ret
173entry:
174  %t = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 255, i8 254)
175  %obit = extractvalue {i8, i1} %t, 1
176  %ret = select i1 %obit, i32 %v1, i32 %v2
177  ret i32 %ret
178}
179
180define i32 @uaddo.never.i8(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) {
181; CHECK-LABEL: uaddo.never.i8:
182; CHECK:       // %bb.0: // %entry
183; CHECK-NEXT:    mov w0, w1
184; CHECK-NEXT:    ret
185entry:
186  %t = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 2, i8 1)
187  %obit = extractvalue {i8, i1} %t, 1
188  %ret = select i1 %obit, i32 %v1, i32 %v2
189  ret i32 %ret
190}
191
192
193declare {i8, i1} @llvm.sadd.with.overflow.i8(i8, i8) nounwind readnone
194declare {i16, i1} @llvm.sadd.with.overflow.i16(i16, i16) nounwind readnone
195declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
196declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone
197declare {i8, i1} @llvm.uadd.with.overflow.i8(i8, i8) nounwind readnone
198declare {i16, i1} @llvm.uadd.with.overflow.i16(i16, i16) nounwind readnone
199declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
200declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone
201declare {i8, i1} @llvm.ssub.with.overflow.i8(i8, i8) nounwind readnone
202declare {i16, i1} @llvm.ssub.with.overflow.i16(i16, i16) nounwind readnone
203declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone
204declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone
205declare {i8, i1} @llvm.usub.with.overflow.i8(i8, i8) nounwind readnone
206declare {i16, i1} @llvm.usub.with.overflow.i16(i16, i16) nounwind readnone
207declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone
208declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone
209declare {i8, i1} @llvm.smul.with.overflow.i8(i8, i8) nounwind readnone
210declare {i16, i1} @llvm.smul.with.overflow.i16(i16, i16) nounwind readnone
211declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
212declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone
213declare {i8, i1} @llvm.umul.with.overflow.i8(i8, i8) nounwind readnone
214declare {i16, i1} @llvm.umul.with.overflow.i16(i16, i16) nounwind readnone
215declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
216declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone
217