xref: /llvm-project/llvm/test/CodeGen/AArch64/abdu-neg.ll (revision 7afdc6bd57d634354597df185fd7037bec9241ff)
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(nabs(sub(zext(a),zext(b)))) -> nabds(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:    and w8, w0, #0xff
12; CHECK-NEXT:    sub w8, w8, w1, uxtb
13; CHECK-NEXT:    cmp w8, #0
14; CHECK-NEXT:    cneg w0, w8, pl
15; CHECK-NEXT:    ret
16  %aext = zext i8 %a to i64
17  %bext = zext i8 %b to i64
18  %sub = sub i64 %aext, %bext
19  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
20  %nabs = sub i64 0, %abs
21  %trunc = trunc i64 %nabs to i8
22  ret i8 %trunc
23}
24
25define i8 @abd_ext_i8_i16(i8 %a, i16 %b) nounwind {
26; CHECK-LABEL: abd_ext_i8_i16:
27; CHECK:       // %bb.0:
28; CHECK-NEXT:    and w8, w0, #0xff
29; CHECK-NEXT:    sub w8, w8, w1, uxth
30; CHECK-NEXT:    cmp w8, #0
31; CHECK-NEXT:    cneg w0, w8, pl
32; CHECK-NEXT:    ret
33  %aext = zext i8 %a to i64
34  %bext = zext i16 %b to i64
35  %sub = sub i64 %aext, %bext
36  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
37  %nabs = sub i64 0, %abs
38  %trunc = trunc i64 %nabs to i8
39  ret i8 %trunc
40}
41
42define i8 @abd_ext_i8_undef(i8 %a, i8 %b) nounwind {
43; CHECK-LABEL: abd_ext_i8_undef:
44; CHECK:       // %bb.0:
45; CHECK-NEXT:    and w8, w0, #0xff
46; CHECK-NEXT:    sub w8, w8, w1, uxtb
47; CHECK-NEXT:    cmp w8, #0
48; CHECK-NEXT:    cneg w0, w8, pl
49; CHECK-NEXT:    ret
50  %aext = zext i8 %a to i64
51  %bext = zext i8 %b to i64
52  %sub = sub i64 %aext, %bext
53  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
54  %nabs = sub i64 0, %abs
55  %trunc = trunc i64 %nabs to i8
56  ret i8 %trunc
57}
58
59define i16 @abd_ext_i16(i16 %a, i16 %b) nounwind {
60; CHECK-LABEL: abd_ext_i16:
61; CHECK:       // %bb.0:
62; CHECK-NEXT:    and w8, w0, #0xffff
63; CHECK-NEXT:    sub w8, w8, w1, uxth
64; CHECK-NEXT:    cmp w8, #0
65; CHECK-NEXT:    cneg w0, w8, pl
66; CHECK-NEXT:    ret
67  %aext = zext i16 %a to i64
68  %bext = zext i16 %b to i64
69  %sub = sub i64 %aext, %bext
70  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
71  %nabs = sub i64 0, %abs
72  %trunc = trunc i64 %nabs to i16
73  ret i16 %trunc
74}
75
76define i16 @abd_ext_i16_i32(i16 %a, i32 %b) nounwind {
77; CHECK-LABEL: abd_ext_i16_i32:
78; CHECK:       // %bb.0:
79; CHECK-NEXT:    and w8, w0, #0xffff
80; CHECK-NEXT:    sub w9, w1, w8
81; CHECK-NEXT:    subs w8, w8, w1
82; CHECK-NEXT:    csel w8, w8, w9, hi
83; CHECK-NEXT:    neg w0, w8
84; CHECK-NEXT:    ret
85  %aext = zext i16 %a to i64
86  %bext = zext i32 %b to i64
87  %sub = sub i64 %aext, %bext
88  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
89  %nabs = sub i64 0, %abs
90  %trunc = trunc i64 %nabs to i16
91  ret i16 %trunc
92}
93
94define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind {
95; CHECK-LABEL: abd_ext_i16_undef:
96; CHECK:       // %bb.0:
97; CHECK-NEXT:    and w8, w0, #0xffff
98; CHECK-NEXT:    sub w8, w8, w1, uxth
99; CHECK-NEXT:    cmp w8, #0
100; CHECK-NEXT:    cneg w0, w8, pl
101; CHECK-NEXT:    ret
102  %aext = zext i16 %a to i64
103  %bext = zext i16 %b to i64
104  %sub = sub i64 %aext, %bext
105  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
106  %nabs = sub i64 0, %abs
107  %trunc = trunc i64 %nabs to i16
108  ret i16 %trunc
109}
110
111define i32 @abd_ext_i32(i32 %a, i32 %b) nounwind {
112; CHECK-LABEL: abd_ext_i32:
113; CHECK:       // %bb.0:
114; CHECK-NEXT:    sub w8, w1, w0
115; CHECK-NEXT:    subs w9, w0, w1
116; CHECK-NEXT:    csel w8, w9, w8, hi
117; CHECK-NEXT:    neg w0, w8
118; CHECK-NEXT:    ret
119  %aext = zext i32 %a to i64
120  %bext = zext i32 %b to i64
121  %sub = sub i64 %aext, %bext
122  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
123  %nabs = sub i64 0, %abs
124  %trunc = trunc i64 %nabs to i32
125  ret i32 %trunc
126}
127
128define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind {
129; CHECK-LABEL: abd_ext_i32_i16:
130; CHECK:       // %bb.0:
131; CHECK-NEXT:    and w8, w1, #0xffff
132; CHECK-NEXT:    sub w9, w8, w0
133; CHECK-NEXT:    subs w8, w0, w8
134; CHECK-NEXT:    csel w8, w8, w9, hi
135; CHECK-NEXT:    neg w0, w8
136; CHECK-NEXT:    ret
137  %aext = zext i32 %a to i64
138  %bext = zext i16 %b to i64
139  %sub = sub i64 %aext, %bext
140  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
141  %nabs = sub i64 0, %abs
142  %trunc = trunc i64 %nabs to i32
143  ret i32 %trunc
144}
145
146define i32 @abd_ext_i32_undef(i32 %a, i32 %b) nounwind {
147; CHECK-LABEL: abd_ext_i32_undef:
148; CHECK:       // %bb.0:
149; CHECK-NEXT:    sub w8, w1, w0
150; CHECK-NEXT:    subs w9, w0, w1
151; CHECK-NEXT:    csel w8, w9, w8, hi
152; CHECK-NEXT:    neg w0, w8
153; CHECK-NEXT:    ret
154  %aext = zext i32 %a to i64
155  %bext = zext i32 %b to i64
156  %sub = sub i64 %aext, %bext
157  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
158  %nabs = sub i64 0, %abs
159  %trunc = trunc i64 %nabs to i32
160  ret i32 %trunc
161}
162
163define i64 @abd_ext_i64(i64 %a, i64 %b) nounwind {
164; CHECK-LABEL: abd_ext_i64:
165; CHECK:       // %bb.0:
166; CHECK-NEXT:    sub x8, x1, x0
167; CHECK-NEXT:    subs x9, x0, x1
168; CHECK-NEXT:    csel x8, x9, x8, hi
169; CHECK-NEXT:    neg x0, x8
170; CHECK-NEXT:    ret
171  %aext = zext i64 %a to i128
172  %bext = zext i64 %b to i128
173  %sub = sub i128 %aext, %bext
174  %abs = call i128 @llvm.abs.i128(i128 %sub, i1 false)
175  %nabs = sub i128 0, %abs
176  %trunc = trunc i128 %nabs to i64
177  ret i64 %trunc
178}
179
180define i64 @abd_ext_i64_undef(i64 %a, i64 %b) nounwind {
181; CHECK-LABEL: abd_ext_i64_undef:
182; CHECK:       // %bb.0:
183; CHECK-NEXT:    sub x8, x1, x0
184; CHECK-NEXT:    subs x9, x0, x1
185; CHECK-NEXT:    csel x8, x9, x8, hi
186; CHECK-NEXT:    neg x0, x8
187; CHECK-NEXT:    ret
188  %aext = zext i64 %a to i128
189  %bext = zext i64 %b to i128
190  %sub = sub i128 %aext, %bext
191  %abs = call i128 @llvm.abs.i128(i128 %sub, i1 true)
192  %nabs = sub i128 0, %abs
193  %trunc = trunc i128 %nabs to i64
194  ret i64 %trunc
195}
196
197define i128 @abd_ext_i128(i128 %a, i128 %b) nounwind {
198; CHECK-LABEL: abd_ext_i128:
199; CHECK:       // %bb.0:
200; CHECK-NEXT:    subs x8, x0, x2
201; CHECK-NEXT:    sbcs x9, x1, x3
202; CHECK-NEXT:    cset w10, lo
203; CHECK-NEXT:    sbfx x10, x10, #0, #1
204; CHECK-NEXT:    eor x8, x8, x10
205; CHECK-NEXT:    eor x9, x9, x10
206; CHECK-NEXT:    subs x8, x8, x10
207; CHECK-NEXT:    sbc x9, x9, x10
208; CHECK-NEXT:    negs x0, x8
209; CHECK-NEXT:    ngc x1, x9
210; CHECK-NEXT:    ret
211  %aext = zext i128 %a to i256
212  %bext = zext i128 %b to i256
213  %sub = sub i256 %aext, %bext
214  %abs = call i256 @llvm.abs.i256(i256 %sub, i1 false)
215  %nabs = sub i256 0, %abs
216  %trunc = trunc i256 %nabs to i128
217  ret i128 %trunc
218}
219
220define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind {
221; CHECK-LABEL: abd_ext_i128_undef:
222; CHECK:       // %bb.0:
223; CHECK-NEXT:    subs x8, x0, x2
224; CHECK-NEXT:    sbcs x9, x1, x3
225; CHECK-NEXT:    cset w10, lo
226; CHECK-NEXT:    sbfx x10, x10, #0, #1
227; CHECK-NEXT:    eor x8, x8, x10
228; CHECK-NEXT:    eor x9, x9, x10
229; CHECK-NEXT:    subs x8, x8, x10
230; CHECK-NEXT:    sbc x9, x9, x10
231; CHECK-NEXT:    negs x0, x8
232; CHECK-NEXT:    ngc x1, x9
233; CHECK-NEXT:    ret
234  %aext = zext i128 %a to i256
235  %bext = zext i128 %b to i256
236  %sub = sub i256 %aext, %bext
237  %abs = call i256 @llvm.abs.i256(i256 %sub, i1 true)
238  %nabs = sub i256 0, %abs
239  %trunc = trunc i256 %nabs to i128
240  ret i128 %trunc
241}
242
243;
244; sub(umin(a,b),umax(a,b)) -> nabds(a,b)
245;
246
247define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind {
248; CHECK-LABEL: abd_minmax_i8:
249; CHECK:       // %bb.0:
250; CHECK-NEXT:    and w8, w1, #0xff
251; CHECK-NEXT:    and w9, w0, #0xff
252; CHECK-NEXT:    cmp w9, w8
253; CHECK-NEXT:    csel w10, w9, w8, lo
254; CHECK-NEXT:    csel w8, w9, w8, hi
255; CHECK-NEXT:    sub w0, w10, w8
256; CHECK-NEXT:    ret
257  %min = call i8 @llvm.umin.i8(i8 %a, i8 %b)
258  %max = call i8 @llvm.umax.i8(i8 %a, i8 %b)
259  %sub = sub i8 %min, %max
260  ret i8 %sub
261}
262
263define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
264; CHECK-LABEL: abd_minmax_i16:
265; CHECK:       // %bb.0:
266; CHECK-NEXT:    and w8, w1, #0xffff
267; CHECK-NEXT:    and w9, w0, #0xffff
268; CHECK-NEXT:    cmp w9, w8
269; CHECK-NEXT:    csel w10, w9, w8, lo
270; CHECK-NEXT:    csel w8, w9, w8, hi
271; CHECK-NEXT:    sub w0, w10, w8
272; CHECK-NEXT:    ret
273  %min = call i16 @llvm.umin.i16(i16 %a, i16 %b)
274  %max = call i16 @llvm.umax.i16(i16 %a, i16 %b)
275  %sub = sub i16 %min, %max
276  ret i16 %sub
277}
278
279define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
280; CHECK-LABEL: abd_minmax_i32:
281; CHECK:       // %bb.0:
282; CHECK-NEXT:    cmp w0, w1
283; CHECK-NEXT:    csel w8, w0, w1, lo
284; CHECK-NEXT:    csel w9, w0, w1, hi
285; CHECK-NEXT:    sub w0, w8, w9
286; CHECK-NEXT:    ret
287  %min = call i32 @llvm.umin.i32(i32 %a, i32 %b)
288  %max = call i32 @llvm.umax.i32(i32 %a, i32 %b)
289  %sub = sub i32 %min, %max
290  ret i32 %sub
291}
292
293define i64 @abd_minmax_i64(i64 %a, i64 %b) nounwind {
294; CHECK-LABEL: abd_minmax_i64:
295; CHECK:       // %bb.0:
296; CHECK-NEXT:    cmp x0, x1
297; CHECK-NEXT:    csel x8, x0, x1, lo
298; CHECK-NEXT:    csel x9, x0, x1, hi
299; CHECK-NEXT:    sub x0, x8, x9
300; CHECK-NEXT:    ret
301  %min = call i64 @llvm.umin.i64(i64 %a, i64 %b)
302  %max = call i64 @llvm.umax.i64(i64 %a, i64 %b)
303  %sub = sub i64 %min, %max
304  ret i64 %sub
305}
306
307define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind {
308; CHECK-LABEL: abd_minmax_i128:
309; CHECK:       // %bb.0:
310; CHECK-NEXT:    cmp x0, x2
311; CHECK-NEXT:    sbcs xzr, x1, x3
312; CHECK-NEXT:    csel x8, x1, x3, lo
313; CHECK-NEXT:    csel x9, x0, x2, lo
314; CHECK-NEXT:    cmp x2, x0
315; CHECK-NEXT:    sbcs xzr, x3, x1
316; CHECK-NEXT:    csel x10, x0, x2, lo
317; CHECK-NEXT:    csel x11, x1, x3, lo
318; CHECK-NEXT:    subs x0, x9, x10
319; CHECK-NEXT:    sbc x1, x8, x11
320; CHECK-NEXT:    ret
321  %min = call i128 @llvm.umin.i128(i128 %a, i128 %b)
322  %max = call i128 @llvm.umax.i128(i128 %a, i128 %b)
323  %sub = sub i128 %min, %max
324  ret i128 %sub
325}
326
327;
328; select(icmp(a,b),sub(a,b),sub(b,a)) -> nabds(a,b)
329;
330
331define i8 @abd_cmp_i8(i8 %a, i8 %b) nounwind {
332; CHECK-LABEL: abd_cmp_i8:
333; CHECK:       // %bb.0:
334; CHECK-NEXT:    and w8, w0, #0xff
335; CHECK-NEXT:    sub w9, w0, w1
336; CHECK-NEXT:    sub w10, w1, w0
337; CHECK-NEXT:    cmp w8, w1, uxtb
338; CHECK-NEXT:    csel w0, w9, w10, ls
339; CHECK-NEXT:    ret
340  %cmp = icmp ule i8 %a, %b
341  %ab = sub i8 %a, %b
342  %ba = sub i8 %b, %a
343  %sel = select i1 %cmp, i8 %ab, i8 %ba
344  ret i8 %sel
345}
346
347define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
348; CHECK-LABEL: abd_cmp_i16:
349; CHECK:       // %bb.0:
350; CHECK-NEXT:    and w8, w0, #0xffff
351; CHECK-NEXT:    sub w9, w0, w1
352; CHECK-NEXT:    sub w10, w1, w0
353; CHECK-NEXT:    cmp w8, w1, uxth
354; CHECK-NEXT:    csel w0, w9, w10, lo
355; CHECK-NEXT:    ret
356  %cmp = icmp ult i16 %a, %b
357  %ab = sub i16 %a, %b
358  %ba = sub i16 %b, %a
359  %sel = select i1 %cmp, i16 %ab, i16 %ba
360  ret i16 %sel
361}
362
363define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
364; CHECK-LABEL: abd_cmp_i32:
365; CHECK:       // %bb.0:
366; CHECK-NEXT:    sub w8, w1, w0
367; CHECK-NEXT:    subs w9, w0, w1
368; CHECK-NEXT:    csel w0, w8, w9, hs
369; CHECK-NEXT:    ret
370  %cmp = icmp uge i32 %a, %b
371  %ab = sub i32 %a, %b
372  %ba = sub i32 %b, %a
373  %sel = select i1 %cmp, i32 %ba, i32 %ab
374  ret i32 %sel
375}
376
377define i64 @abd_cmp_i64(i64 %a, i64 %b) nounwind {
378; CHECK-LABEL: abd_cmp_i64:
379; CHECK:       // %bb.0:
380; CHECK-NEXT:    sub x8, x1, x0
381; CHECK-NEXT:    subs x9, x0, x1
382; CHECK-NEXT:    csel x0, x9, x8, lo
383; CHECK-NEXT:    ret
384  %cmp = icmp ult i64 %a, %b
385  %ab = sub i64 %a, %b
386  %ba = sub i64 %b, %a
387  %sel = select i1 %cmp, i64 %ab, i64 %ba
388  ret i64 %sel
389}
390
391define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind {
392; CHECK-LABEL: abd_cmp_i128:
393; CHECK:       // %bb.0:
394; CHECK-NEXT:    cmp x0, x2
395; CHECK-NEXT:    sbc x8, x1, x3
396; CHECK-NEXT:    subs x9, x2, x0
397; CHECK-NEXT:    sbc x10, x3, x1
398; CHECK-NEXT:    subs x11, x0, x2
399; CHECK-NEXT:    sbcs xzr, x1, x3
400; CHECK-NEXT:    csel x0, x11, x9, lo
401; CHECK-NEXT:    csel x1, x8, x10, lo
402; CHECK-NEXT:    ret
403  %cmp = icmp ult i128 %a, %b
404  %ab = sub i128 %a, %b
405  %ba = sub i128 %b, %a
406  %sel = select i1 %cmp, i128 %ab, i128 %ba
407  ret i128 %sel
408}
409
410declare i8 @llvm.abs.i8(i8, i1)
411declare i16 @llvm.abs.i16(i16, i1)
412declare i32 @llvm.abs.i32(i32, i1)
413declare i64 @llvm.abs.i64(i64, i1)
414declare i128 @llvm.abs.i128(i128, i1)
415
416declare i8 @llvm.umax.i8(i8, i8)
417declare i16 @llvm.umax.i16(i16, i16)
418declare i32 @llvm.umax.i32(i32, i32)
419declare i64 @llvm.umax.i64(i64, i64)
420
421declare i8 @llvm.umin.i8(i8, i8)
422declare i16 @llvm.umin.i16(i16, i16)
423declare i32 @llvm.umin.i32(i32, i32)
424declare i64 @llvm.umin.i64(i64, i64)
425