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:    adc 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:    sbc 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:    sbcs x2, x2, x6
102; CHECK-NEXT:    sbcs x3, x3, x7
103; CHECK-NEXT:    cset w8, lo
104; CHECK-NEXT:    eor w4, w8, #0x1
105; CHECK-NEXT:    ret
106  %1 = tail call { i256, i1 } @llvm.usub.with.overflow.i256(i256 %x, i256 %y)
107  %2 = extractvalue { i256, i1 } %1, 0
108  %3 = extractvalue { i256, i1 } %1, 1
109  %4 = xor i1 %3, true
110  %5 = zext i1 %4 to i8
111  %6 = insertvalue { i256, i8 } undef, i256 %2, 0
112  %7 = insertvalue { i256, i8 } %6, i8 %5, 1
113  ret { i256, i8 } %7
114}
115
116define { i256, i8 } @u256_overflowing_sub(i256 %x, i256 %y) {
117; CHECK-LABEL: u256_overflowing_sub:
118; CHECK:       // %bb.0:
119; CHECK-NEXT:    subs x0, x0, x4
120; CHECK-NEXT:    sbcs x1, x1, x5
121; CHECK-NEXT:    sbcs x2, x2, x6
122; CHECK-NEXT:    sbcs x3, x3, x7
123; CHECK-NEXT:    cset w4, lo
124; CHECK-NEXT:    ret
125  %1 = tail call { i256, i1 } @llvm.usub.with.overflow.i256(i256 %x, i256 %y)
126  %2 = extractvalue { i256, i1 } %1, 0
127  %3 = extractvalue { i256, i1 } %1, 1
128  %4 = zext i1 %3 to i8
129  %5 = insertvalue { i256, i8 } undef, i256 %2, 0
130  %6 = insertvalue { i256, i8 } %5, i8 %4, 1
131  ret { i256, i8 } %6
132}
133
134define i256 @u256_saturating_sub(i256 %x, i256 %y) {
135; CHECK-LABEL: u256_saturating_sub:
136; CHECK:       // %bb.0:
137; CHECK-NEXT:    subs x8, x0, x4
138; CHECK-NEXT:    sbcs x9, x1, x5
139; CHECK-NEXT:    sbcs x10, x2, x6
140; CHECK-NEXT:    sbcs x11, x3, x7
141; CHECK-NEXT:    cset w12, lo
142; CHECK-NEXT:    cmp w12, #0
143; CHECK-NEXT:    csel x0, xzr, x8, ne
144; CHECK-NEXT:    csel x1, xzr, x9, ne
145; CHECK-NEXT:    csel x2, xzr, x10, ne
146; CHECK-NEXT:    csel x3, xzr, x11, ne
147; CHECK-NEXT:    ret
148  %1 = tail call i256 @llvm.usub.sat.i256(i256 %x, i256 %y)
149  ret i256 %1
150}
151
152define i256 @i256_add(i256 %x, i256 %y) {
153; CHECK-LABEL: i256_add:
154; CHECK:       // %bb.0:
155; CHECK-NEXT:    adds x0, x0, x4
156; CHECK-NEXT:    adcs x1, x1, x5
157; CHECK-NEXT:    adcs x2, x2, x6
158; CHECK-NEXT:    adc x3, x3, x7
159; CHECK-NEXT:    ret
160  %1 = add i256 %x, %y
161  ret i256 %1
162}
163
164define { i256, i8 } @i256_checked_add(i256 %x, i256 %y) {
165; CHECK-LABEL: i256_checked_add:
166; CHECK:       // %bb.0:
167; CHECK-NEXT:    adds x0, x0, x4
168; CHECK-NEXT:    adcs x1, x1, x5
169; CHECK-NEXT:    adcs x2, x2, x6
170; CHECK-NEXT:    adcs x3, x3, x7
171; CHECK-NEXT:    cset w8, vs
172; CHECK-NEXT:    eor w4, w8, #0x1
173; CHECK-NEXT:    ret
174  %1 = tail call { i256, i1 } @llvm.sadd.with.overflow.i256(i256 %x, i256 %y)
175  %2 = extractvalue { i256, i1 } %1, 0
176  %3 = extractvalue { i256, i1 } %1, 1
177  %4 = xor i1 %3, true
178  %5 = zext i1 %4 to i8
179  %6 = insertvalue { i256, i8 } undef, i256 %2, 0
180  %7 = insertvalue { i256, i8 } %6, i8 %5, 1
181  ret { i256, i8 } %7
182}
183
184define { i256, i8 } @i256_overflowing_add(i256 %x, i256 %y) {
185; CHECK-LABEL: i256_overflowing_add:
186; CHECK:       // %bb.0:
187; CHECK-NEXT:    adds x0, x0, x4
188; CHECK-NEXT:    adcs x1, x1, x5
189; CHECK-NEXT:    adcs x2, x2, x6
190; CHECK-NEXT:    adcs x3, x3, x7
191; CHECK-NEXT:    cset w4, vs
192; CHECK-NEXT:    ret
193  %1 = tail call { i256, i1 } @llvm.sadd.with.overflow.i256(i256 %x, i256 %y)
194  %2 = extractvalue { i256, i1 } %1, 0
195  %3 = extractvalue { i256, i1 } %1, 1
196  %4 = zext i1 %3 to i8
197  %5 = insertvalue { i256, i8 } undef, i256 %2, 0
198  %6 = insertvalue { i256, i8 } %5, i8 %4, 1
199  ret { i256, i8 } %6
200}
201
202define i256 @i256_saturating_add(i256 %x, i256 %y) {
203; CHECK-LABEL: i256_saturating_add:
204; CHECK:       // %bb.0:
205; CHECK-NEXT:    adds x8, x0, x4
206; CHECK-NEXT:    adcs x9, x1, x5
207; CHECK-NEXT:    adcs x10, x2, x6
208; CHECK-NEXT:    adcs x11, x3, x7
209; CHECK-NEXT:    cset w12, vs
210; CHECK-NEXT:    asr x13, x11, #63
211; CHECK-NEXT:    cmp w12, #0
212; CHECK-NEXT:    csel x0, x13, x8, ne
213; CHECK-NEXT:    eor x8, x13, #0x8000000000000000
214; CHECK-NEXT:    csel x1, x13, x9, ne
215; CHECK-NEXT:    csel x2, x13, x10, ne
216; CHECK-NEXT:    csel x3, x8, x11, ne
217; CHECK-NEXT:    ret
218  %1 = tail call i256 @llvm.sadd.sat.i256(i256 %x, i256 %y)
219  ret i256 %1
220}
221
222define i256 @i256_sub(i256 %x, i256 %y) {
223; CHECK-LABEL: i256_sub:
224; CHECK:       // %bb.0:
225; CHECK-NEXT:    subs x0, x0, x4
226; CHECK-NEXT:    sbcs x1, x1, x5
227; CHECK-NEXT:    sbcs x2, x2, x6
228; CHECK-NEXT:    sbc x3, x3, x7
229; CHECK-NEXT:    ret
230  %1 = sub i256 %x, %y
231  ret i256 %1
232}
233
234define { i256, i8 } @i256_checked_sub(i256 %x, i256 %y) {
235; CHECK-LABEL: i256_checked_sub:
236; CHECK:       // %bb.0:
237; CHECK-NEXT:    subs x0, x0, x4
238; CHECK-NEXT:    sbcs x1, x1, x5
239; CHECK-NEXT:    sbcs x2, x2, x6
240; CHECK-NEXT:    sbcs x3, x3, x7
241; CHECK-NEXT:    cset w8, vs
242; CHECK-NEXT:    eor w4, w8, #0x1
243; CHECK-NEXT:    ret
244  %1 = tail call { i256, i1 } @llvm.ssub.with.overflow.i256(i256 %x, i256 %y)
245  %2 = extractvalue { i256, i1 } %1, 0
246  %3 = extractvalue { i256, i1 } %1, 1
247  %4 = xor i1 %3, true
248  %5 = zext i1 %4 to i8
249  %6 = insertvalue { i256, i8 } undef, i256 %2, 0
250  %7 = insertvalue { i256, i8 } %6, i8 %5, 1
251  ret { i256, i8 } %7
252}
253
254define { i256, i8 } @i256_overflowing_sub(i256 %x, i256 %y) {
255; CHECK-LABEL: i256_overflowing_sub:
256; CHECK:       // %bb.0:
257; CHECK-NEXT:    subs x0, x0, x4
258; CHECK-NEXT:    sbcs x1, x1, x5
259; CHECK-NEXT:    sbcs x2, x2, x6
260; CHECK-NEXT:    sbcs x3, x3, x7
261; CHECK-NEXT:    cset w4, vs
262; CHECK-NEXT:    ret
263  %1 = tail call { i256, i1 } @llvm.ssub.with.overflow.i256(i256 %x, i256 %y)
264  %2 = extractvalue { i256, i1 } %1, 0
265  %3 = extractvalue { i256, i1 } %1, 1
266  %4 = zext i1 %3 to i8
267  %5 = insertvalue { i256, i8 } undef, i256 %2, 0
268  %6 = insertvalue { i256, i8 } %5, i8 %4, 1
269  ret { i256, i8 } %6
270}
271
272define i256 @i256_saturating_sub(i256 %x, i256 %y) {
273; CHECK-LABEL: i256_saturating_sub:
274; CHECK:       // %bb.0:
275; CHECK-NEXT:    subs x8, x0, x4
276; CHECK-NEXT:    sbcs x9, x1, x5
277; CHECK-NEXT:    sbcs x10, x2, x6
278; CHECK-NEXT:    sbcs x11, x3, x7
279; CHECK-NEXT:    cset w12, vs
280; CHECK-NEXT:    asr x13, x11, #63
281; CHECK-NEXT:    cmp w12, #0
282; CHECK-NEXT:    csel x0, x13, x8, ne
283; CHECK-NEXT:    eor x8, x13, #0x8000000000000000
284; CHECK-NEXT:    csel x1, x13, x9, ne
285; CHECK-NEXT:    csel x2, x13, x10, ne
286; CHECK-NEXT:    csel x3, x8, x11, ne
287; CHECK-NEXT:    ret
288  %1 = tail call i256 @llvm.ssub.sat.i256(i256 %x, i256 %y)
289  ret i256 %1
290}
291