Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / AArch64 / neon-abd.ll
blobf743bae84053dca41990553d659b347426efaca4
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s | FileCheck %s
4 target triple = "aarch64-unknown-linux-gnu"
7 ; SABD
10 define <8 x i8> @sabd_8b(<8 x i8> %a, <8 x i8> %b) #0 {
11 ; CHECK-LABEL: sabd_8b:
12 ; CHECK:       // %bb.0:
13 ; CHECK-NEXT:    sabd v0.8b, v0.8b, v1.8b
14 ; CHECK-NEXT:    ret
15   %a.sext = sext <8 x i8> %a to <8 x i16>
16   %b.sext = sext <8 x i8> %b to <8 x i16>
17   %sub = sub <8 x i16> %a.sext, %b.sext
18   %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true)
19   %trunc = trunc <8 x i16> %abs to <8 x i8>
20   ret <8 x i8> %trunc
23 define <16 x i8> @sabd_16b(<16 x i8> %a, <16 x i8> %b) #0 {
24 ; CHECK-LABEL: sabd_16b:
25 ; CHECK:       // %bb.0:
26 ; CHECK-NEXT:    sabd v0.16b, v0.16b, v1.16b
27 ; CHECK-NEXT:    ret
28   %a.sext = sext <16 x i8> %a to <16 x i16>
29   %b.sext = sext <16 x i8> %b to <16 x i16>
30   %sub = sub <16 x i16> %a.sext, %b.sext
31   %abs = call <16 x i16> @llvm.abs.v16i16(<16 x i16> %sub, i1 true)
32   %trunc = trunc <16 x i16> %abs to <16 x i8>
33   ret <16 x i8> %trunc
36 define <4 x i16> @sabd_4h(<4 x i16> %a, <4 x i16> %b) #0 {
37 ; CHECK-LABEL: sabd_4h:
38 ; CHECK:       // %bb.0:
39 ; CHECK-NEXT:    sabd v0.4h, v0.4h, v1.4h
40 ; CHECK-NEXT:    ret
41   %a.sext = sext <4 x i16> %a to <4 x i32>
42   %b.sext = sext <4 x i16> %b to <4 x i32>
43   %sub = sub <4 x i32> %a.sext, %b.sext
44   %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true)
45   %trunc = trunc <4 x i32> %abs to <4 x i16>
46   ret <4 x i16> %trunc
49 define <4 x i16> @sabd_4h_promoted_ops(<4 x i8> %a, <4 x i8> %b) #0 {
50 ; CHECK-LABEL: sabd_4h_promoted_ops:
51 ; CHECK:       // %bb.0:
52 ; CHECK-NEXT:    shl v0.4h, v0.4h, #8
53 ; CHECK-NEXT:    shl v1.4h, v1.4h, #8
54 ; CHECK-NEXT:    sshr v0.4h, v0.4h, #8
55 ; CHECK-NEXT:    sshr v1.4h, v1.4h, #8
56 ; CHECK-NEXT:    sabd v0.4h, v0.4h, v1.4h
57 ; CHECK-NEXT:    ret
58   %a.sext = sext <4 x i8> %a to <4 x i16>
59   %b.sext = sext <4 x i8> %b to <4 x i16>
60   %sub = sub <4 x i16> %a.sext, %b.sext
61   %abs = call <4 x i16> @llvm.abs.v4i16(<4 x i16> %sub, i1 true)
62   ret <4 x i16> %abs
65 define <8 x i16> @sabd_8h(<8 x i16> %a, <8 x i16> %b) #0 {
66 ; CHECK-LABEL: sabd_8h:
67 ; CHECK:       // %bb.0:
68 ; CHECK-NEXT:    sabd v0.8h, v0.8h, v1.8h
69 ; CHECK-NEXT:    ret
70   %a.sext = sext <8 x i16> %a to <8 x i32>
71   %b.sext = sext <8 x i16> %b to <8 x i32>
72   %sub = sub <8 x i32> %a.sext, %b.sext
73   %abs = call <8 x i32> @llvm.abs.v8i32(<8 x i32> %sub, i1 true)
74   %trunc = trunc <8 x i32> %abs to <8 x i16>
75   ret <8 x i16> %trunc
78 define <8 x i16> @sabd_8h_promoted_ops(<8 x i8> %a, <8 x i8> %b) #0 {
79 ; CHECK-LABEL: sabd_8h_promoted_ops:
80 ; CHECK:       // %bb.0:
81 ; CHECK-NEXT:    sabdl v0.8h, v0.8b, v1.8b
82 ; CHECK-NEXT:    ret
83   %a.sext = sext <8 x i8> %a to <8 x i16>
84   %b.sext = sext <8 x i8> %b to <8 x i16>
85   %sub = sub <8 x i16> %a.sext, %b.sext
86   %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true)
87   ret <8 x i16> %abs
90 define <2 x i32> @sabd_2s(<2 x i32> %a, <2 x i32> %b) #0 {
91 ; CHECK-LABEL: sabd_2s:
92 ; CHECK:       // %bb.0:
93 ; CHECK-NEXT:    sabd v0.2s, v0.2s, v1.2s
94 ; CHECK-NEXT:    ret
95   %a.sext = sext <2 x i32> %a to <2 x i64>
96   %b.sext = sext <2 x i32> %b to <2 x i64>
97   %sub = sub <2 x i64> %a.sext, %b.sext
98   %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true)
99   %trunc = trunc <2 x i64> %abs to <2 x i32>
100   ret <2 x i32> %trunc
103 define <2 x i32> @sabd_2s_promoted_ops(<2 x i16> %a, <2 x i16> %b) #0 {
104 ; CHECK-LABEL: sabd_2s_promoted_ops:
105 ; CHECK:       // %bb.0:
106 ; CHECK-NEXT:    shl v0.2s, v0.2s, #16
107 ; CHECK-NEXT:    shl v1.2s, v1.2s, #16
108 ; CHECK-NEXT:    sshr v0.2s, v0.2s, #16
109 ; CHECK-NEXT:    sshr v1.2s, v1.2s, #16
110 ; CHECK-NEXT:    sabd v0.2s, v0.2s, v1.2s
111 ; CHECK-NEXT:    ret
112   %a.sext = sext <2 x i16> %a to <2 x i32>
113   %b.sext = sext <2 x i16> %b to <2 x i32>
114   %sub = sub <2 x i32> %a.sext, %b.sext
115   %abs = call <2 x i32> @llvm.abs.v2i32(<2 x i32> %sub, i1 true)
116   ret <2 x i32> %abs
119 define <4 x i32> @sabd_4s(<4 x i32> %a, <4 x i32> %b) #0 {
120 ; CHECK-LABEL: sabd_4s:
121 ; CHECK:       // %bb.0:
122 ; CHECK-NEXT:    sabd v0.4s, v0.4s, v1.4s
123 ; CHECK-NEXT:    ret
124   %a.sext = sext <4 x i32> %a to <4 x i64>
125   %b.sext = sext <4 x i32> %b to <4 x i64>
126   %sub = sub <4 x i64> %a.sext, %b.sext
127   %abs = call <4 x i64> @llvm.abs.v4i64(<4 x i64> %sub, i1 true)
128   %trunc = trunc <4 x i64> %abs to <4 x i32>
129   ret <4 x i32> %trunc
132 define <4 x i32> @sabd_4s_promoted_ops(<4 x i16> %a, <4 x i16> %b) #0 {
133 ; CHECK-LABEL: sabd_4s_promoted_ops:
134 ; CHECK:       // %bb.0:
135 ; CHECK-NEXT:    sabdl v0.4s, v0.4h, v1.4h
136 ; CHECK-NEXT:    ret
137   %a.sext = sext <4 x i16> %a to <4 x i32>
138   %b.sext = sext <4 x i16> %b to <4 x i32>
139   %sub = sub <4 x i32> %a.sext, %b.sext
140   %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true)
141   ret <4 x i32> %abs
144 define <2 x i64> @sabd_2d(<2 x i64> %a, <2 x i64> %b) #0 {
145 ; CHECK-LABEL: sabd_2d:
146 ; CHECK:       // %bb.0:
147 ; CHECK-NEXT:    mov x8, v0.d[1]
148 ; CHECK-NEXT:    mov x9, v1.d[1]
149 ; CHECK-NEXT:    fmov x10, d0
150 ; CHECK-NEXT:    fmov x12, d1
151 ; CHECK-NEXT:    asr x14, x10, #63
152 ; CHECK-NEXT:    asr x11, x8, #63
153 ; CHECK-NEXT:    asr x13, x9, #63
154 ; CHECK-NEXT:    asr x15, x12, #63
155 ; CHECK-NEXT:    subs x8, x8, x9
156 ; CHECK-NEXT:    sbc x9, x11, x13
157 ; CHECK-NEXT:    subs x10, x10, x12
158 ; CHECK-NEXT:    sbc x11, x14, x15
159 ; CHECK-NEXT:    asr x9, x9, #63
160 ; CHECK-NEXT:    asr x11, x11, #63
161 ; CHECK-NEXT:    eor x8, x8, x9
162 ; CHECK-NEXT:    eor x10, x10, x11
163 ; CHECK-NEXT:    sub x8, x8, x9
164 ; CHECK-NEXT:    sub x10, x10, x11
165 ; CHECK-NEXT:    fmov d1, x8
166 ; CHECK-NEXT:    fmov d0, x10
167 ; CHECK-NEXT:    mov v0.d[1], v1.d[0]
168 ; CHECK-NEXT:    ret
169   %a.sext = sext <2 x i64> %a to <2 x i128>
170   %b.sext = sext <2 x i64> %b to <2 x i128>
171   %sub = sub <2 x i128> %a.sext, %b.sext
172   %abs = call <2 x i128> @llvm.abs.v2i128(<2 x i128> %sub, i1 true)
173   %trunc = trunc <2 x i128> %abs to <2 x i64>
174   ret <2 x i64> %trunc
177 define <2 x i64> @sabd_2d_promoted_ops(<2 x i32> %a, <2 x i32> %b) #0 {
178 ; CHECK-LABEL: sabd_2d_promoted_ops:
179 ; CHECK:       // %bb.0:
180 ; CHECK-NEXT:    sabdl v0.2d, v0.2s, v1.2s
181 ; CHECK-NEXT:    ret
182   %a.sext = sext <2 x i32> %a to <2 x i64>
183   %b.sext = sext <2 x i32> %b to <2 x i64>
184   %sub = sub <2 x i64> %a.sext, %b.sext
185   %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true)
186   ret <2 x i64> %abs
190 ; UABD
193 define <8 x i8> @uabd_8b(<8 x i8> %a, <8 x i8> %b) #0 {
194 ; CHECK-LABEL: uabd_8b:
195 ; CHECK:       // %bb.0:
196 ; CHECK-NEXT:    uabd v0.8b, v0.8b, v1.8b
197 ; CHECK-NEXT:    ret
198   %a.zext = zext <8 x i8> %a to <8 x i16>
199   %b.zext = zext <8 x i8> %b to <8 x i16>
200   %sub = sub <8 x i16> %a.zext, %b.zext
201   %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true)
202   %trunc = trunc <8 x i16> %abs to <8 x i8>
203   ret <8 x i8> %trunc
206 define <16 x i8> @uabd_16b(<16 x i8> %a, <16 x i8> %b) #0 {
207 ; CHECK-LABEL: uabd_16b:
208 ; CHECK:       // %bb.0:
209 ; CHECK-NEXT:    uabd v0.16b, v0.16b, v1.16b
210 ; CHECK-NEXT:    ret
211   %a.zext = zext <16 x i8> %a to <16 x i16>
212   %b.zext = zext <16 x i8> %b to <16 x i16>
213   %sub = sub <16 x i16> %a.zext, %b.zext
214   %abs = call <16 x i16> @llvm.abs.v16i16(<16 x i16> %sub, i1 true)
215   %trunc = trunc <16 x i16> %abs to <16 x i8>
216   ret <16 x i8> %trunc
219 define <4 x i16> @uabd_4h(<4 x i16> %a, <4 x i16> %b) #0 {
220 ; CHECK-LABEL: uabd_4h:
221 ; CHECK:       // %bb.0:
222 ; CHECK-NEXT:    uabd v0.4h, v0.4h, v1.4h
223 ; CHECK-NEXT:    ret
224   %a.zext = zext <4 x i16> %a to <4 x i32>
225   %b.zext = zext <4 x i16> %b to <4 x i32>
226   %sub = sub <4 x i32> %a.zext, %b.zext
227   %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true)
228   %trunc = trunc <4 x i32> %abs to <4 x i16>
229   ret <4 x i16> %trunc
232 define <4 x i16> @uabd_4h_promoted_ops(<4 x i8> %a, <4 x i8> %b) #0 {
233 ; CHECK-LABEL: uabd_4h_promoted_ops:
234 ; CHECK:       // %bb.0:
235 ; CHECK-NEXT:    bic v0.4h, #255, lsl #8
236 ; CHECK-NEXT:    bic v1.4h, #255, lsl #8
237 ; CHECK-NEXT:    uabd v0.4h, v0.4h, v1.4h
238 ; CHECK-NEXT:    ret
239   %a.zext = zext <4 x i8> %a to <4 x i16>
240   %b.zext = zext <4 x i8> %b to <4 x i16>
241   %sub = sub <4 x i16> %a.zext, %b.zext
242   %abs = call <4 x i16> @llvm.abs.v4i16(<4 x i16> %sub, i1 true)
243   ret <4 x i16> %abs
246 define <8 x i16> @uabd_8h(<8 x i16> %a, <8 x i16> %b) #0 {
247 ; CHECK-LABEL: uabd_8h:
248 ; CHECK:       // %bb.0:
249 ; CHECK-NEXT:    uabd v0.8h, v0.8h, v1.8h
250 ; CHECK-NEXT:    ret
251   %a.zext = zext <8 x i16> %a to <8 x i32>
252   %b.zext = zext <8 x i16> %b to <8 x i32>
253   %sub = sub <8 x i32> %a.zext, %b.zext
254   %abs = call <8 x i32> @llvm.abs.v8i32(<8 x i32> %sub, i1 true)
255   %trunc = trunc <8 x i32> %abs to <8 x i16>
256   ret <8 x i16> %trunc
259 define <8 x i16> @uabd_8h_promoted_ops(<8 x i8> %a, <8 x i8> %b) #0 {
260 ; CHECK-LABEL: uabd_8h_promoted_ops:
261 ; CHECK:       // %bb.0:
262 ; CHECK-NEXT:    uabdl v0.8h, v0.8b, v1.8b
263 ; CHECK-NEXT:    ret
264   %a.zext = zext <8 x i8> %a to <8 x i16>
265   %b.zext = zext <8 x i8> %b to <8 x i16>
266   %sub = sub <8 x i16> %a.zext, %b.zext
267   %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true)
268   ret <8 x i16> %abs
271 define <2 x i32> @uabd_2s(<2 x i32> %a, <2 x i32> %b) #0 {
272 ; CHECK-LABEL: uabd_2s:
273 ; CHECK:       // %bb.0:
274 ; CHECK-NEXT:    uabd v0.2s, v0.2s, v1.2s
275 ; CHECK-NEXT:    ret
276   %a.zext = zext <2 x i32> %a to <2 x i64>
277   %b.zext = zext <2 x i32> %b to <2 x i64>
278   %sub = sub <2 x i64> %a.zext, %b.zext
279   %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true)
280   %trunc = trunc <2 x i64> %abs to <2 x i32>
281   ret <2 x i32> %trunc
284 define <2 x i32> @uabd_2s_promoted_ops(<2 x i16> %a, <2 x i16> %b) #0 {
285 ; CHECK-LABEL: uabd_2s_promoted_ops:
286 ; CHECK:       // %bb.0:
287 ; CHECK-NEXT:    movi d2, #0x00ffff0000ffff
288 ; CHECK-NEXT:    and v0.8b, v0.8b, v2.8b
289 ; CHECK-NEXT:    and v1.8b, v1.8b, v2.8b
290 ; CHECK-NEXT:    uabd v0.2s, v0.2s, v1.2s
291 ; CHECK-NEXT:    ret
292   %a.zext = zext <2 x i16> %a to <2 x i32>
293   %b.zext = zext <2 x i16> %b to <2 x i32>
294   %sub = sub <2 x i32> %a.zext, %b.zext
295   %abs = call <2 x i32> @llvm.abs.v2i32(<2 x i32> %sub, i1 true)
296   ret <2 x i32> %abs
299 define <4 x i32> @uabd_4s(<4 x i32> %a, <4 x i32> %b) #0 {
300 ; CHECK-LABEL: uabd_4s:
301 ; CHECK:       // %bb.0:
302 ; CHECK-NEXT:    uabd v0.4s, v0.4s, v1.4s
303 ; CHECK-NEXT:    ret
304   %a.zext = zext <4 x i32> %a to <4 x i64>
305   %b.zext = zext <4 x i32> %b to <4 x i64>
306   %sub = sub <4 x i64> %a.zext, %b.zext
307   %abs = call <4 x i64> @llvm.abs.v4i64(<4 x i64> %sub, i1 true)
308   %trunc = trunc <4 x i64> %abs to <4 x i32>
309   ret <4 x i32> %trunc
312 define <4 x i32> @uabd_4s_promoted_ops(<4 x i16> %a, <4 x i16> %b) #0 {
313 ; CHECK-LABEL: uabd_4s_promoted_ops:
314 ; CHECK:       // %bb.0:
315 ; CHECK-NEXT:    uabdl v0.4s, v0.4h, v1.4h
316 ; CHECK-NEXT:    ret
317   %a.zext = zext <4 x i16> %a to <4 x i32>
318   %b.zext = zext <4 x i16> %b to <4 x i32>
319   %sub = sub <4 x i32> %a.zext, %b.zext
320   %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true)
321   ret <4 x i32> %abs
324 define <2 x i64> @uabd_2d(<2 x i64> %a, <2 x i64> %b) #0 {
325 ; CHECK-LABEL: uabd_2d:
326 ; CHECK:       // %bb.0:
327 ; CHECK-NEXT:    mov x8, v0.d[1]
328 ; CHECK-NEXT:    mov x9, v1.d[1]
329 ; CHECK-NEXT:    fmov x10, d0
330 ; CHECK-NEXT:    fmov x11, d1
331 ; CHECK-NEXT:    subs x8, x8, x9
332 ; CHECK-NEXT:    ngc x9, xzr
333 ; CHECK-NEXT:    subs x10, x10, x11
334 ; CHECK-NEXT:    ngc x11, xzr
335 ; CHECK-NEXT:    asr x9, x9, #63
336 ; CHECK-NEXT:    asr x11, x11, #63
337 ; CHECK-NEXT:    eor x8, x8, x9
338 ; CHECK-NEXT:    eor x10, x10, x11
339 ; CHECK-NEXT:    sub x8, x8, x9
340 ; CHECK-NEXT:    sub x10, x10, x11
341 ; CHECK-NEXT:    fmov d1, x8
342 ; CHECK-NEXT:    fmov d0, x10
343 ; CHECK-NEXT:    mov v0.d[1], v1.d[0]
344 ; CHECK-NEXT:    ret
345   %a.zext = zext <2 x i64> %a to <2 x i128>
346   %b.zext = zext <2 x i64> %b to <2 x i128>
347   %sub = sub <2 x i128> %a.zext, %b.zext
348   %abs = call <2 x i128> @llvm.abs.v2i128(<2 x i128> %sub, i1 true)
349   %trunc = trunc <2 x i128> %abs to <2 x i64>
350   ret <2 x i64> %trunc
353 define <2 x i64> @uabd_2d_promoted_ops(<2 x i32> %a, <2 x i32> %b) #0 {
354 ; CHECK-LABEL: uabd_2d_promoted_ops:
355 ; CHECK:       // %bb.0:
356 ; CHECK-NEXT:    uabdl v0.2d, v0.2s, v1.2s
357 ; CHECK-NEXT:    ret
358   %a.zext = zext <2 x i32> %a to <2 x i64>
359   %b.zext = zext <2 x i32> %b to <2 x i64>
360   %sub = sub <2 x i64> %a.zext, %b.zext
361   %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true)
362   ret <2 x i64> %abs
365 define <16 x i8> @uabd_v16i8_nuw(<16 x i8> %a, <16 x i8> %b) #0 {
366 ; CHECK-LABEL: uabd_v16i8_nuw:
367 ; CHECK:       // %bb.0:
368 ; CHECK-NEXT:    sub v0.16b, v0.16b, v1.16b
369 ; CHECK-NEXT:    abs v0.16b, v0.16b
370 ; CHECK-NEXT:    ret
371   %sub = sub nuw <16 x i8> %a, %b
372   %abs = call <16 x i8> @llvm.abs.v16i8(<16 x i8> %sub, i1 true)
373   ret <16 x i8> %abs
376 define <8 x i16> @uabd_v8i16_nuw(<8 x i16> %a, <8 x i16> %b) #0 {
377 ; CHECK-LABEL: uabd_v8i16_nuw:
378 ; CHECK:       // %bb.0:
379 ; CHECK-NEXT:    sub v0.8h, v0.8h, v1.8h
380 ; CHECK-NEXT:    abs v0.8h, v0.8h
381 ; CHECK-NEXT:    ret
382   %sub = sub nuw <8 x i16> %a, %b
383   %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true)
384   ret <8 x i16> %abs
387 define <4 x i32> @uabd_v4i32_nuw(<4 x i32> %a, <4 x i32> %b) #0 {
388 ; CHECK-LABEL: uabd_v4i32_nuw:
389 ; CHECK:       // %bb.0:
390 ; CHECK-NEXT:    sub v0.4s, v0.4s, v1.4s
391 ; CHECK-NEXT:    abs v0.4s, v0.4s
392 ; CHECK-NEXT:    ret
393   %sub = sub nuw <4 x i32> %a, %b
394   %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true)
395   ret <4 x i32> %abs
398 define <2 x i64> @uabd_v2i64_nuw(<2 x i64> %a, <2 x i64> %b) #0 {
399 ; CHECK-LABEL: uabd_v2i64_nuw:
400 ; CHECK:       // %bb.0:
401 ; CHECK-NEXT:    sub v0.2d, v0.2d, v1.2d
402 ; CHECK-NEXT:    abs v0.2d, v0.2d
403 ; CHECK-NEXT:    ret
404   %sub = sub nuw <2 x i64> %a, %b
405   %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true)
406   ret <2 x i64> %abs
409 define <16 x i8> @sabd_v16i8_nsw(<16 x i8> %a, <16 x i8> %b) #0 {
410 ; CHECK-LABEL: sabd_v16i8_nsw:
411 ; CHECK:       // %bb.0:
412 ; CHECK-NEXT:    sabd v0.16b, v0.16b, v1.16b
413 ; CHECK-NEXT:    ret
414   %sub = sub nsw <16 x i8> %a, %b
415   %abs = call <16 x i8> @llvm.abs.v16i8(<16 x i8> %sub, i1 true)
416   ret <16 x i8> %abs
419 define <8 x i16> @sabd_v8i16_nsw(<8 x i16> %a, <8 x i16> %b) #0 {
420 ; CHECK-LABEL: sabd_v8i16_nsw:
421 ; CHECK:       // %bb.0:
422 ; CHECK-NEXT:    sabd v0.8h, v0.8h, v1.8h
423 ; CHECK-NEXT:    ret
424   %sub = sub nsw <8 x i16> %a, %b
425   %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true)
426   ret <8 x i16> %abs
429 define <4 x i32> @sabd_v4i32_nsw(<4 x i32> %a, <4 x i32> %b) #0 {
430 ; CHECK-LABEL: sabd_v4i32_nsw:
431 ; CHECK:       // %bb.0:
432 ; CHECK-NEXT:    sabd v0.4s, v0.4s, v1.4s
433 ; CHECK-NEXT:    ret
434   %sub = sub nsw <4 x i32> %a, %b
435   %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true)
436   ret <4 x i32> %abs
439 define <2 x i64> @sabd_v2i64_nsw(<2 x i64> %a, <2 x i64> %b) #0 {
440 ; CHECK-LABEL: sabd_v2i64_nsw:
441 ; CHECK:       // %bb.0:
442 ; CHECK-NEXT:    sub v0.2d, v0.2d, v1.2d
443 ; CHECK-NEXT:    abs v0.2d, v0.2d
444 ; CHECK-NEXT:    ret
445   %sub = sub nsw <2 x i64> %a, %b
446   %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true)
447   ret <2 x i64> %abs
450 define <16 x i8> @smaxmin_v16i8(<16 x i8> %0, <16 x i8> %1) {
451 ; CHECK-LABEL: smaxmin_v16i8:
452 ; CHECK:       // %bb.0:
453 ; CHECK-NEXT:    sabd v0.16b, v0.16b, v1.16b
454 ; CHECK-NEXT:    ret
455   %a = tail call <16 x i8> @llvm.smax.v16i8(<16 x i8> %0, <16 x i8> %1)
456   %b = tail call <16 x i8> @llvm.smin.v16i8(<16 x i8> %0, <16 x i8> %1)
457   %sub = sub <16 x i8> %a, %b
458   ret <16 x i8> %sub
461 define <8 x i16> @smaxmin_v8i16(<8 x i16> %0, <8 x i16> %1) {
462 ; CHECK-LABEL: smaxmin_v8i16:
463 ; CHECK:       // %bb.0:
464 ; CHECK-NEXT:    sabd v0.8h, v0.8h, v1.8h
465 ; CHECK-NEXT:    ret
466   %a = tail call <8 x i16> @llvm.smax.v8i16(<8 x i16> %0, <8 x i16> %1)
467   %b = tail call <8 x i16> @llvm.smin.v8i16(<8 x i16> %0, <8 x i16> %1)
468   %sub = sub <8 x i16> %a, %b
469   ret <8 x i16> %sub
472 define <4 x i32> @smaxmin_v4i32(<4 x i32> %0, <4 x i32> %1) {
473 ; CHECK-LABEL: smaxmin_v4i32:
474 ; CHECK:       // %bb.0:
475 ; CHECK-NEXT:    sabd v0.4s, v0.4s, v1.4s
476 ; CHECK-NEXT:    ret
477   %a = tail call <4 x i32> @llvm.smax.v4i32(<4 x i32> %0, <4 x i32> %1)
478   %b = tail call <4 x i32> @llvm.smin.v4i32(<4 x i32> %0, <4 x i32> %1)
479   %sub = sub <4 x i32> %a, %b
480   ret <4 x i32> %sub
483 define <2 x i64> @smaxmin_v2i64(<2 x i64> %0, <2 x i64> %1) {
484 ; CHECK-LABEL: smaxmin_v2i64:
485 ; CHECK:       // %bb.0:
486 ; CHECK-NEXT:    cmgt v2.2d, v0.2d, v1.2d
487 ; CHECK-NEXT:    cmgt v3.2d, v1.2d, v0.2d
488 ; CHECK-NEXT:    bsl v2.16b, v0.16b, v1.16b
489 ; CHECK-NEXT:    bif v0.16b, v1.16b, v3.16b
490 ; CHECK-NEXT:    sub v0.2d, v2.2d, v0.2d
491 ; CHECK-NEXT:    ret
492   %a = tail call <2 x i64> @llvm.smax.v2i64(<2 x i64> %0, <2 x i64> %1)
493   %b = tail call <2 x i64> @llvm.smin.v2i64(<2 x i64> %0, <2 x i64> %1)
494   %sub = sub <2 x i64> %a, %b
495   ret <2 x i64> %sub
498 define <16 x i8> @umaxmin_v16i8(<16 x i8> %0, <16 x i8> %1) {
499 ; CHECK-LABEL: umaxmin_v16i8:
500 ; CHECK:       // %bb.0:
501 ; CHECK-NEXT:    uabd v0.16b, v0.16b, v1.16b
502 ; CHECK-NEXT:    ret
503   %a = tail call <16 x i8> @llvm.umax.v16i8(<16 x i8> %0, <16 x i8> %1)
504   %b = tail call <16 x i8> @llvm.umin.v16i8(<16 x i8> %0, <16 x i8> %1)
505   %sub = sub <16 x i8> %a, %b
506   ret <16 x i8> %sub
509 define <8 x i16> @umaxmin_v8i16(<8 x i16> %0, <8 x i16> %1) {
510 ; CHECK-LABEL: umaxmin_v8i16:
511 ; CHECK:       // %bb.0:
512 ; CHECK-NEXT:    uabd v0.8h, v0.8h, v1.8h
513 ; CHECK-NEXT:    ret
514   %a = tail call <8 x i16> @llvm.umax.v8i16(<8 x i16> %0, <8 x i16> %1)
515   %b = tail call <8 x i16> @llvm.umin.v8i16(<8 x i16> %0, <8 x i16> %1)
516   %sub = sub <8 x i16> %a, %b
517   ret <8 x i16> %sub
520 define <4 x i32> @umaxmin_v4i32(<4 x i32> %0, <4 x i32> %1) {
521 ; CHECK-LABEL: umaxmin_v4i32:
522 ; CHECK:       // %bb.0:
523 ; CHECK-NEXT:    uabd v0.4s, v0.4s, v1.4s
524 ; CHECK-NEXT:    ret
525   %a = tail call <4 x i32> @llvm.umax.v4i32(<4 x i32> %0, <4 x i32> %1)
526   %b = tail call <4 x i32> @llvm.umin.v4i32(<4 x i32> %0, <4 x i32> %1)
527   %sub = sub <4 x i32> %a, %b
528   ret <4 x i32> %sub
531 define <2 x i64> @umaxmin_v2i64(<2 x i64> %0, <2 x i64> %1) {
532 ; CHECK-LABEL: umaxmin_v2i64:
533 ; CHECK:       // %bb.0:
534 ; CHECK-NEXT:    cmhi v2.2d, v0.2d, v1.2d
535 ; CHECK-NEXT:    cmhi v3.2d, v1.2d, v0.2d
536 ; CHECK-NEXT:    bsl v2.16b, v0.16b, v1.16b
537 ; CHECK-NEXT:    bif v0.16b, v1.16b, v3.16b
538 ; CHECK-NEXT:    sub v0.2d, v2.2d, v0.2d
539 ; CHECK-NEXT:    ret
540   %a = tail call <2 x i64> @llvm.umax.v2i64(<2 x i64> %0, <2 x i64> %1)
541   %b = tail call <2 x i64> @llvm.umin.v2i64(<2 x i64> %0, <2 x i64> %1)
542   %sub = sub <2 x i64> %a, %b
543   ret <2 x i64> %sub
546 define <16 x i8> @umaxmin_v16i8_com1(<16 x i8> %0, <16 x i8> %1) {
547 ; CHECK-LABEL: umaxmin_v16i8_com1:
548 ; CHECK:       // %bb.0:
549 ; CHECK-NEXT:    uabd v0.16b, v0.16b, v1.16b
550 ; CHECK-NEXT:    ret
551   %a = tail call <16 x i8> @llvm.umax.v16i8(<16 x i8> %0, <16 x i8> %1)
552   %b = tail call <16 x i8> @llvm.umin.v16i8(<16 x i8> %1, <16 x i8> %0)
553   %sub = sub <16 x i8> %a, %b
554   ret <16 x i8> %sub
557 ; (abds x, y) upper bits are known zero if x and y have extra sign bits
558 define <4 x i16> @combine_sabd_4h_zerosign(<4 x i16> %a, <4 x i16> %b) #0 {
559 ; CHECK-LABEL: combine_sabd_4h_zerosign:
560 ; CHECK:       // %bb.0:
561 ; CHECK-NEXT:    movi v0.2d, #0000000000000000
562 ; CHECK-NEXT:    ret
563   %a.ext = ashr <4 x i16> %a, <i16 7, i16 8, i16 9, i16 10>
564   %b.ext = ashr <4 x i16> %b, <i16 11, i16 12, i16 13, i16 14>
565   %max = tail call <4 x i16> @llvm.smax.v4i16(<4 x i16> %a.ext, <4 x i16> %b.ext)
566   %min = tail call <4 x i16> @llvm.smin.v4i16(<4 x i16> %a.ext, <4 x i16> %b.ext)
567   %sub = sub <4 x i16> %max, %min
568   %mask = and <4 x i16> %sub, <i16 32768, i16 32768, i16 32768, i16 32768>
569   ret <4 x i16> %mask
572 ; negative test - mask extends beyond known zero bits
573 define <2 x i32> @combine_sabd_2s_zerosign_negative(<2 x i32> %a, <2 x i32> %b) {
574 ; CHECK-LABEL: combine_sabd_2s_zerosign_negative:
575 ; CHECK:       // %bb.0:
576 ; CHECK-NEXT:    sshr v0.2s, v0.2s, #3
577 ; CHECK-NEXT:    sshr v1.2s, v1.2s, #15
578 ; CHECK-NEXT:    mvni v2.2s, #7, msl #16
579 ; CHECK-NEXT:    sabd v0.2s, v0.2s, v1.2s
580 ; CHECK-NEXT:    and v0.8b, v0.8b, v2.8b
581 ; CHECK-NEXT:    ret
582   %a.ext = ashr <2 x i32> %a, <i32 3, i32 3>
583   %b.ext = ashr <2 x i32> %b, <i32 15, i32 15>
584   %max = tail call <2 x i32> @llvm.smax.v2i32(<2 x i32> %a.ext, <2 x i32> %b.ext)
585   %min = tail call <2 x i32> @llvm.smin.v2i32(<2 x i32> %a.ext, <2 x i32> %b.ext)
586   %sub = sub <2 x i32> %max, %min
587   %mask = and <2 x i32> %sub, <i32 -524288, i32 -524288> ; 0xFFF80000
588   ret <2 x i32> %mask
591 declare <8 x i8> @llvm.abs.v8i8(<8 x i8>, i1)
592 declare <16 x i8> @llvm.abs.v16i8(<16 x i8>, i1)
594 declare <4 x i16> @llvm.abs.v4i16(<4 x i16>, i1)
595 declare <8 x i16> @llvm.abs.v8i16(<8 x i16>, i1)
596 declare <16 x i16> @llvm.abs.v16i16(<16 x i16>, i1)
598 declare <2 x i32> @llvm.abs.v2i32(<2 x i32>, i1)
599 declare <4 x i32> @llvm.abs.v4i32(<4 x i32>, i1)
600 declare <8 x i32> @llvm.abs.v8i32(<8 x i32>, i1)
602 declare <2 x i64> @llvm.abs.v2i64(<2 x i64>, i1)
603 declare <4 x i64> @llvm.abs.v4i64(<4 x i64>, i1)
605 declare <2 x i128> @llvm.abs.v2i128(<2 x i128>, i1)
607 declare <16 x i8> @llvm.smax.v16i8(<16 x i8>, <16 x i8>)
608 declare <8 x i16> @llvm.smax.v8i16(<8 x i16>, <8 x i16>)
609 declare <4 x i32> @llvm.smax.v4i32(<4 x i32>, <4 x i32>)
610 declare <2 x i64> @llvm.smax.v2i64(<2 x i64>, <2 x i64>)
611 declare <16 x i8> @llvm.smin.v16i8(<16 x i8>, <16 x i8>)
612 declare <8 x i16> @llvm.smin.v8i16(<8 x i16>, <8 x i16>)
613 declare <4 x i32> @llvm.smin.v4i32(<4 x i32>, <4 x i32>)
614 declare <2 x i64> @llvm.smin.v2i64(<2 x i64>, <2 x i64>)
615 declare <16 x i8> @llvm.umax.v16i8(<16 x i8>, <16 x i8>)
616 declare <8 x i16> @llvm.umax.v8i16(<8 x i16>, <8 x i16>)
617 declare <4 x i32> @llvm.umax.v4i32(<4 x i32>, <4 x i32>)
618 declare <2 x i64> @llvm.umax.v2i64(<2 x i64>, <2 x i64>)
619 declare <16 x i8> @llvm.umin.v16i8(<16 x i8>, <16 x i8>)
620 declare <8 x i16> @llvm.umin.v8i16(<8 x i16>, <8 x i16>)
621 declare <4 x i32> @llvm.umin.v4i32(<4 x i32>, <4 x i32>)
622 declare <2 x i64> @llvm.umin.v2i64(<2 x i64>, <2 x i64>)
624 attributes #0 = { "target-features"="+neon" }