1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64 | FileCheck %s
5 ; trunc(nabs(sub(sext(a),sext(b)))) -> nabds(a,b)
8 define i8 @abd_ext_i8(i8 %a, i8 %b) nounwind {
9 ; CHECK-LABEL: abd_ext_i8:
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, pl
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 %nabs = sub i64 0, %abs
21 %trunc = trunc i64 %nabs to i8
25 define i8 @abd_ext_i8_i16(i8 %a, i16 %b) nounwind {
26 ; CHECK-LABEL: abd_ext_i8_i16:
28 ; CHECK-NEXT: sxtb w8, w0
29 ; CHECK-NEXT: sub w8, w8, w1, sxth
30 ; CHECK-NEXT: cmp w8, #0
31 ; CHECK-NEXT: cneg w0, w8, pl
33 %aext = sext i8 %a to i64
34 %bext = sext 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
42 define i8 @abd_ext_i8_undef(i8 %a, i8 %b) nounwind {
43 ; CHECK-LABEL: abd_ext_i8_undef:
45 ; CHECK-NEXT: sxtb w8, w0
46 ; CHECK-NEXT: sub w8, w8, w1, sxtb
47 ; CHECK-NEXT: cmp w8, #0
48 ; CHECK-NEXT: cneg w0, w8, pl
50 %aext = sext i8 %a to i64
51 %bext = sext 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
59 define i16 @abd_ext_i16(i16 %a, i16 %b) nounwind {
60 ; CHECK-LABEL: abd_ext_i16:
62 ; CHECK-NEXT: sxth w8, w0
63 ; CHECK-NEXT: sub w8, w8, w1, sxth
64 ; CHECK-NEXT: cmp w8, #0
65 ; CHECK-NEXT: cneg w0, w8, pl
67 %aext = sext i16 %a to i64
68 %bext = sext 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
76 define i16 @abd_ext_i16_i32(i16 %a, i32 %b) nounwind {
77 ; CHECK-LABEL: abd_ext_i16_i32:
79 ; CHECK-NEXT: sxth w8, w0
80 ; CHECK-NEXT: sub w9, w1, w8
81 ; CHECK-NEXT: subs w8, w8, w1
82 ; CHECK-NEXT: csel w8, w8, w9, gt
83 ; CHECK-NEXT: neg w0, w8
85 %aext = sext i16 %a to i64
86 %bext = sext 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
94 define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind {
95 ; CHECK-LABEL: abd_ext_i16_undef:
97 ; CHECK-NEXT: sxth w8, w0
98 ; CHECK-NEXT: sub w8, w8, w1, sxth
99 ; CHECK-NEXT: cmp w8, #0
100 ; CHECK-NEXT: cneg w0, w8, pl
102 %aext = sext i16 %a to i64
103 %bext = sext 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
111 define i32 @abd_ext_i32(i32 %a, i32 %b) nounwind {
112 ; CHECK-LABEL: abd_ext_i32:
114 ; CHECK-NEXT: sub w8, w1, w0
115 ; CHECK-NEXT: subs w9, w0, w1
116 ; CHECK-NEXT: csel w8, w9, w8, gt
117 ; CHECK-NEXT: neg w0, w8
119 %aext = sext i32 %a to i64
120 %bext = sext 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
128 define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind {
129 ; CHECK-LABEL: abd_ext_i32_i16:
131 ; CHECK-NEXT: sxth w8, w1
132 ; CHECK-NEXT: sub w9, w8, w0
133 ; CHECK-NEXT: subs w8, w0, w8
134 ; CHECK-NEXT: csel w8, w8, w9, gt
135 ; CHECK-NEXT: neg w0, w8
137 %aext = sext i32 %a to i64
138 %bext = sext 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
146 define i32 @abd_ext_i32_undef(i32 %a, i32 %b) nounwind {
147 ; CHECK-LABEL: abd_ext_i32_undef:
149 ; CHECK-NEXT: sub w8, w1, w0
150 ; CHECK-NEXT: subs w9, w0, w1
151 ; CHECK-NEXT: csel w8, w9, w8, gt
152 ; CHECK-NEXT: neg w0, w8
154 %aext = sext i32 %a to i64
155 %bext = sext 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
163 define i64 @abd_ext_i64(i64 %a, i64 %b) nounwind {
164 ; CHECK-LABEL: abd_ext_i64:
166 ; CHECK-NEXT: sub x8, x1, x0
167 ; CHECK-NEXT: subs x9, x0, x1
168 ; CHECK-NEXT: csel x8, x9, x8, gt
169 ; CHECK-NEXT: neg x0, x8
171 %aext = sext i64 %a to i128
172 %bext = sext 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
180 define i64 @abd_ext_i64_undef(i64 %a, i64 %b) nounwind {
181 ; CHECK-LABEL: abd_ext_i64_undef:
183 ; CHECK-NEXT: sub x8, x1, x0
184 ; CHECK-NEXT: subs x9, x0, x1
185 ; CHECK-NEXT: csel x8, x9, x8, gt
186 ; CHECK-NEXT: neg x0, x8
188 %aext = sext i64 %a to i128
189 %bext = sext 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
197 define i128 @abd_ext_i128(i128 %a, i128 %b) nounwind {
198 ; CHECK-LABEL: abd_ext_i128:
200 ; CHECK-NEXT: subs x8, x0, x2
201 ; CHECK-NEXT: sbc x9, x1, x3
202 ; CHECK-NEXT: subs x10, x2, x0
203 ; CHECK-NEXT: sbc x11, x3, x1
204 ; CHECK-NEXT: sbcs xzr, x3, x1
205 ; CHECK-NEXT: csel x8, x8, x10, lt
206 ; CHECK-NEXT: csel x9, x9, x11, lt
207 ; CHECK-NEXT: negs x0, x8
208 ; CHECK-NEXT: ngc x1, x9
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 false)
214 %nabs = sub i256 0, %abs
215 %trunc = trunc i256 %nabs to i128
219 define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind {
220 ; CHECK-LABEL: abd_ext_i128_undef:
222 ; CHECK-NEXT: subs x8, x0, x2
223 ; CHECK-NEXT: sbc x9, x1, x3
224 ; CHECK-NEXT: subs x10, x2, x0
225 ; CHECK-NEXT: sbc x11, x3, x1
226 ; CHECK-NEXT: sbcs xzr, x3, x1
227 ; CHECK-NEXT: csel x8, x8, x10, lt
228 ; CHECK-NEXT: csel x9, x9, x11, lt
229 ; CHECK-NEXT: negs x0, x8
230 ; CHECK-NEXT: ngc x1, x9
232 %aext = sext i128 %a to i256
233 %bext = sext i128 %b to i256
234 %sub = sub i256 %aext, %bext
235 %abs = call i256 @llvm.abs.i256(i256 %sub, i1 true)
236 %nabs = sub i256 0, %abs
237 %trunc = trunc i256 %nabs to i128
242 ; sub(smin(a,b),smax(a,b)) -> nabds(a,b)
245 define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind {
246 ; CHECK-LABEL: abd_minmax_i8:
248 ; CHECK-NEXT: sxtb w8, w1
249 ; CHECK-NEXT: sxtb w9, w0
250 ; CHECK-NEXT: cmp w9, w8
251 ; CHECK-NEXT: csel w10, w9, w8, lt
252 ; CHECK-NEXT: csel w8, w9, w8, gt
253 ; CHECK-NEXT: sub w0, w10, w8
255 %min = call i8 @llvm.smin.i8(i8 %a, i8 %b)
256 %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)
257 %sub = sub i8 %min, %max
261 define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
262 ; CHECK-LABEL: abd_minmax_i16:
264 ; CHECK-NEXT: sxth w8, w1
265 ; CHECK-NEXT: sxth w9, w0
266 ; CHECK-NEXT: cmp w9, w8
267 ; CHECK-NEXT: csel w10, w9, w8, lt
268 ; CHECK-NEXT: csel w8, w9, w8, gt
269 ; CHECK-NEXT: sub w0, w10, w8
271 %min = call i16 @llvm.smin.i16(i16 %a, i16 %b)
272 %max = call i16 @llvm.smax.i16(i16 %a, i16 %b)
273 %sub = sub i16 %min, %max
277 define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
278 ; CHECK-LABEL: abd_minmax_i32:
280 ; CHECK-NEXT: cmp w0, w1
281 ; CHECK-NEXT: csel w8, w0, w1, lt
282 ; CHECK-NEXT: csel w9, w0, w1, gt
283 ; CHECK-NEXT: sub w0, w8, w9
285 %min = call i32 @llvm.smin.i32(i32 %a, i32 %b)
286 %max = call i32 @llvm.smax.i32(i32 %a, i32 %b)
287 %sub = sub i32 %min, %max
291 define i64 @abd_minmax_i64(i64 %a, i64 %b) nounwind {
292 ; CHECK-LABEL: abd_minmax_i64:
294 ; CHECK-NEXT: cmp x0, x1
295 ; CHECK-NEXT: csel x8, x0, x1, lt
296 ; CHECK-NEXT: csel x9, x0, x1, gt
297 ; CHECK-NEXT: sub x0, x8, x9
299 %min = call i64 @llvm.smin.i64(i64 %a, i64 %b)
300 %max = call i64 @llvm.smax.i64(i64 %a, i64 %b)
301 %sub = sub i64 %min, %max
305 define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind {
306 ; CHECK-LABEL: abd_minmax_i128:
308 ; CHECK-NEXT: cmp x0, x2
309 ; CHECK-NEXT: sbcs xzr, x1, x3
310 ; CHECK-NEXT: csel x8, x1, x3, lt
311 ; CHECK-NEXT: csel x9, x0, x2, lt
312 ; CHECK-NEXT: cmp x2, x0
313 ; CHECK-NEXT: sbcs xzr, x3, x1
314 ; CHECK-NEXT: csel x10, x0, x2, lt
315 ; CHECK-NEXT: csel x11, x1, x3, lt
316 ; CHECK-NEXT: subs x0, x9, x10
317 ; CHECK-NEXT: sbc x1, x8, x11
319 %min = call i128 @llvm.smin.i128(i128 %a, i128 %b)
320 %max = call i128 @llvm.smax.i128(i128 %a, i128 %b)
321 %sub = sub i128 %min, %max
326 ; select(icmp(a,b),sub(a,b),sub(b,a)) -> nabds(a,b)
329 define i8 @abd_cmp_i8(i8 %a, i8 %b) nounwind {
330 ; CHECK-LABEL: abd_cmp_i8:
332 ; CHECK-NEXT: sxtb w8, w0
333 ; CHECK-NEXT: sub w9, w0, w1
334 ; CHECK-NEXT: sub w10, w1, w0
335 ; CHECK-NEXT: cmp w8, w1, sxtb
336 ; CHECK-NEXT: csel w0, w9, w10, le
338 %cmp = icmp sle i8 %a, %b
341 %sel = select i1 %cmp, i8 %ab, i8 %ba
345 define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
346 ; CHECK-LABEL: abd_cmp_i16:
348 ; CHECK-NEXT: sxth w8, w0
349 ; CHECK-NEXT: sub w9, w0, w1
350 ; CHECK-NEXT: sub w10, w1, w0
351 ; CHECK-NEXT: cmp w8, w1, sxth
352 ; CHECK-NEXT: csel w0, w9, w10, lt
354 %cmp = icmp slt i16 %a, %b
357 %sel = select i1 %cmp, i16 %ab, i16 %ba
361 define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
362 ; CHECK-LABEL: abd_cmp_i32:
364 ; CHECK-NEXT: sub w8, w1, w0
365 ; CHECK-NEXT: subs w9, w0, w1
366 ; CHECK-NEXT: csel w0, w8, w9, ge
368 %cmp = icmp sge i32 %a, %b
371 %sel = select i1 %cmp, i32 %ba, i32 %ab
375 define i64 @abd_cmp_i64(i64 %a, i64 %b) nounwind {
376 ; CHECK-LABEL: abd_cmp_i64:
378 ; CHECK-NEXT: sub x8, x1, x0
379 ; CHECK-NEXT: subs x9, x0, x1
380 ; CHECK-NEXT: csel x0, x9, x8, lt
382 %cmp = icmp slt i64 %a, %b
385 %sel = select i1 %cmp, i64 %ab, i64 %ba
389 define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind {
390 ; CHECK-LABEL: abd_cmp_i128:
392 ; CHECK-NEXT: cmp x0, x2
393 ; CHECK-NEXT: sbc x8, x1, x3
394 ; CHECK-NEXT: subs x9, x2, x0
395 ; CHECK-NEXT: sbc x10, x3, x1
396 ; CHECK-NEXT: subs x11, x0, x2
397 ; CHECK-NEXT: sbcs xzr, x1, x3
398 ; CHECK-NEXT: csel x0, x11, x9, lt
399 ; CHECK-NEXT: csel x1, x8, x10, lt
401 %cmp = icmp slt i128 %a, %b
402 %ab = sub i128 %a, %b
403 %ba = sub i128 %b, %a
404 %sel = select i1 %cmp, i128 %ab, i128 %ba
409 ; nabs(sub_nsw(x, y)) -> nabds(a,b)
412 define i8 @abd_subnsw_i8(i8 %a, i8 %b) nounwind {
413 ; CHECK-LABEL: abd_subnsw_i8:
415 ; CHECK-NEXT: sub w8, w0, w1
416 ; CHECK-NEXT: sbfx w9, w8, #7, #1
417 ; CHECK-NEXT: eor w8, w8, w9
418 ; CHECK-NEXT: sub w0, w9, w8
420 %sub = sub nsw i8 %a, %b
421 %abs = call i8 @llvm.abs.i8(i8 %sub, i1 false)
422 %nabs = sub i8 0, %abs
426 define i8 @abd_subnsw_i8_undef(i8 %a, i8 %b) nounwind {
427 ; CHECK-LABEL: abd_subnsw_i8_undef:
429 ; CHECK-NEXT: sub w8, w0, w1
430 ; CHECK-NEXT: sbfx w9, w8, #7, #1
431 ; CHECK-NEXT: eor w8, w8, w9
432 ; CHECK-NEXT: sub w0, w9, w8
434 %sub = sub nsw i8 %a, %b
435 %abs = call i8 @llvm.abs.i8(i8 %sub, i1 true)
436 %nabs = sub i8 0, %abs
440 define i16 @abd_subnsw_i16(i16 %a, i16 %b) nounwind {
441 ; CHECK-LABEL: abd_subnsw_i16:
443 ; CHECK-NEXT: sub w8, w0, w1
444 ; CHECK-NEXT: sbfx w9, w8, #15, #1
445 ; CHECK-NEXT: eor w8, w8, w9
446 ; CHECK-NEXT: sub w0, w9, w8
448 %sub = sub nsw i16 %a, %b
449 %abs = call i16 @llvm.abs.i16(i16 %sub, i1 false)
450 %nabs = sub i16 0, %abs
454 define i16 @abd_subnsw_i16_undef(i16 %a, i16 %b) nounwind {
455 ; CHECK-LABEL: abd_subnsw_i16_undef:
457 ; CHECK-NEXT: sub w8, w0, w1
458 ; CHECK-NEXT: sbfx w9, w8, #15, #1
459 ; CHECK-NEXT: eor w8, w8, w9
460 ; CHECK-NEXT: sub w0, w9, w8
462 %sub = sub nsw i16 %a, %b
463 %abs = call i16 @llvm.abs.i16(i16 %sub, i1 true)
464 %nabs = sub i16 0, %abs
468 define i32 @abd_subnsw_i32(i32 %a, i32 %b) nounwind {
469 ; CHECK-LABEL: abd_subnsw_i32:
471 ; CHECK-NEXT: subs w8, w0, w1
472 ; CHECK-NEXT: cneg w0, w8, pl
474 %sub = sub nsw i32 %a, %b
475 %abs = call i32 @llvm.abs.i32(i32 %sub, i1 false)
476 %nabs = sub i32 0, %abs
480 define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
481 ; CHECK-LABEL: abd_subnsw_i32_undef:
483 ; CHECK-NEXT: subs w8, w0, w1
484 ; CHECK-NEXT: cneg w0, w8, pl
486 %sub = sub nsw i32 %a, %b
487 %abs = call i32 @llvm.abs.i32(i32 %sub, i1 true)
488 %nabs = sub i32 0, %abs
492 define i64 @abd_subnsw_i64(i64 %a, i64 %b) nounwind {
493 ; CHECK-LABEL: abd_subnsw_i64:
495 ; CHECK-NEXT: subs x8, x0, x1
496 ; CHECK-NEXT: cneg x0, x8, pl
498 %sub = sub nsw i64 %a, %b
499 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
500 %nabs = sub i64 0, %abs
504 define i64 @abd_subnsw_i64_undef(i64 %a, i64 %b) nounwind {
505 ; CHECK-LABEL: abd_subnsw_i64_undef:
507 ; CHECK-NEXT: subs x8, x0, x1
508 ; CHECK-NEXT: cneg x0, x8, pl
510 %sub = sub nsw i64 %a, %b
511 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
512 %nabs = sub i64 0, %abs
516 define i128 @abd_subnsw_i128(i128 %a, i128 %b) nounwind {
517 ; CHECK-LABEL: abd_subnsw_i128:
519 ; CHECK-NEXT: subs x8, x0, x2
520 ; CHECK-NEXT: sbc x9, x1, x3
521 ; CHECK-NEXT: asr x10, x9, #63
522 ; CHECK-NEXT: eor x8, x8, x10
523 ; CHECK-NEXT: eor x9, x9, x10
524 ; CHECK-NEXT: subs x0, x10, x8
525 ; CHECK-NEXT: sbc x1, x10, x9
527 %sub = sub nsw i128 %a, %b
528 %abs = call i128 @llvm.abs.i128(i128 %sub, i1 false)
529 %nabs = sub i128 0, %abs
533 define i128 @abd_subnsw_i128_undef(i128 %a, i128 %b) nounwind {
534 ; CHECK-LABEL: abd_subnsw_i128_undef:
536 ; CHECK-NEXT: subs x8, x0, x2
537 ; CHECK-NEXT: sbc x9, x1, x3
538 ; CHECK-NEXT: asr x10, x9, #63
539 ; CHECK-NEXT: eor x8, x8, x10
540 ; CHECK-NEXT: eor x9, x9, x10
541 ; CHECK-NEXT: subs x0, x10, x8
542 ; CHECK-NEXT: sbc x1, x10, x9
544 %sub = sub nsw i128 %a, %b
545 %abs = call i128 @llvm.abs.i128(i128 %sub, i1 true)
546 %nabs = sub i128 0, %abs
550 declare i8 @llvm.abs.i8(i8, i1)
551 declare i16 @llvm.abs.i16(i16, i1)
552 declare i32 @llvm.abs.i32(i32, i1)
553 declare i64 @llvm.abs.i64(i64, i1)
554 declare i128 @llvm.abs.i128(i128, i1)
556 declare i8 @llvm.smax.i8(i8, i8)
557 declare i16 @llvm.smax.i16(i16, i16)
558 declare i32 @llvm.smax.i32(i32, i32)
559 declare i64 @llvm.smax.i64(i64, i64)
561 declare i8 @llvm.smin.i8(i8, i8)
562 declare i16 @llvm.smin.i16(i16, i16)
563 declare i32 @llvm.smin.i32(i32, i32)
564 declare i64 @llvm.smin.i64(i64, i64)