xref: /llvm-project/llvm/test/CodeGen/AArch64/abds.ll (revision 854ded9b24ea41ae10e884294b19bf3f80ca49f6)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=aarch64 | FileCheck %s
3
4;
5; trunc(abs(sub(sext(a),sext(b)))) -> abds(a,b)
6;
7
8define i8 @abd_ext_i8(i8 %a, i8 %b) nounwind {
9; CHECK-LABEL: abd_ext_i8:
10; CHECK:       // %bb.0:
11; CHECK-NEXT:    sxtb w8, w0
12; CHECK-NEXT:    sub w8, w8, w1, sxtb
13; CHECK-NEXT:    cmp w8, #0
14; CHECK-NEXT:    cneg w0, w8, mi
15; CHECK-NEXT:    ret
16  %aext = sext i8 %a to i64
17  %bext = sext i8 %b to i64
18  %sub = sub i64 %aext, %bext
19  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
20  %trunc = trunc i64 %abs to i8
21  ret i8 %trunc
22}
23
24define i8 @abd_ext_i8_i16(i8 %a, i16 %b) nounwind {
25; CHECK-LABEL: abd_ext_i8_i16:
26; CHECK:       // %bb.0:
27; CHECK-NEXT:    sxtb w8, w0
28; CHECK-NEXT:    sub w8, w8, w1, sxth
29; CHECK-NEXT:    cmp w8, #0
30; CHECK-NEXT:    cneg w0, w8, mi
31; CHECK-NEXT:    ret
32  %aext = sext i8 %a to i64
33  %bext = sext i16 %b to i64
34  %sub = sub i64 %aext, %bext
35  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
36  %trunc = trunc i64 %abs to i8
37  ret i8 %trunc
38}
39
40define i8 @abd_ext_i8_undef(i8 %a, i8 %b) nounwind {
41; CHECK-LABEL: abd_ext_i8_undef:
42; CHECK:       // %bb.0:
43; CHECK-NEXT:    sxtb w8, w0
44; CHECK-NEXT:    sub w8, w8, w1, sxtb
45; CHECK-NEXT:    cmp w8, #0
46; CHECK-NEXT:    cneg w0, w8, mi
47; CHECK-NEXT:    ret
48  %aext = sext i8 %a to i64
49  %bext = sext i8 %b to i64
50  %sub = sub i64 %aext, %bext
51  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
52  %trunc = trunc i64 %abs to i8
53  ret i8 %trunc
54}
55
56define i16 @abd_ext_i16(i16 %a, i16 %b) nounwind {
57; CHECK-LABEL: abd_ext_i16:
58; CHECK:       // %bb.0:
59; CHECK-NEXT:    sxth w8, w0
60; CHECK-NEXT:    sub w8, w8, w1, sxth
61; CHECK-NEXT:    cmp w8, #0
62; CHECK-NEXT:    cneg w0, w8, mi
63; CHECK-NEXT:    ret
64  %aext = sext i16 %a to i64
65  %bext = sext i16 %b to i64
66  %sub = sub i64 %aext, %bext
67  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
68  %trunc = trunc i64 %abs to i16
69  ret i16 %trunc
70}
71
72define i16 @abd_ext_i16_i32(i16 %a, i32 %b) nounwind {
73; CHECK-LABEL: abd_ext_i16_i32:
74; CHECK:       // %bb.0:
75; CHECK-NEXT:    sxth w8, w0
76; CHECK-NEXT:    sub w9, w1, w8
77; CHECK-NEXT:    subs w8, w8, w1
78; CHECK-NEXT:    csel w0, w8, w9, gt
79; CHECK-NEXT:    ret
80  %aext = sext i16 %a to i64
81  %bext = sext i32 %b to i64
82  %sub = sub i64 %aext, %bext
83  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
84  %trunc = trunc i64 %abs to i16
85  ret i16 %trunc
86}
87
88define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind {
89; CHECK-LABEL: abd_ext_i16_undef:
90; CHECK:       // %bb.0:
91; CHECK-NEXT:    sxth w8, w0
92; CHECK-NEXT:    sub w8, w8, w1, sxth
93; CHECK-NEXT:    cmp w8, #0
94; CHECK-NEXT:    cneg w0, w8, mi
95; CHECK-NEXT:    ret
96  %aext = sext i16 %a to i64
97  %bext = sext i16 %b to i64
98  %sub = sub i64 %aext, %bext
99  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
100  %trunc = trunc i64 %abs to i16
101  ret i16 %trunc
102}
103
104define i32 @abd_ext_i32(i32 %a, i32 %b) nounwind {
105; CHECK-LABEL: abd_ext_i32:
106; CHECK:       // %bb.0:
107; CHECK-NEXT:    sub w8, w1, w0
108; CHECK-NEXT:    subs w9, w0, w1
109; CHECK-NEXT:    csel w0, w9, w8, gt
110; CHECK-NEXT:    ret
111  %aext = sext i32 %a to i64
112  %bext = sext i32 %b to i64
113  %sub = sub i64 %aext, %bext
114  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
115  %trunc = trunc i64 %abs to i32
116  ret i32 %trunc
117}
118
119define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind {
120; CHECK-LABEL: abd_ext_i32_i16:
121; CHECK:       // %bb.0:
122; CHECK-NEXT:    sxth w8, w1
123; CHECK-NEXT:    sub w9, w8, w0
124; CHECK-NEXT:    subs w8, w0, w8
125; CHECK-NEXT:    csel w0, w8, w9, gt
126; CHECK-NEXT:    ret
127  %aext = sext i32 %a to i64
128  %bext = sext i16 %b to i64
129  %sub = sub i64 %aext, %bext
130  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
131  %trunc = trunc i64 %abs to i32
132  ret i32 %trunc
133}
134
135define i32 @abd_ext_i32_undef(i32 %a, i32 %b) nounwind {
136; CHECK-LABEL: abd_ext_i32_undef:
137; CHECK:       // %bb.0:
138; CHECK-NEXT:    sub w8, w1, w0
139; CHECK-NEXT:    subs w9, w0, w1
140; CHECK-NEXT:    csel w0, w9, w8, gt
141; CHECK-NEXT:    ret
142  %aext = sext i32 %a to i64
143  %bext = sext i32 %b to i64
144  %sub = sub i64 %aext, %bext
145  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
146  %trunc = trunc i64 %abs to i32
147  ret i32 %trunc
148}
149
150define i64 @abd_ext_i64(i64 %a, i64 %b) nounwind {
151; CHECK-LABEL: abd_ext_i64:
152; CHECK:       // %bb.0:
153; CHECK-NEXT:    sub x8, x1, x0
154; CHECK-NEXT:    subs x9, x0, x1
155; CHECK-NEXT:    csel x0, x9, x8, gt
156; CHECK-NEXT:    ret
157  %aext = sext i64 %a to i128
158  %bext = sext i64 %b to i128
159  %sub = sub i128 %aext, %bext
160  %abs = call i128 @llvm.abs.i128(i128 %sub, i1 false)
161  %trunc = trunc i128 %abs to i64
162  ret i64 %trunc
163}
164
165define i64 @abd_ext_i64_undef(i64 %a, i64 %b) nounwind {
166; CHECK-LABEL: abd_ext_i64_undef:
167; CHECK:       // %bb.0:
168; CHECK-NEXT:    sub x8, x1, x0
169; CHECK-NEXT:    subs x9, x0, x1
170; CHECK-NEXT:    csel x0, x9, x8, gt
171; CHECK-NEXT:    ret
172  %aext = sext i64 %a to i128
173  %bext = sext i64 %b to i128
174  %sub = sub i128 %aext, %bext
175  %abs = call i128 @llvm.abs.i128(i128 %sub, i1 true)
176  %trunc = trunc i128 %abs to i64
177  ret i64 %trunc
178}
179
180define i128 @abd_ext_i128(i128 %a, i128 %b) nounwind {
181; CHECK-LABEL: abd_ext_i128:
182; CHECK:       // %bb.0:
183; CHECK-NEXT:    subs x8, x0, x2
184; CHECK-NEXT:    sbc x9, x1, x3
185; CHECK-NEXT:    subs x10, x2, x0
186; CHECK-NEXT:    sbc x11, x3, x1
187; CHECK-NEXT:    sbcs xzr, x3, x1
188; CHECK-NEXT:    csel x0, x8, x10, lt
189; CHECK-NEXT:    csel x1, x9, x11, lt
190; CHECK-NEXT:    ret
191  %aext = sext i128 %a to i256
192  %bext = sext i128 %b to i256
193  %sub = sub i256 %aext, %bext
194  %abs = call i256 @llvm.abs.i256(i256 %sub, i1 false)
195  %trunc = trunc i256 %abs to i128
196  ret i128 %trunc
197}
198
199define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind {
200; CHECK-LABEL: abd_ext_i128_undef:
201; CHECK:       // %bb.0:
202; CHECK-NEXT:    subs x8, x0, x2
203; CHECK-NEXT:    sbc x9, x1, x3
204; CHECK-NEXT:    subs x10, x2, x0
205; CHECK-NEXT:    sbc x11, x3, x1
206; CHECK-NEXT:    sbcs xzr, x3, x1
207; CHECK-NEXT:    csel x0, x8, x10, lt
208; CHECK-NEXT:    csel x1, x9, x11, lt
209; CHECK-NEXT:    ret
210  %aext = sext i128 %a to i256
211  %bext = sext i128 %b to i256
212  %sub = sub i256 %aext, %bext
213  %abs = call i256 @llvm.abs.i256(i256 %sub, i1 true)
214  %trunc = trunc i256 %abs to i128
215  ret i128 %trunc
216}
217
218;
219; sub(smax(a,b),smin(a,b)) -> abds(a,b)
220;
221
222define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind {
223; CHECK-LABEL: abd_minmax_i8:
224; CHECK:       // %bb.0:
225; CHECK-NEXT:    sxtb w8, w0
226; CHECK-NEXT:    sub w8, w8, w1, sxtb
227; CHECK-NEXT:    cmp w8, #0
228; CHECK-NEXT:    cneg w0, w8, mi
229; CHECK-NEXT:    ret
230  %min = call i8 @llvm.smin.i8(i8 %a, i8 %b)
231  %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)
232  %sub = sub i8 %max, %min
233  ret i8 %sub
234}
235
236define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
237; CHECK-LABEL: abd_minmax_i16:
238; CHECK:       // %bb.0:
239; CHECK-NEXT:    sxth w8, w0
240; CHECK-NEXT:    sub w8, w8, w1, sxth
241; CHECK-NEXT:    cmp w8, #0
242; CHECK-NEXT:    cneg w0, w8, mi
243; CHECK-NEXT:    ret
244  %min = call i16 @llvm.smin.i16(i16 %a, i16 %b)
245  %max = call i16 @llvm.smax.i16(i16 %a, i16 %b)
246  %sub = sub i16 %max, %min
247  ret i16 %sub
248}
249
250define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
251; CHECK-LABEL: abd_minmax_i32:
252; CHECK:       // %bb.0:
253; CHECK-NEXT:    sub w8, w1, w0
254; CHECK-NEXT:    subs w9, w0, w1
255; CHECK-NEXT:    csel w0, w9, w8, gt
256; CHECK-NEXT:    ret
257  %min = call i32 @llvm.smin.i32(i32 %a, i32 %b)
258  %max = call i32 @llvm.smax.i32(i32 %a, i32 %b)
259  %sub = sub i32 %max, %min
260  ret i32 %sub
261}
262
263define i64 @abd_minmax_i64(i64 %a, i64 %b) nounwind {
264; CHECK-LABEL: abd_minmax_i64:
265; CHECK:       // %bb.0:
266; CHECK-NEXT:    sub x8, x1, x0
267; CHECK-NEXT:    subs x9, x0, x1
268; CHECK-NEXT:    csel x0, x9, x8, gt
269; CHECK-NEXT:    ret
270  %min = call i64 @llvm.smin.i64(i64 %a, i64 %b)
271  %max = call i64 @llvm.smax.i64(i64 %a, i64 %b)
272  %sub = sub i64 %max, %min
273  ret i64 %sub
274}
275
276define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind {
277; CHECK-LABEL: abd_minmax_i128:
278; CHECK:       // %bb.0:
279; CHECK-NEXT:    subs x8, x0, x2
280; CHECK-NEXT:    sbc x9, x1, x3
281; CHECK-NEXT:    subs x10, x2, x0
282; CHECK-NEXT:    sbc x11, x3, x1
283; CHECK-NEXT:    sbcs xzr, x3, x1
284; CHECK-NEXT:    csel x0, x8, x10, lt
285; CHECK-NEXT:    csel x1, x9, x11, lt
286; CHECK-NEXT:    ret
287  %min = call i128 @llvm.smin.i128(i128 %a, i128 %b)
288  %max = call i128 @llvm.smax.i128(i128 %a, i128 %b)
289  %sub = sub i128 %max, %min
290  ret i128 %sub
291}
292
293;
294; select(icmp(a,b),sub(a,b),sub(b,a)) -> abds(a,b)
295;
296
297define i8 @abd_cmp_i8(i8 %a, i8 %b) nounwind {
298; CHECK-LABEL: abd_cmp_i8:
299; CHECK:       // %bb.0:
300; CHECK-NEXT:    sxtb w8, w0
301; CHECK-NEXT:    sub w8, w8, w1, sxtb
302; CHECK-NEXT:    cmp w8, #0
303; CHECK-NEXT:    cneg w0, w8, mi
304; CHECK-NEXT:    ret
305  %cmp = icmp sgt i8 %a, %b
306  %ab = sub i8 %a, %b
307  %ba = sub i8 %b, %a
308  %sel = select i1 %cmp, i8 %ab, i8 %ba
309  ret i8 %sel
310}
311
312define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
313; CHECK-LABEL: abd_cmp_i16:
314; CHECK:       // %bb.0:
315; CHECK-NEXT:    sxth w8, w0
316; CHECK-NEXT:    sub w8, w8, w1, sxth
317; CHECK-NEXT:    cmp w8, #0
318; CHECK-NEXT:    cneg w0, w8, mi
319; CHECK-NEXT:    ret
320  %cmp = icmp sge i16 %a, %b
321  %ab = sub i16 %a, %b
322  %ba = sub i16 %b, %a
323  %sel = select i1 %cmp, i16 %ab, i16 %ba
324  ret i16 %sel
325}
326
327define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
328; CHECK-LABEL: abd_cmp_i32:
329; CHECK:       // %bb.0:
330; CHECK-NEXT:    sub w8, w1, w0
331; CHECK-NEXT:    subs w9, w0, w1
332; CHECK-NEXT:    csel w0, w9, w8, gt
333; CHECK-NEXT:    ret
334  %cmp = icmp slt i32 %a, %b
335  %ab = sub i32 %a, %b
336  %ba = sub i32 %b, %a
337  %sel = select i1 %cmp, i32 %ba, i32 %ab
338  ret i32 %sel
339}
340
341define i64 @abd_cmp_i64(i64 %a, i64 %b) nounwind {
342; CHECK-LABEL: abd_cmp_i64:
343; CHECK:       // %bb.0:
344; CHECK-NEXT:    sub x8, x1, x0
345; CHECK-NEXT:    subs x9, x0, x1
346; CHECK-NEXT:    csel x0, x9, x8, gt
347; CHECK-NEXT:    ret
348  %cmp = icmp sge i64 %a, %b
349  %ab = sub i64 %a, %b
350  %ba = sub i64 %b, %a
351  %sel = select i1 %cmp, i64 %ab, i64 %ba
352  ret i64 %sel
353}
354
355define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind {
356; CHECK-LABEL: abd_cmp_i128:
357; CHECK:       // %bb.0:
358; CHECK-NEXT:    subs x8, x0, x2
359; CHECK-NEXT:    sbc x9, x1, x3
360; CHECK-NEXT:    subs x10, x2, x0
361; CHECK-NEXT:    sbc x11, x3, x1
362; CHECK-NEXT:    sbcs xzr, x3, x1
363; CHECK-NEXT:    csel x0, x8, x10, lt
364; CHECK-NEXT:    csel x1, x9, x11, lt
365; CHECK-NEXT:    ret
366  %cmp = icmp sge i128 %a, %b
367  %ab = sub i128 %a, %b
368  %ba = sub i128 %b, %a
369  %sel = select i1 %cmp, i128 %ab, i128 %ba
370  ret i128 %sel
371}
372
373;
374; abs(sub_nsw(x, y)) -> abds(a,b)
375;
376
377define i8 @abd_subnsw_i8(i8 %a, i8 %b) nounwind {
378; CHECK-LABEL: abd_subnsw_i8:
379; CHECK:       // %bb.0:
380; CHECK-NEXT:    sub w8, w0, w1
381; CHECK-NEXT:    sxtb w8, w8
382; CHECK-NEXT:    cmp w8, #0
383; CHECK-NEXT:    cneg w0, w8, mi
384; CHECK-NEXT:    ret
385  %sub = sub nsw i8 %a, %b
386  %abs = call i8 @llvm.abs.i8(i8 %sub, i1 false)
387  ret i8 %abs
388}
389
390define i8 @abd_subnsw_i8_undef(i8 %a, i8 %b) nounwind {
391; CHECK-LABEL: abd_subnsw_i8_undef:
392; CHECK:       // %bb.0:
393; CHECK-NEXT:    sub w8, w0, w1
394; CHECK-NEXT:    sxtb w8, w8
395; CHECK-NEXT:    cmp w8, #0
396; CHECK-NEXT:    cneg w0, w8, mi
397; CHECK-NEXT:    ret
398  %sub = sub nsw i8 %a, %b
399  %abs = call i8 @llvm.abs.i8(i8 %sub, i1 true)
400  ret i8 %abs
401}
402
403define i16 @abd_subnsw_i16(i16 %a, i16 %b) nounwind {
404; CHECK-LABEL: abd_subnsw_i16:
405; CHECK:       // %bb.0:
406; CHECK-NEXT:    sub w8, w0, w1
407; CHECK-NEXT:    sxth w8, w8
408; CHECK-NEXT:    cmp w8, #0
409; CHECK-NEXT:    cneg w0, w8, mi
410; CHECK-NEXT:    ret
411  %sub = sub nsw i16 %a, %b
412  %abs = call i16 @llvm.abs.i16(i16 %sub, i1 false)
413  ret i16 %abs
414}
415
416define i16 @abd_subnsw_i16_undef(i16 %a, i16 %b) nounwind {
417; CHECK-LABEL: abd_subnsw_i16_undef:
418; CHECK:       // %bb.0:
419; CHECK-NEXT:    sub w8, w0, w1
420; CHECK-NEXT:    sxth w8, w8
421; CHECK-NEXT:    cmp w8, #0
422; CHECK-NEXT:    cneg w0, w8, mi
423; CHECK-NEXT:    ret
424  %sub = sub nsw i16 %a, %b
425  %abs = call i16 @llvm.abs.i16(i16 %sub, i1 true)
426  ret i16 %abs
427}
428
429define i32 @abd_subnsw_i32(i32 %a, i32 %b) nounwind {
430; CHECK-LABEL: abd_subnsw_i32:
431; CHECK:       // %bb.0:
432; CHECK-NEXT:    subs w8, w0, w1
433; CHECK-NEXT:    cneg w0, w8, mi
434; CHECK-NEXT:    ret
435  %sub = sub nsw i32 %a, %b
436  %abs = call i32 @llvm.abs.i32(i32 %sub, i1 false)
437  ret i32 %abs
438}
439
440define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
441; CHECK-LABEL: abd_subnsw_i32_undef:
442; CHECK:       // %bb.0:
443; CHECK-NEXT:    subs w8, w0, w1
444; CHECK-NEXT:    cneg w0, w8, mi
445; CHECK-NEXT:    ret
446  %sub = sub nsw i32 %a, %b
447  %abs = call i32 @llvm.abs.i32(i32 %sub, i1 true)
448  ret i32 %abs
449}
450
451define i64 @abd_subnsw_i64(i64 %a, i64 %b) nounwind {
452; CHECK-LABEL: abd_subnsw_i64:
453; CHECK:       // %bb.0:
454; CHECK-NEXT:    subs x8, x0, x1
455; CHECK-NEXT:    cneg x0, x8, mi
456; CHECK-NEXT:    ret
457  %sub = sub nsw i64 %a, %b
458  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
459  ret i64 %abs
460}
461
462define i64 @abd_subnsw_i64_undef(i64 %a, i64 %b) nounwind {
463; CHECK-LABEL: abd_subnsw_i64_undef:
464; CHECK:       // %bb.0:
465; CHECK-NEXT:    subs x8, x0, x1
466; CHECK-NEXT:    cneg x0, x8, mi
467; CHECK-NEXT:    ret
468  %sub = sub nsw i64 %a, %b
469  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
470  ret i64 %abs
471}
472
473define i128 @abd_subnsw_i128(i128 %a, i128 %b) nounwind {
474; CHECK-LABEL: abd_subnsw_i128:
475; CHECK:       // %bb.0:
476; CHECK-NEXT:    subs x8, x0, x2
477; CHECK-NEXT:    sbc x9, x1, x3
478; CHECK-NEXT:    asr x10, x9, #63
479; CHECK-NEXT:    eor x8, x8, x10
480; CHECK-NEXT:    eor x9, x9, x10
481; CHECK-NEXT:    subs x0, x8, x10
482; CHECK-NEXT:    sbc x1, x9, x10
483; CHECK-NEXT:    ret
484  %sub = sub nsw i128 %a, %b
485  %abs = call i128 @llvm.abs.i128(i128 %sub, i1 false)
486  ret i128 %abs
487}
488
489define i128 @abd_subnsw_i128_undef(i128 %a, i128 %b) nounwind {
490; CHECK-LABEL: abd_subnsw_i128_undef:
491; CHECK:       // %bb.0:
492; CHECK-NEXT:    subs x8, x0, x2
493; CHECK-NEXT:    sbc x9, x1, x3
494; CHECK-NEXT:    asr x10, x9, #63
495; CHECK-NEXT:    eor x8, x8, x10
496; CHECK-NEXT:    eor x9, x9, x10
497; CHECK-NEXT:    subs x0, x8, x10
498; CHECK-NEXT:    sbc x1, x9, x10
499; CHECK-NEXT:    ret
500  %sub = sub nsw i128 %a, %b
501  %abs = call i128 @llvm.abs.i128(i128 %sub, i1 true)
502  ret i128 %abs
503}
504
505;
506; negative tests
507;
508
509define i32 @abd_sub_i32(i32 %a, i32 %b) nounwind {
510; CHECK-LABEL: abd_sub_i32:
511; CHECK:       // %bb.0:
512; CHECK-NEXT:    subs w8, w0, w1
513; CHECK-NEXT:    cneg w0, w8, mi
514; CHECK-NEXT:    ret
515  %sub = sub i32 %a, %b
516  %abs = call i32 @llvm.abs.i32(i32 %sub, i1 false)
517  ret i32 %abs
518}
519
520define i64 @vector_legalized(i16 %a, i16 %b) {
521; CHECK-LABEL: vector_legalized:
522; CHECK:       // %bb.0:
523; CHECK-NEXT:    movi v0.2d, #0000000000000000
524; CHECK-NEXT:    sxth w8, w0
525; CHECK-NEXT:    sub w8, w8, w1, sxth
526; CHECK-NEXT:    addp d0, v0.2d
527; CHECK-NEXT:    cmp w8, #0
528; CHECK-NEXT:    cneg w8, w8, mi
529; CHECK-NEXT:    fmov x9, d0
530; CHECK-NEXT:    add x0, x9, x8
531; CHECK-NEXT:    ret
532  %ea = sext i16 %a to i32
533  %eb = sext i16 %b to i32
534  %s = sub i32 %ea, %eb
535  %ab = call i32 @llvm.abs.i32(i32 %s, i1 false)
536  %e = zext i32 %ab to i64
537  %red = call i64 @llvm.vector.reduce.add.v32i64(<32 x i64> zeroinitializer)
538  %z = add i64 %red, %e
539  ret i64 %z
540}
541
542;
543; sub(select(icmp(a,b),a,b),select(icmp(a,b),b,a)) -> abds(a,b)
544;
545
546define i8 @abd_select_i8(i8 %a, i8 %b) nounwind {
547; CHECK-LABEL: abd_select_i8:
548; CHECK:       // %bb.0:
549; CHECK-NEXT:    sxtb w8, w0
550; CHECK-NEXT:    sub w8, w8, w1, sxtb
551; CHECK-NEXT:    cmp w8, #0
552; CHECK-NEXT:    cneg w0, w8, mi
553; CHECK-NEXT:    ret
554  %cmp = icmp slt i8 %a, %b
555  %ab = select i1 %cmp, i8 %a, i8 %b
556  %ba = select i1 %cmp, i8 %b, i8 %a
557  %sub = sub i8 %ba, %ab
558  ret i8 %sub
559}
560
561define i16 @abd_select_i16(i16 %a, i16 %b) nounwind {
562; CHECK-LABEL: abd_select_i16:
563; CHECK:       // %bb.0:
564; CHECK-NEXT:    sxth w8, w0
565; CHECK-NEXT:    sub w8, w8, w1, sxth
566; CHECK-NEXT:    cmp w8, #0
567; CHECK-NEXT:    cneg w0, w8, mi
568; CHECK-NEXT:    ret
569  %cmp = icmp sle i16 %a, %b
570  %ab = select i1 %cmp, i16 %a, i16 %b
571  %ba = select i1 %cmp, i16 %b, i16 %a
572  %sub = sub i16 %ba, %ab
573  ret i16 %sub
574}
575
576define i32 @abd_select_i32(i32 %a, i32 %b) nounwind {
577; CHECK-LABEL: abd_select_i32:
578; CHECK:       // %bb.0:
579; CHECK-NEXT:    sub w8, w1, w0
580; CHECK-NEXT:    subs w9, w0, w1
581; CHECK-NEXT:    csel w0, w9, w8, gt
582; CHECK-NEXT:    ret
583  %cmp = icmp sgt i32 %a, %b
584  %ab = select i1 %cmp, i32 %a, i32 %b
585  %ba = select i1 %cmp, i32 %b, i32 %a
586  %sub = sub i32 %ab, %ba
587  ret i32 %sub
588}
589
590define i64 @abd_select_i64(i64 %a, i64 %b) nounwind {
591; CHECK-LABEL: abd_select_i64:
592; CHECK:       // %bb.0:
593; CHECK-NEXT:    sub x8, x1, x0
594; CHECK-NEXT:    subs x9, x0, x1
595; CHECK-NEXT:    csel x0, x9, x8, gt
596; CHECK-NEXT:    ret
597  %cmp = icmp sge i64 %a, %b
598  %ab = select i1 %cmp, i64 %a, i64 %b
599  %ba = select i1 %cmp, i64 %b, i64 %a
600  %sub = sub i64 %ab, %ba
601  ret i64 %sub
602}
603
604define i128 @abd_select_i128(i128 %a, i128 %b) nounwind {
605; CHECK-LABEL: abd_select_i128:
606; CHECK:       // %bb.0:
607; CHECK-NEXT:    subs x8, x0, x2
608; CHECK-NEXT:    sbc x9, x1, x3
609; CHECK-NEXT:    subs x10, x2, x0
610; CHECK-NEXT:    sbc x11, x3, x1
611; CHECK-NEXT:    sbcs xzr, x3, x1
612; CHECK-NEXT:    csel x0, x8, x10, lt
613; CHECK-NEXT:    csel x1, x9, x11, lt
614; CHECK-NEXT:    ret
615  %cmp = icmp slt i128 %a, %b
616  %ab = select i1 %cmp, i128 %a, i128 %b
617  %ba = select i1 %cmp, i128 %b, i128 %a
618  %sub = sub i128 %ba, %ab
619  ret i128 %sub
620}
621
622declare i8 @llvm.abs.i8(i8, i1)
623declare i16 @llvm.abs.i16(i16, i1)
624declare i32 @llvm.abs.i32(i32, i1)
625declare i64 @llvm.abs.i64(i64, i1)
626declare i128 @llvm.abs.i128(i128, i1)
627
628declare i8 @llvm.smax.i8(i8, i8)
629declare i16 @llvm.smax.i16(i16, i16)
630declare i32 @llvm.smax.i32(i32, i32)
631declare i64 @llvm.smax.i64(i64, i64)
632
633declare i8 @llvm.smin.i8(i8, i8)
634declare i16 @llvm.smin.i16(i16, i16)
635declare i32 @llvm.smin.i32(i32, i32)
636declare i64 @llvm.smin.i64(i64, i64)
637