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