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"
10 define <vscale x 16 x i8> @sabd_b(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b) #0 {
11 ; CHECK-LABEL: sabd_b:
13 ; CHECK-NEXT: ptrue p0.b
14 ; CHECK-NEXT: sabd z0.b, p0/m, z0.b, z1.b
16 %a.sext = sext <vscale x 16 x i8> %a to <vscale x 16 x i16>
17 %b.sext = sext <vscale x 16 x i8> %b to <vscale x 16 x i16>
18 %sub = sub <vscale x 16 x i16> %a.sext, %b.sext
19 %abs = call <vscale x 16 x i16> @llvm.abs.nxv16i16(<vscale x 16 x i16> %sub, i1 true)
20 %trunc = trunc <vscale x 16 x i16> %abs to <vscale x 16 x i8>
21 ret <vscale x 16 x i8> %trunc
24 define <vscale x 16 x i8> @sabd_b_promoted_ops(<vscale x 16 x i1> %a, <vscale x 16 x i1> %b) #0 {
25 ; CHECK-LABEL: sabd_b_promoted_ops:
27 ; CHECK-NEXT: ptrue p2.b
28 ; CHECK-NEXT: eor p0.b, p2/z, p0.b, p1.b
29 ; CHECK-NEXT: mov z0.b, p0/z, #1 // =0x1
31 %a.sext = sext <vscale x 16 x i1> %a to <vscale x 16 x i8>
32 %b.sext = sext <vscale x 16 x i1> %b to <vscale x 16 x i8>
33 %sub = sub <vscale x 16 x i8> %a.sext, %b.sext
34 %abs = call <vscale x 16 x i8> @llvm.abs.nxv16i8(<vscale x 16 x i8> %sub, i1 true)
35 ret <vscale x 16 x i8> %abs
38 define <vscale x 8 x i16> @sabd_h(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b) #0 {
39 ; CHECK-LABEL: sabd_h:
41 ; CHECK-NEXT: ptrue p0.h
42 ; CHECK-NEXT: sabd z0.h, p0/m, z0.h, z1.h
44 %a.sext = sext <vscale x 8 x i16> %a to <vscale x 8 x i32>
45 %b.sext = sext <vscale x 8 x i16> %b to <vscale x 8 x i32>
46 %sub = sub <vscale x 8 x i32> %a.sext, %b.sext
47 %abs = call <vscale x 8 x i32> @llvm.abs.nxv8i32(<vscale x 8 x i32> %sub, i1 true)
48 %trunc = trunc <vscale x 8 x i32> %abs to <vscale x 8 x i16>
49 ret <vscale x 8 x i16> %trunc
52 define <vscale x 8 x i16> @sabd_h_promoted_ops(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) #0 {
53 ; CHECK-LABEL: sabd_h_promoted_ops:
55 ; CHECK-NEXT: ptrue p0.h
56 ; CHECK-NEXT: sxtb z1.h, p0/m, z1.h
57 ; CHECK-NEXT: sxtb z0.h, p0/m, z0.h
58 ; CHECK-NEXT: sabd z0.h, p0/m, z0.h, z1.h
60 %a.sext = sext <vscale x 8 x i8> %a to <vscale x 8 x i16>
61 %b.sext = sext <vscale x 8 x i8> %b to <vscale x 8 x i16>
62 %sub = sub <vscale x 8 x i16> %a.sext, %b.sext
63 %abs = call <vscale x 8 x i16> @llvm.abs.nxv8i16(<vscale x 8 x i16> %sub, i1 true)
64 ret <vscale x 8 x i16> %abs
67 define <vscale x 4 x i32> @sabd_s(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) #0 {
68 ; CHECK-LABEL: sabd_s:
70 ; CHECK-NEXT: ptrue p0.s
71 ; CHECK-NEXT: sabd z0.s, p0/m, z0.s, z1.s
73 %a.sext = sext <vscale x 4 x i32> %a to <vscale x 4 x i64>
74 %b.sext = sext <vscale x 4 x i32> %b to <vscale x 4 x i64>
75 %sub = sub <vscale x 4 x i64> %a.sext, %b.sext
76 %abs = call <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64> %sub, i1 true)
77 %trunc = trunc <vscale x 4 x i64> %abs to <vscale x 4 x i32>
78 ret <vscale x 4 x i32> %trunc
81 define <vscale x 4 x i32> @sabd_s_promoted_ops(<vscale x 4 x i16> %a, <vscale x 4 x i16> %b) #0 {
82 ; CHECK-LABEL: sabd_s_promoted_ops:
84 ; CHECK-NEXT: ptrue p0.s
85 ; CHECK-NEXT: sxth z1.s, p0/m, z1.s
86 ; CHECK-NEXT: sxth z0.s, p0/m, z0.s
87 ; CHECK-NEXT: sabd z0.s, p0/m, z0.s, z1.s
89 %a.sext = sext <vscale x 4 x i16> %a to <vscale x 4 x i32>
90 %b.sext = sext <vscale x 4 x i16> %b to <vscale x 4 x i32>
91 %sub = sub <vscale x 4 x i32> %a.sext, %b.sext
92 %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true)
93 ret <vscale x 4 x i32> %abs
96 define <vscale x 2 x i64> @sabd_d(<vscale x 2 x i64> %a, <vscale x 2 x i64> %b) #0 {
97 ; CHECK-LABEL: sabd_d:
99 ; CHECK-NEXT: ptrue p0.d
100 ; CHECK-NEXT: sabd z0.d, p0/m, z0.d, z1.d
102 %a.sext = sext <vscale x 2 x i64> %a to <vscale x 2 x i128>
103 %b.sext = sext <vscale x 2 x i64> %b to <vscale x 2 x i128>
104 %sub = sub <vscale x 2 x i128> %a.sext, %b.sext
105 %abs = call <vscale x 2 x i128> @llvm.abs.nxv2i128(<vscale x 2 x i128> %sub, i1 true)
106 %trunc = trunc <vscale x 2 x i128> %abs to <vscale x 2 x i64>
107 ret <vscale x 2 x i64> %trunc
110 define <vscale x 2 x i64> @sabd_d_promoted_ops(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) #0 {
111 ; CHECK-LABEL: sabd_d_promoted_ops:
113 ; CHECK-NEXT: ptrue p0.d
114 ; CHECK-NEXT: sxtw z1.d, p0/m, z1.d
115 ; CHECK-NEXT: sxtw z0.d, p0/m, z0.d
116 ; CHECK-NEXT: sabd z0.d, p0/m, z0.d, z1.d
118 %a.sext = sext <vscale x 2 x i32> %a to <vscale x 2 x i64>
119 %b.sext = sext <vscale x 2 x i32> %b to <vscale x 2 x i64>
120 %sub = sub <vscale x 2 x i64> %a.sext, %b.sext
121 %abs = call <vscale x 2 x i64> @llvm.abs.nxv2i64(<vscale x 2 x i64> %sub, i1 true)
122 ret <vscale x 2 x i64> %abs
129 define <vscale x 16 x i8> @uabd_b(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b) #0 {
130 ; CHECK-LABEL: uabd_b:
132 ; CHECK-NEXT: ptrue p0.b
133 ; CHECK-NEXT: uabd z0.b, p0/m, z0.b, z1.b
135 %a.zext = zext <vscale x 16 x i8> %a to <vscale x 16 x i16>
136 %b.zext = zext <vscale x 16 x i8> %b to <vscale x 16 x i16>
137 %sub = sub <vscale x 16 x i16> %a.zext, %b.zext
138 %abs = call <vscale x 16 x i16> @llvm.abs.nxv16i16(<vscale x 16 x i16> %sub, i1 true)
139 %trunc = trunc <vscale x 16 x i16> %abs to <vscale x 16 x i8>
140 ret <vscale x 16 x i8> %trunc
143 define <vscale x 16 x i8> @uabd_b_promoted_ops(<vscale x 16 x i1> %a, <vscale x 16 x i1> %b) #0 {
144 ; CHECK-LABEL: uabd_b_promoted_ops:
146 ; CHECK-NEXT: ptrue p2.b
147 ; CHECK-NEXT: eor p0.b, p2/z, p0.b, p1.b
148 ; CHECK-NEXT: mov z0.b, p0/z, #1 // =0x1
150 %a.zext = zext <vscale x 16 x i1> %a to <vscale x 16 x i8>
151 %b.zext = zext <vscale x 16 x i1> %b to <vscale x 16 x i8>
152 %sub = sub <vscale x 16 x i8> %a.zext, %b.zext
153 %abs = call <vscale x 16 x i8> @llvm.abs.nxv16i8(<vscale x 16 x i8> %sub, i1 true)
154 ret <vscale x 16 x i8> %abs
157 define <vscale x 8 x i16> @uabd_h(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b) #0 {
158 ; CHECK-LABEL: uabd_h:
160 ; CHECK-NEXT: ptrue p0.h
161 ; CHECK-NEXT: uabd z0.h, p0/m, z0.h, z1.h
163 %a.zext = zext <vscale x 8 x i16> %a to <vscale x 8 x i32>
164 %b.zext = zext <vscale x 8 x i16> %b to <vscale x 8 x i32>
165 %sub = sub <vscale x 8 x i32> %a.zext, %b.zext
166 %abs = call <vscale x 8 x i32> @llvm.abs.nxv8i32(<vscale x 8 x i32> %sub, i1 true)
167 %trunc = trunc <vscale x 8 x i32> %abs to <vscale x 8 x i16>
168 ret <vscale x 8 x i16> %trunc
171 define <vscale x 8 x i16> @uabd_h_promoted_ops(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) #0 {
172 ; CHECK-LABEL: uabd_h_promoted_ops:
174 ; CHECK-NEXT: and z1.h, z1.h, #0xff
175 ; CHECK-NEXT: and z0.h, z0.h, #0xff
176 ; CHECK-NEXT: ptrue p0.h
177 ; CHECK-NEXT: uabd z0.h, p0/m, z0.h, z1.h
179 %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i16>
180 %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i16>
181 %sub = sub <vscale x 8 x i16> %a.zext, %b.zext
182 %abs = call <vscale x 8 x i16> @llvm.abs.nxv8i16(<vscale x 8 x i16> %sub, i1 true)
183 ret <vscale x 8 x i16> %abs
186 define <vscale x 4 x i32> @uabd_s(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) #0 {
187 ; CHECK-LABEL: uabd_s:
189 ; CHECK-NEXT: ptrue p0.s
190 ; CHECK-NEXT: uabd z0.s, p0/m, z0.s, z1.s
192 %a.zext = zext <vscale x 4 x i32> %a to <vscale x 4 x i64>
193 %b.zext = zext <vscale x 4 x i32> %b to <vscale x 4 x i64>
194 %sub = sub <vscale x 4 x i64> %a.zext, %b.zext
195 %abs = call <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64> %sub, i1 true)
196 %trunc = trunc <vscale x 4 x i64> %abs to <vscale x 4 x i32>
197 ret <vscale x 4 x i32> %trunc
200 define <vscale x 4 x i32> @uabd_s_promoted_ops(<vscale x 4 x i16> %a, <vscale x 4 x i16> %b) #0 {
201 ; CHECK-LABEL: uabd_s_promoted_ops:
203 ; CHECK-NEXT: and z1.s, z1.s, #0xffff
204 ; CHECK-NEXT: and z0.s, z0.s, #0xffff
205 ; CHECK-NEXT: ptrue p0.s
206 ; CHECK-NEXT: uabd z0.s, p0/m, z0.s, z1.s
208 %a.zext = zext <vscale x 4 x i16> %a to <vscale x 4 x i32>
209 %b.zext = zext <vscale x 4 x i16> %b to <vscale x 4 x i32>
210 %sub = sub <vscale x 4 x i32> %a.zext, %b.zext
211 %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true)
212 ret <vscale x 4 x i32> %abs
215 define <vscale x 2 x i64> @uabd_d(<vscale x 2 x i64> %a, <vscale x 2 x i64> %b) #0 {
216 ; CHECK-LABEL: uabd_d:
218 ; CHECK-NEXT: ptrue p0.d
219 ; CHECK-NEXT: uabd z0.d, p0/m, z0.d, z1.d
221 %a.zext = zext <vscale x 2 x i64> %a to <vscale x 2 x i128>
222 %b.zext = zext <vscale x 2 x i64> %b to <vscale x 2 x i128>
223 %sub = sub <vscale x 2 x i128> %a.zext, %b.zext
224 %abs = call <vscale x 2 x i128> @llvm.abs.nxv2i128(<vscale x 2 x i128> %sub, i1 true)
225 %trunc = trunc <vscale x 2 x i128> %abs to <vscale x 2 x i64>
226 ret <vscale x 2 x i64> %trunc
229 define <vscale x 2 x i64> @uabd_d_promoted_ops(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) #0 {
230 ; CHECK-LABEL: uabd_d_promoted_ops:
232 ; CHECK-NEXT: and z1.d, z1.d, #0xffffffff
233 ; CHECK-NEXT: and z0.d, z0.d, #0xffffffff
234 ; CHECK-NEXT: ptrue p0.d
235 ; CHECK-NEXT: uabd z0.d, p0/m, z0.d, z1.d
237 %a.zext = zext <vscale x 2 x i32> %a to <vscale x 2 x i64>
238 %b.zext = zext <vscale x 2 x i32> %b to <vscale x 2 x i64>
239 %sub = sub <vscale x 2 x i64> %a.zext, %b.zext
240 %abs = call <vscale x 2 x i64> @llvm.abs.nxv2i64(<vscale x 2 x i64> %sub, i1 true)
241 ret <vscale x 2 x i64> %abs
244 ; Test the situation where isLegal(ISD::ABD, typeof(%a)) returns true but %a and
245 ; %b have differing types.
246 define <vscale x 4 x i32> @uabd_non_matching_extension(<vscale x 4 x i32> %a, <vscale x 4 x i8> %b) #0 {
247 ; CHECK-LABEL: uabd_non_matching_extension:
249 ; CHECK-NEXT: and z1.s, z1.s, #0xff
250 ; CHECK-NEXT: ptrue p0.s
251 ; CHECK-NEXT: uabd z0.s, p0/m, z0.s, z1.s
253 %a.zext = zext <vscale x 4 x i32> %a to <vscale x 4 x i64>
254 %b.zext = zext <vscale x 4 x i8> %b to <vscale x 4 x i64>
255 %sub = sub <vscale x 4 x i64> %a.zext, %b.zext
256 %abs = call <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64> %sub, i1 true)
257 %trunc = trunc <vscale x 4 x i64> %abs to <vscale x 4 x i32>
258 ret <vscale x 4 x i32> %trunc
261 ; Test the situation where isLegal(ISD::ABD, typeof(%a.zext)) returns true but
262 ; %a and %b have differing types.
263 define <vscale x 4 x i32> @uabd_non_matching_promoted_ops(<vscale x 4 x i8> %a, <vscale x 4 x i16> %b) #0 {
264 ; CHECK-LABEL: uabd_non_matching_promoted_ops:
266 ; CHECK-NEXT: and z1.s, z1.s, #0xffff
267 ; CHECK-NEXT: and z0.s, z0.s, #0xff
268 ; CHECK-NEXT: ptrue p0.s
269 ; CHECK-NEXT: uabd z0.s, p0/m, z0.s, z1.s
271 %a.zext = zext <vscale x 4 x i8> %a to <vscale x 4 x i32>
272 %b.zext = zext <vscale x 4 x i16> %b to <vscale x 4 x i32>
273 %sub = sub <vscale x 4 x i32> %a.zext, %b.zext
274 %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true)
275 ret <vscale x 4 x i32> %abs
278 ; Test the situation where isLegal(ISD::ABD, typeof(%a)) returns true but %a and
279 ; %b are promoted differently.
280 define <vscale x 4 x i32> @uabd_non_matching_promotion(<vscale x 4 x i8> %a, <vscale x 4 x i8> %b) #0 {
281 ; CHECK-LABEL: uabd_non_matching_promotion:
283 ; CHECK-NEXT: ptrue p0.s
284 ; CHECK-NEXT: and z0.s, z0.s, #0xff
285 ; CHECK-NEXT: sxtb z1.s, p0/m, z1.s
286 ; CHECK-NEXT: sub z0.s, z0.s, z1.s
287 ; CHECK-NEXT: abs z0.s, p0/m, z0.s
289 %a.zext = zext <vscale x 4 x i8> %a to <vscale x 4 x i32>
290 %b.zext = sext <vscale x 4 x i8> %b to <vscale x 4 x i32>
291 %sub = sub <vscale x 4 x i32> %a.zext, %b.zext
292 %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true)
293 ret <vscale x 4 x i32> %abs
296 declare <vscale x 16 x i8> @llvm.abs.nxv16i8(<vscale x 16 x i8>, i1)
298 declare <vscale x 8 x i16> @llvm.abs.nxv8i16(<vscale x 8 x i16>, i1)
299 declare <vscale x 16 x i16> @llvm.abs.nxv16i16(<vscale x 16 x i16>, i1)
301 declare <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32>, i1)
302 declare <vscale x 8 x i32> @llvm.abs.nxv8i32(<vscale x 8 x i32>, i1)
304 declare <vscale x 2 x i64> @llvm.abs.nxv2i64(<vscale x 2 x i64>, i1)
305 declare <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64>, i1)
307 declare <vscale x 2 x i128> @llvm.abs.nxv2i128(<vscale x 2 x i128>, i1)
309 attributes #0 = { "target-features"="+neon,+sve" }