1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s
3
4declare { i256, i1 } @llvm.uadd.with.overflow.i256(i256, i256)
5declare   i256       @llvm.uadd.sat.i256(i256, i256)
6
7declare { i256, i1 } @llvm.usub.with.overflow.i256(i256, i256)
8declare   i256       @llvm.usub.sat.i256(i256, i256)
9
10declare { i256, i1 } @llvm.sadd.with.overflow.i256(i256, i256)
11declare   i256       @llvm.sadd.sat.i256(i256, i256)
12
13declare { i256, i1 } @llvm.ssub.with.overflow.i256(i256, i256)
14declare   i256       @llvm.ssub.sat.i256(i256, i256)
15
16define i256 @u256_add(i256 %x, i256 %y) {
17; CHECK-LABEL: u256_add:
18; CHECK:       // %bb.0:
19; CHECK-NEXT:    adds x0, x0, x4
20; CHECK-NEXT:    adcs x1, x1, x5
21; CHECK-NEXT:    adcs x2, x2, x6
22; CHECK-NEXT:    adcs x3, x3, x7
23; CHECK-NEXT:    ret
24  %1 = add i256 %x, %y
25  ret i256 %1
26}
27
28define { i256, i8 } @u256_checked_add(i256 %x, i256 %y) {
29; CHECK-LABEL: u256_checked_add:
30; CHECK:       // %bb.0:
31; CHECK-NEXT:    adds x0, x0, x4
32; CHECK-NEXT:    adcs x1, x1, x5
33; CHECK-NEXT:    adcs x2, x2, x6
34; CHECK-NEXT:    adcs x3, x3, x7
35; CHECK-NEXT:    cset w8, hs
36; CHECK-NEXT:    eor w4, w8, #0x1
37; CHECK-NEXT:    ret
38  %1 = tail call { i256, i1 } @llvm.uadd.with.overflow.i256(i256 %x, i256 %y)
39  %2 = extractvalue { i256, i1 } %1, 0
40  %3 = extractvalue { i256, i1 } %1, 1
41  %4 = xor i1 %3, true
42  %5 = zext i1 %4 to i8
43  %6 = insertvalue { i256, i8 } undef, i256 %2, 0
44  %7 = insertvalue { i256, i8 } %6, i8 %5, 1
45  ret { i256, i8 } %7
46}
47
48define { i256, i8 } @u256_overflowing_add(i256 %x, i256 %y) {
49; CHECK-LABEL: u256_overflowing_add:
50; CHECK:       // %bb.0:
51; CHECK-NEXT:    adds x0, x0, x4
52; CHECK-NEXT:    adcs x1, x1, x5
53; CHECK-NEXT:    adcs x2, x2, x6
54; CHECK-NEXT:    adcs x3, x3, x7
55; CHECK-NEXT:    cset w4, hs
56; CHECK-NEXT:    ret
57  %1 = tail call { i256, i1 } @llvm.uadd.with.overflow.i256(i256 %x, i256 %y)
58  %2 = extractvalue { i256, i1 } %1, 0
59  %3 = extractvalue { i256, i1 } %1, 1
60  %4 = zext i1 %3 to i8
61  %5 = insertvalue { i256, i8 } undef, i256 %2, 0
62  %6 = insertvalue { i256, i8 } %5, i8 %4, 1
63  ret { i256, i8 } %6
64}
65
66define i256 @u256_saturating_add(i256 %x, i256 %y) {
67; CHECK-LABEL: u256_saturating_add:
68; CHECK:       // %bb.0:
69; CHECK-NEXT:    adds x8, x0, x4
70; CHECK-NEXT:    adcs x9, x1, x5
71; CHECK-NEXT:    adcs x10, x2, x6
72; CHECK-NEXT:    adcs x11, x3, x7
73; CHECK-NEXT:    cset w12, hs
74; CHECK-NEXT:    cmp w12, #0
75; CHECK-NEXT:    csinv x0, x8, xzr, eq
76; CHECK-NEXT:    csinv x1, x9, xzr, eq
77; CHECK-NEXT:    csinv x2, x10, xzr, eq
78; CHECK-NEXT:    csinv x3, x11, xzr, eq
79; CHECK-NEXT:    ret
80  %1 = tail call i256 @llvm.uadd.sat.i256(i256 %x, i256 %y)
81  ret i256 %1
82}
83
84define i256 @u256_sub(i256 %x, i256 %y) {
85; CHECK-LABEL: u256_sub:
86; CHECK:       // %bb.0:
87; CHECK-NEXT:    subs x0, x0, x4
88; CHECK-NEXT:    sbcs x1, x1, x5
89; CHECK-NEXT:    sbcs x2, x2, x6
90; CHECK-NEXT:    sbcs x3, x3, x7
91; CHECK-NEXT:    ret
92  %1 = sub i256 %x, %y
93  ret i256 %1
94}
95
96define { i256, i8 } @u256_checked_sub(i256 %x, i256 %y) {
97; CHECK-LABEL: u256_checked_sub:
98; CHECK:       // %bb.0:
99; CHECK-NEXT:    subs x0, x0, x4
100; CHECK-NEXT:    sbcs x1, x1, x5
101; CHECK-NEXT:    cset w8, lo
102; CHECK-NEXT:    cmp wzr, w8
103; CHECK-NEXT:    sbcs x2, x2, x6
104; CHECK-NEXT:    cset w8, lo
105; CHECK-NEXT:    cmp wzr, w8
106; CHECK-NEXT:    sbcs x3, x3, x7
107; CHECK-NEXT:    cset w8, lo
108; CHECK-NEXT:    eor w4, w8, #0x1
109; CHECK-NEXT:    ret
110  %1 = tail call { i256, i1 } @llvm.usub.with.overflow.i256(i256 %x, i256 %y)
111  %2 = extractvalue { i256, i1 } %1, 0
112  %3 = extractvalue { i256, i1 } %1, 1
113  %4 = xor i1 %3, true
114  %5 = zext i1 %4 to i8
115  %6 = insertvalue { i256, i8 } undef, i256 %2, 0
116  %7 = insertvalue { i256, i8 } %6, i8 %5, 1
117  ret { i256, i8 } %7
118}
119
120define { i256, i8 } @u256_overflowing_sub(i256 %x, i256 %y) {
121; CHECK-LABEL: u256_overflowing_sub:
122; CHECK:       // %bb.0:
123; CHECK-NEXT:    subs x0, x0, x4
124; CHECK-NEXT:    sbcs x1, x1, x5
125; CHECK-NEXT:    cset w8, lo
126; CHECK-NEXT:    cmp wzr, w8
127; CHECK-NEXT:    sbcs x2, x2, x6
128; CHECK-NEXT:    cset w8, lo
129; CHECK-NEXT:    cmp wzr, w8
130; CHECK-NEXT:    sbcs x3, x3, x7
131; CHECK-NEXT:    cset w4, lo
132; CHECK-NEXT:    ret
133  %1 = tail call { i256, i1 } @llvm.usub.with.overflow.i256(i256 %x, i256 %y)
134  %2 = extractvalue { i256, i1 } %1, 0
135  %3 = extractvalue { i256, i1 } %1, 1
136  %4 = zext i1 %3 to i8
137  %5 = insertvalue { i256, i8 } undef, i256 %2, 0
138  %6 = insertvalue { i256, i8 } %5, i8 %4, 1
139  ret { i256, i8 } %6
140}
141
142define i256 @u256_saturating_sub(i256 %x, i256 %y) {
143; CHECK-LABEL: u256_saturating_sub:
144; CHECK:       // %bb.0:
145; CHECK-NEXT:    subs x8, x0, x4
146; CHECK-NEXT:    sbcs x9, x1, x5
147; CHECK-NEXT:    sbcs x10, x2, x6
148; CHECK-NEXT:    sbcs x11, x3, x7
149; CHECK-NEXT:    cset w12, lo
150; CHECK-NEXT:    cmp w12, #0
151; CHECK-NEXT:    csel x0, xzr, x8, ne
152; CHECK-NEXT:    csel x1, xzr, x9, ne
153; CHECK-NEXT:    csel x2, xzr, x10, ne
154; CHECK-NEXT:    csel x3, xzr, x11, ne
155; CHECK-NEXT:    ret
156  %1 = tail call i256 @llvm.usub.sat.i256(i256 %x, i256 %y)
157  ret i256 %1
158}
159
160define i256 @i256_add(i256 %x, i256 %y) {
161; CHECK-LABEL: i256_add:
162; CHECK:       // %bb.0:
163; CHECK-NEXT:    adds x0, x0, x4
164; CHECK-NEXT:    adcs x1, x1, x5
165; CHECK-NEXT:    adcs x2, x2, x6
166; CHECK-NEXT:    adcs x3, x3, x7
167; CHECK-NEXT:    ret
168  %1 = add i256 %x, %y
169  ret i256 %1
170}
171
172define { i256, i8 } @i256_checked_add(i256 %x, i256 %y) {
173; CHECK-LABEL: i256_checked_add:
174; CHECK:       // %bb.0:
175; CHECK-NEXT:    adds x0, x0, x4
176; CHECK-NEXT:    adcs x1, x1, x5
177; CHECK-NEXT:    adcs x2, x2, x6
178; CHECK-NEXT:    adcs x3, x3, x7
179; CHECK-NEXT:    cset w8, vs
180; CHECK-NEXT:    eor w4, w8, #0x1
181; CHECK-NEXT:    ret
182  %1 = tail call { i256, i1 } @llvm.sadd.with.overflow.i256(i256 %x, i256 %y)
183  %2 = extractvalue { i256, i1 } %1, 0
184  %3 = extractvalue { i256, i1 } %1, 1
185  %4 = xor i1 %3, true
186  %5 = zext i1 %4 to i8
187  %6 = insertvalue { i256, i8 } undef, i256 %2, 0
188  %7 = insertvalue { i256, i8 } %6, i8 %5, 1
189  ret { i256, i8 } %7
190}
191
192define { i256, i8 } @i256_overflowing_add(i256 %x, i256 %y) {
193; CHECK-LABEL: i256_overflowing_add:
194; CHECK:       // %bb.0:
195; CHECK-NEXT:    adds x0, x0, x4
196; CHECK-NEXT:    adcs x1, x1, x5
197; CHECK-NEXT:    adcs x2, x2, x6
198; CHECK-NEXT:    adcs x3, x3, x7
199; CHECK-NEXT:    cset w4, vs
200; CHECK-NEXT:    ret
201  %1 = tail call { i256, i1 } @llvm.sadd.with.overflow.i256(i256 %x, i256 %y)
202  %2 = extractvalue { i256, i1 } %1, 0
203  %3 = extractvalue { i256, i1 } %1, 1
204  %4 = zext i1 %3 to i8
205  %5 = insertvalue { i256, i8 } undef, i256 %2, 0
206  %6 = insertvalue { i256, i8 } %5, i8 %4, 1
207  ret { i256, i8 } %6
208}
209
210define i256 @i256_saturating_add(i256 %x, i256 %y) {
211; CHECK-LABEL: i256_saturating_add:
212; CHECK:       // %bb.0:
213; CHECK-NEXT:    adds x8, x0, x4
214; CHECK-NEXT:    adcs x9, x1, x5
215; CHECK-NEXT:    adcs x10, x2, x6
216; CHECK-NEXT:    adcs x11, x3, x7
217; CHECK-NEXT:    cset w12, vs
218; CHECK-NEXT:    asr x13, x11, #63
219; CHECK-NEXT:    cmp w12, #0
220; CHECK-NEXT:    csel x0, x13, x8, ne
221; CHECK-NEXT:    eor x8, x13, #0x8000000000000000
222; CHECK-NEXT:    csel x1, x13, x9, ne
223; CHECK-NEXT:    csel x2, x13, x10, ne
224; CHECK-NEXT:    csel x3, x8, x11, ne
225; CHECK-NEXT:    ret
226  %1 = tail call i256 @llvm.sadd.sat.i256(i256 %x, i256 %y)
227  ret i256 %1
228}
229
230define i256 @i256_sub(i256 %x, i256 %y) {
231; CHECK-LABEL: i256_sub:
232; CHECK:       // %bb.0:
233; CHECK-NEXT:    subs x0, x0, x4
234; CHECK-NEXT:    sbcs x1, x1, x5
235; CHECK-NEXT:    sbcs x2, x2, x6
236; CHECK-NEXT:    sbcs x3, x3, x7
237; CHECK-NEXT:    ret
238  %1 = sub i256 %x, %y
239  ret i256 %1
240}
241
242define { i256, i8 } @i256_checked_sub(i256 %x, i256 %y) {
243; CHECK-LABEL: i256_checked_sub:
244; CHECK:       // %bb.0:
245; CHECK-NEXT:    subs x0, x0, x4
246; CHECK-NEXT:    sbcs x1, x1, x5
247; CHECK-NEXT:    cset w8, lo
248; CHECK-NEXT:    cmp wzr, w8
249; CHECK-NEXT:    sbcs x2, x2, x6
250; CHECK-NEXT:    cset w8, lo
251; CHECK-NEXT:    cmp wzr, w8
252; CHECK-NEXT:    sbcs x3, x3, x7
253; CHECK-NEXT:    cset w8, vs
254; CHECK-NEXT:    eor w4, w8, #0x1
255; CHECK-NEXT:    ret
256  %1 = tail call { i256, i1 } @llvm.ssub.with.overflow.i256(i256 %x, i256 %y)
257  %2 = extractvalue { i256, i1 } %1, 0
258  %3 = extractvalue { i256, i1 } %1, 1
259  %4 = xor i1 %3, true
260  %5 = zext i1 %4 to i8
261  %6 = insertvalue { i256, i8 } undef, i256 %2, 0
262  %7 = insertvalue { i256, i8 } %6, i8 %5, 1
263  ret { i256, i8 } %7
264}
265
266define { i256, i8 } @i256_overflowing_sub(i256 %x, i256 %y) {
267; CHECK-LABEL: i256_overflowing_sub:
268; CHECK:       // %bb.0:
269; CHECK-NEXT:    subs x0, x0, x4
270; CHECK-NEXT:    sbcs x1, x1, x5
271; CHECK-NEXT:    cset w8, lo
272; CHECK-NEXT:    cmp wzr, w8
273; CHECK-NEXT:    sbcs x2, x2, x6
274; CHECK-NEXT:    cset w8, lo
275; CHECK-NEXT:    cmp wzr, w8
276; CHECK-NEXT:    sbcs x3, x3, x7
277; CHECK-NEXT:    cset w4, vs
278; CHECK-NEXT:    ret
279  %1 = tail call { i256, i1 } @llvm.ssub.with.overflow.i256(i256 %x, i256 %y)
280  %2 = extractvalue { i256, i1 } %1, 0
281  %3 = extractvalue { i256, i1 } %1, 1
282  %4 = zext i1 %3 to i8
283  %5 = insertvalue { i256, i8 } undef, i256 %2, 0
284  %6 = insertvalue { i256, i8 } %5, i8 %4, 1
285  ret { i256, i8 } %6
286}
287
288define i256 @i256_saturating_sub(i256 %x, i256 %y) {
289; CHECK-LABEL: i256_saturating_sub:
290; CHECK:       // %bb.0:
291; CHECK-NEXT:    subs x8, x0, x4
292; CHECK-NEXT:    sbcs x9, x1, x5
293; CHECK-NEXT:    sbcs x10, x2, x6
294; CHECK-NEXT:    sbcs x11, x3, x7
295; CHECK-NEXT:    cset w12, vs
296; CHECK-NEXT:    asr x13, x11, #63
297; CHECK-NEXT:    cmp w12, #0
298; CHECK-NEXT:    csel x0, x13, x8, ne
299; CHECK-NEXT:    eor x8, x13, #0x8000000000000000
300; CHECK-NEXT:    csel x1, x13, x9, ne
301; CHECK-NEXT:    csel x2, x13, x10, ne
302; CHECK-NEXT:    csel x3, x8, x11, ne
303; CHECK-NEXT:    ret
304  %1 = tail call i256 @llvm.ssub.sat.i256(i256 %x, i256 %y)
305  ret i256 %1
306}
307