1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -mattr=+v,+d -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,RV32
3 ; RUN: llc -mtriple=riscv64 -mattr=+v,+d -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,RV64
9 define <vscale x 16 x i8> @sabd_b(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b) {
10 ; CHECK-LABEL: sabd_b:
12 ; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma
13 ; CHECK-NEXT: vmin.vv v12, v8, v10
14 ; CHECK-NEXT: vmax.vv v8, v8, v10
15 ; CHECK-NEXT: vsub.vv v8, v8, v12
17 %a.sext = sext <vscale x 16 x i8> %a to <vscale x 16 x i16>
18 %b.sext = sext <vscale x 16 x i8> %b to <vscale x 16 x i16>
19 %sub = sub <vscale x 16 x i16> %a.sext, %b.sext
20 %abs = call <vscale x 16 x i16> @llvm.abs.nxv16i16(<vscale x 16 x i16> %sub, i1 true)
21 %trunc = trunc <vscale x 16 x i16> %abs to <vscale x 16 x i8>
22 ret <vscale x 16 x i8> %trunc
25 define <vscale x 16 x i8> @sabd_b_promoted_ops(<vscale x 16 x i1> %a, <vscale x 16 x i1> %b) {
26 ; CHECK-LABEL: sabd_b_promoted_ops:
28 ; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma
29 ; CHECK-NEXT: vmv.v.i v10, 0
30 ; CHECK-NEXT: vmerge.vim v12, v10, -1, v0
31 ; CHECK-NEXT: vmv1r.v v0, v8
32 ; CHECK-NEXT: vmerge.vim v8, v10, -1, v0
33 ; CHECK-NEXT: vmin.vv v10, v12, v8
34 ; CHECK-NEXT: vmax.vv v8, v12, v8
35 ; CHECK-NEXT: vsub.vv v8, v8, v10
37 %a.sext = sext <vscale x 16 x i1> %a to <vscale x 16 x i8>
38 %b.sext = sext <vscale x 16 x i1> %b to <vscale x 16 x i8>
39 %sub = sub <vscale x 16 x i8> %a.sext, %b.sext
40 %abs = call <vscale x 16 x i8> @llvm.abs.nxv16i8(<vscale x 16 x i8> %sub, i1 true)
41 ret <vscale x 16 x i8> %abs
44 define <vscale x 8 x i16> @sabd_h(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b) {
45 ; CHECK-LABEL: sabd_h:
47 ; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma
48 ; CHECK-NEXT: vmin.vv v12, v8, v10
49 ; CHECK-NEXT: vmax.vv v8, v8, v10
50 ; CHECK-NEXT: vsub.vv v8, v8, v12
52 %a.sext = sext <vscale x 8 x i16> %a to <vscale x 8 x i32>
53 %b.sext = sext <vscale x 8 x i16> %b to <vscale x 8 x i32>
54 %sub = sub <vscale x 8 x i32> %a.sext, %b.sext
55 %abs = call <vscale x 8 x i32> @llvm.abs.nxv8i32(<vscale x 8 x i32> %sub, i1 true)
56 %trunc = trunc <vscale x 8 x i32> %abs to <vscale x 8 x i16>
57 ret <vscale x 8 x i16> %trunc
60 define <vscale x 8 x i16> @sabd_h_promoted_ops(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) {
61 ; CHECK-LABEL: sabd_h_promoted_ops:
63 ; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma
64 ; CHECK-NEXT: vmin.vv v10, v8, v9
65 ; CHECK-NEXT: vmax.vv v8, v8, v9
66 ; CHECK-NEXT: vsub.vv v10, v8, v10
67 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma
68 ; CHECK-NEXT: vzext.vf2 v8, v10
70 %a.sext = sext <vscale x 8 x i8> %a to <vscale x 8 x i16>
71 %b.sext = sext <vscale x 8 x i8> %b to <vscale x 8 x i16>
72 %sub = sub <vscale x 8 x i16> %a.sext, %b.sext
73 %abs = call <vscale x 8 x i16> @llvm.abs.nxv8i16(<vscale x 8 x i16> %sub, i1 true)
74 ret <vscale x 8 x i16> %abs
77 define <vscale x 4 x i32> @sabd_s(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
78 ; CHECK-LABEL: sabd_s:
80 ; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma
81 ; CHECK-NEXT: vmin.vv v12, v8, v10
82 ; CHECK-NEXT: vmax.vv v8, v8, v10
83 ; CHECK-NEXT: vsub.vv v8, v8, v12
85 %a.sext = sext <vscale x 4 x i32> %a to <vscale x 4 x i64>
86 %b.sext = sext <vscale x 4 x i32> %b to <vscale x 4 x i64>
87 %sub = sub <vscale x 4 x i64> %a.sext, %b.sext
88 %abs = call <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64> %sub, i1 true)
89 %trunc = trunc <vscale x 4 x i64> %abs to <vscale x 4 x i32>
90 ret <vscale x 4 x i32> %trunc
93 define <vscale x 4 x i32> @sabd_s_promoted_ops(<vscale x 4 x i16> %a, <vscale x 4 x i16> %b) {
94 ; CHECK-LABEL: sabd_s_promoted_ops:
96 ; CHECK-NEXT: vsetvli a0, zero, e16, m1, ta, ma
97 ; CHECK-NEXT: vmin.vv v10, v8, v9
98 ; CHECK-NEXT: vmax.vv v8, v8, v9
99 ; CHECK-NEXT: vsub.vv v10, v8, v10
100 ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma
101 ; CHECK-NEXT: vzext.vf2 v8, v10
103 %a.sext = sext <vscale x 4 x i16> %a to <vscale x 4 x i32>
104 %b.sext = sext <vscale x 4 x i16> %b to <vscale x 4 x i32>
105 %sub = sub <vscale x 4 x i32> %a.sext, %b.sext
106 %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true)
107 ret <vscale x 4 x i32> %abs
110 ; FIXME: Crashes legalization if enabled
111 ;; define <vscale x 2 x i64> @sabd_d(<vscale x 2 x i64> %a, <vscale x 2 x i64> %b) {
112 ;; %a.sext = sext <vscale x 2 x i64> %a to <vscale x 2 x i128>
113 ;; %b.sext = sext <vscale x 2 x i64> %b to <vscale x 2 x i128>
114 ;; %sub = sub <vscale x 2 x i128> %a.sext, %b.sext
115 ;; %abs = call <vscale x 2 x i128> @llvm.abs.nxv2i128(<vscale x 2 x i128> %sub, i1 true)
116 ;; %trunc = trunc <vscale x 2 x i128> %abs to <vscale x 2 x i64>
117 ;; ret <vscale x 2 x i64> %trunc
120 define <vscale x 2 x i64> @sabd_d_promoted_ops(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) {
121 ; CHECK-LABEL: sabd_d_promoted_ops:
123 ; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma
124 ; CHECK-NEXT: vmin.vv v10, v8, v9
125 ; CHECK-NEXT: vmax.vv v8, v8, v9
126 ; CHECK-NEXT: vsub.vv v10, v8, v10
127 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma
128 ; CHECK-NEXT: vzext.vf2 v8, v10
130 %a.sext = sext <vscale x 2 x i32> %a to <vscale x 2 x i64>
131 %b.sext = sext <vscale x 2 x i32> %b to <vscale x 2 x i64>
132 %sub = sub <vscale x 2 x i64> %a.sext, %b.sext
133 %abs = call <vscale x 2 x i64> @llvm.abs.nxv2i64(<vscale x 2 x i64> %sub, i1 true)
134 ret <vscale x 2 x i64> %abs
141 define <vscale x 16 x i8> @uabd_b(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b) {
142 ; CHECK-LABEL: uabd_b:
144 ; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma
145 ; CHECK-NEXT: vminu.vv v12, v8, v10
146 ; CHECK-NEXT: vmaxu.vv v8, v8, v10
147 ; CHECK-NEXT: vsub.vv v8, v8, v12
149 %a.zext = zext <vscale x 16 x i8> %a to <vscale x 16 x i16>
150 %b.zext = zext <vscale x 16 x i8> %b to <vscale x 16 x i16>
151 %sub = sub <vscale x 16 x i16> %a.zext, %b.zext
152 %abs = call <vscale x 16 x i16> @llvm.abs.nxv16i16(<vscale x 16 x i16> %sub, i1 true)
153 %trunc = trunc <vscale x 16 x i16> %abs to <vscale x 16 x i8>
154 ret <vscale x 16 x i8> %trunc
157 define <vscale x 16 x i8> @uabd_b_promoted_ops(<vscale x 16 x i1> %a, <vscale x 16 x i1> %b) {
158 ; CHECK-LABEL: uabd_b_promoted_ops:
160 ; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma
161 ; CHECK-NEXT: vmv.v.i v10, 0
162 ; CHECK-NEXT: vmerge.vim v12, v10, 1, v0
163 ; CHECK-NEXT: vmv1r.v v0, v8
164 ; CHECK-NEXT: vmerge.vim v8, v10, 1, v0
165 ; CHECK-NEXT: vminu.vv v10, v12, v8
166 ; CHECK-NEXT: vmaxu.vv v8, v12, v8
167 ; CHECK-NEXT: vsub.vv v8, v8, v10
169 %a.zext = zext <vscale x 16 x i1> %a to <vscale x 16 x i8>
170 %b.zext = zext <vscale x 16 x i1> %b to <vscale x 16 x i8>
171 %sub = sub <vscale x 16 x i8> %a.zext, %b.zext
172 %abs = call <vscale x 16 x i8> @llvm.abs.nxv16i8(<vscale x 16 x i8> %sub, i1 true)
173 ret <vscale x 16 x i8> %abs
176 define <vscale x 8 x i16> @uabd_h(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b) {
177 ; CHECK-LABEL: uabd_h:
179 ; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma
180 ; CHECK-NEXT: vminu.vv v12, v8, v10
181 ; CHECK-NEXT: vmaxu.vv v8, v8, v10
182 ; CHECK-NEXT: vsub.vv v8, v8, v12
184 %a.zext = zext <vscale x 8 x i16> %a to <vscale x 8 x i32>
185 %b.zext = zext <vscale x 8 x i16> %b to <vscale x 8 x i32>
186 %sub = sub <vscale x 8 x i32> %a.zext, %b.zext
187 %abs = call <vscale x 8 x i32> @llvm.abs.nxv8i32(<vscale x 8 x i32> %sub, i1 true)
188 %trunc = trunc <vscale x 8 x i32> %abs to <vscale x 8 x i16>
189 ret <vscale x 8 x i16> %trunc
192 define <vscale x 8 x i16> @uabd_h_promoted_ops(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) {
193 ; CHECK-LABEL: uabd_h_promoted_ops:
195 ; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma
196 ; CHECK-NEXT: vminu.vv v10, v8, v9
197 ; CHECK-NEXT: vmaxu.vv v8, v8, v9
198 ; CHECK-NEXT: vsub.vv v10, v8, v10
199 ; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma
200 ; CHECK-NEXT: vzext.vf2 v8, v10
202 %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i16>
203 %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i16>
204 %sub = sub <vscale x 8 x i16> %a.zext, %b.zext
205 %abs = call <vscale x 8 x i16> @llvm.abs.nxv8i16(<vscale x 8 x i16> %sub, i1 true)
206 ret <vscale x 8 x i16> %abs
209 define <vscale x 4 x i32> @uabd_s(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
210 ; CHECK-LABEL: uabd_s:
212 ; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma
213 ; CHECK-NEXT: vminu.vv v12, v8, v10
214 ; CHECK-NEXT: vmaxu.vv v8, v8, v10
215 ; CHECK-NEXT: vsub.vv v8, v8, v12
217 %a.zext = zext <vscale x 4 x i32> %a to <vscale x 4 x i64>
218 %b.zext = zext <vscale x 4 x i32> %b to <vscale x 4 x i64>
219 %sub = sub <vscale x 4 x i64> %a.zext, %b.zext
220 %abs = call <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64> %sub, i1 true)
221 %trunc = trunc <vscale x 4 x i64> %abs to <vscale x 4 x i32>
222 ret <vscale x 4 x i32> %trunc
225 define <vscale x 4 x i32> @uabd_s_promoted_ops(<vscale x 4 x i16> %a, <vscale x 4 x i16> %b) {
226 ; CHECK-LABEL: uabd_s_promoted_ops:
228 ; CHECK-NEXT: vsetvli a0, zero, e16, m1, ta, ma
229 ; CHECK-NEXT: vminu.vv v10, v8, v9
230 ; CHECK-NEXT: vmaxu.vv v8, v8, v9
231 ; CHECK-NEXT: vsub.vv v10, v8, v10
232 ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma
233 ; CHECK-NEXT: vzext.vf2 v8, v10
235 %a.zext = zext <vscale x 4 x i16> %a to <vscale x 4 x i32>
236 %b.zext = zext <vscale x 4 x i16> %b to <vscale x 4 x i32>
237 %sub = sub <vscale x 4 x i32> %a.zext, %b.zext
238 %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true)
239 ret <vscale x 4 x i32> %abs
242 ; FIXME: Crashes legalization if enabled
243 ;; define <vscale x 2 x i64> @uabd_d(<vscale x 2 x i64> %a, <vscale x 2 x i64> %b) {
244 ;; %a.zext = zext <vscale x 2 x i64> %a to <vscale x 2 x i128>
245 ;; %b.zext = zext <vscale x 2 x i64> %b to <vscale x 2 x i128>
246 ;; %sub = sub <vscale x 2 x i128> %a.zext, %b.zext
247 ;; %abs = call <vscale x 2 x i128> @llvm.abs.nxv2i128(<vscale x 2 x i128> %sub, i1 true)
248 ;; %trunc = trunc <vscale x 2 x i128> %abs to <vscale x 2 x i64>
249 ;; ret <vscale x 2 x i64> %trunc
252 define <vscale x 2 x i64> @uabd_d_promoted_ops(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) {
253 ; CHECK-LABEL: uabd_d_promoted_ops:
255 ; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma
256 ; CHECK-NEXT: vminu.vv v10, v8, v9
257 ; CHECK-NEXT: vmaxu.vv v8, v8, v9
258 ; CHECK-NEXT: vsub.vv v10, v8, v10
259 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma
260 ; CHECK-NEXT: vzext.vf2 v8, v10
262 %a.zext = zext <vscale x 2 x i32> %a to <vscale x 2 x i64>
263 %b.zext = zext <vscale x 2 x i32> %b to <vscale x 2 x i64>
264 %sub = sub <vscale x 2 x i64> %a.zext, %b.zext
265 %abs = call <vscale x 2 x i64> @llvm.abs.nxv2i64(<vscale x 2 x i64> %sub, i1 true)
266 ret <vscale x 2 x i64> %abs
269 ; Test the situation where isLegal(ISD::ABD, typeof(%a)) returns true but %a and
270 ; %b have differing types.
271 define <vscale x 4 x i32> @uabd_non_matching_extension(<vscale x 4 x i32> %a, <vscale x 4 x i8> %b) {
272 ; CHECK-LABEL: uabd_non_matching_extension:
274 ; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma
275 ; CHECK-NEXT: vzext.vf4 v12, v10
276 ; CHECK-NEXT: vminu.vv v10, v8, v12
277 ; CHECK-NEXT: vmaxu.vv v8, v8, v12
278 ; CHECK-NEXT: vsub.vv v8, v8, v10
280 %a.zext = zext <vscale x 4 x i32> %a to <vscale x 4 x i64>
281 %b.zext = zext <vscale x 4 x i8> %b to <vscale x 4 x i64>
282 %sub = sub <vscale x 4 x i64> %a.zext, %b.zext
283 %abs = call <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64> %sub, i1 true)
284 %trunc = trunc <vscale x 4 x i64> %abs to <vscale x 4 x i32>
285 ret <vscale x 4 x i32> %trunc
288 ; Test the situation where isLegal(ISD::ABD, typeof(%a.zext)) returns true but
289 ; %a and %b have differing types.
290 define <vscale x 4 x i32> @uabd_non_matching_promoted_ops(<vscale x 4 x i8> %a, <vscale x 4 x i16> %b) {
291 ; CHECK-LABEL: uabd_non_matching_promoted_ops:
293 ; CHECK-NEXT: vsetvli a0, zero, e16, m1, ta, ma
294 ; CHECK-NEXT: vzext.vf2 v10, v8
295 ; CHECK-NEXT: vminu.vv v8, v10, v9
296 ; CHECK-NEXT: vmaxu.vv v9, v10, v9
297 ; CHECK-NEXT: vsub.vv v10, v9, v8
298 ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma
299 ; CHECK-NEXT: vzext.vf2 v8, v10
301 %a.zext = zext <vscale x 4 x i8> %a to <vscale x 4 x i32>
302 %b.zext = zext <vscale x 4 x i16> %b to <vscale x 4 x i32>
303 %sub = sub <vscale x 4 x i32> %a.zext, %b.zext
304 %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true)
305 ret <vscale x 4 x i32> %abs
308 ; Test the situation where isLegal(ISD::ABD, typeof(%a)) returns true but %a and
309 ; %b are promoted differently.
310 define <vscale x 4 x i32> @uabd_non_matching_promotion(<vscale x 4 x i8> %a, <vscale x 4 x i8> %b) {
311 ; CHECK-LABEL: uabd_non_matching_promotion:
313 ; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma
314 ; CHECK-NEXT: vzext.vf4 v10, v8
315 ; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, ma
316 ; CHECK-NEXT: vsext.vf2 v8, v9
317 ; CHECK-NEXT: vwsub.wv v10, v10, v8
318 ; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma
319 ; CHECK-NEXT: vrsub.vi v8, v10, 0
320 ; CHECK-NEXT: vmax.vv v8, v10, v8
322 %a.zext = zext <vscale x 4 x i8> %a to <vscale x 4 x i32>
323 %b.zext = sext <vscale x 4 x i8> %b to <vscale x 4 x i32>
324 %sub = sub <vscale x 4 x i32> %a.zext, %b.zext
325 %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true)
326 ret <vscale x 4 x i32> %abs
329 declare <vscale x 16 x i8> @llvm.abs.nxv16i8(<vscale x 16 x i8>, i1)
331 declare <vscale x 8 x i16> @llvm.abs.nxv8i16(<vscale x 8 x i16>, i1)
332 declare <vscale x 16 x i16> @llvm.abs.nxv16i16(<vscale x 16 x i16>, i1)
334 declare <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32>, i1)
335 declare <vscale x 8 x i32> @llvm.abs.nxv8i32(<vscale x 8 x i32>, i1)
337 declare <vscale x 2 x i64> @llvm.abs.nxv2i64(<vscale x 2 x i64>, i1)
338 declare <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64>, i1)
340 declare <vscale x 2 x i128> @llvm.abs.nxv2i128(<vscale x 2 x i128>, i1)
341 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: