1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -aarch64-sve-vector-bits-min=256  < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_256
3; RUN: llc -aarch64-sve-vector-bits-min=512  < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512
4; RUN: llc -aarch64-sve-vector-bits-min=2048 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512
5
6target triple = "aarch64-unknown-linux-gnu"
7
8; i8
9
10; Don't use SVE for 64-bit vectors.
11define <4 x i8> @extract_subvector_v8i8(<8 x i8> %op) vscale_range(2,0) #0 {
12; CHECK-LABEL: extract_subvector_v8i8:
13; CHECK:       // %bb.0:
14; CHECK-NEXT:    zip2 v0.8b, v0.8b, v0.8b
15; CHECK-NEXT:    ret
16  %ret = call <4 x i8> @llvm.experimental.vector.extract.v4i8.v8i8(<8 x i8> %op, i64 4)
17  ret <4 x i8> %ret
18}
19
20; Don't use SVE for 128-bit vectors.
21define <8 x i8> @extract_subvector_v16i8(<16 x i8> %op) vscale_range(2,0) #0 {
22; CHECK-LABEL: extract_subvector_v16i8:
23; CHECK:       // %bb.0:
24; CHECK-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
25; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
26; CHECK-NEXT:    ret
27  %ret = call <8 x i8> @llvm.experimental.vector.extract.v8i8.v16i8(<16 x i8> %op, i64 8)
28  ret <8 x i8> %ret
29}
30
31define void @extract_subvector_v32i8(<32 x i8>* %a, <16 x i8>* %b) vscale_range(2,0) #0 {
32; CHECK-LABEL: extract_subvector_v32i8:
33; CHECK:       // %bb.0:
34; CHECK-NEXT:    ptrue p0.b, vl32
35; CHECK-NEXT:    ld1b { z0.b }, p0/z, [x0]
36; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #16
37; CHECK-NEXT:    str q0, [x1]
38; CHECK-NEXT:    ret
39  %op = load <32 x i8>, <32 x i8>* %a
40  %ret = call <16 x i8> @llvm.experimental.vector.extract.v16i8.v32i8(<32 x i8> %op, i64 16)
41  store <16 x i8> %ret, <16 x i8>* %b
42  ret void
43}
44
45define void @extract_subvector_v64i8(<64 x i8>* %a, <32 x i8>* %b) #0 {
46; VBITS_GE_256-LABEL: extract_subvector_v64i8:
47; VBITS_GE_256:       // %bb.0:
48; VBITS_GE_256-NEXT:    mov w8, #32
49; VBITS_GE_256-NEXT:    ptrue p0.b, vl32
50; VBITS_GE_256-NEXT:    ld1b { z0.b }, p0/z, [x0, x8]
51; VBITS_GE_256-NEXT:    st1b { z0.b }, p0, [x1]
52; VBITS_GE_256-NEXT:    ret
53;
54; VBITS_GE_512-LABEL: extract_subvector_v64i8:
55; VBITS_GE_512:       // %bb.0:
56; VBITS_GE_512-NEXT:    ptrue p0.b, vl64
57; VBITS_GE_512-NEXT:    ld1b { z0.b }, p0/z, [x0]
58; VBITS_GE_512-NEXT:    ptrue p0.b, vl32
59; VBITS_GE_512-NEXT:    ext z0.b, z0.b, z0.b, #32
60; VBITS_GE_512-NEXT:    st1b { z0.b }, p0, [x1]
61; VBITS_GE_512-NEXT:    ret
62  %op = load <64 x i8>, <64 x i8>* %a
63  %ret = call <32 x i8> @llvm.experimental.vector.extract.v32i8.v64i8(<64 x i8> %op, i64 32)
64  store <32 x i8> %ret, <32 x i8>* %b
65  ret void
66}
67
68define void @extract_subvector_v128i8(<128 x i8>* %a, <64 x i8>* %b) vscale_range(8,0) #0 {
69; CHECK-LABEL: extract_subvector_v128i8:
70; CHECK:       // %bb.0:
71; CHECK-NEXT:    ptrue p0.b, vl128
72; CHECK-NEXT:    ld1b { z0.b }, p0/z, [x0]
73; CHECK-NEXT:    ptrue p0.b, vl64
74; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #64
75; CHECK-NEXT:    st1b { z0.b }, p0, [x1]
76; CHECK-NEXT:    ret
77  %op = load <128 x i8>, <128 x i8>* %a
78  %ret = call <64 x i8> @llvm.experimental.vector.extract.v64i8.v128i8(<128 x i8> %op, i64 64)
79  store <64 x i8> %ret, <64 x i8>* %b
80  ret void
81}
82
83define void @extract_subvector_v256i8(<256 x i8>* %a, <128 x i8>* %b) vscale_range(16,0) #0 {
84; CHECK-LABEL: extract_subvector_v256i8:
85; CHECK:       // %bb.0:
86; CHECK-NEXT:    ptrue p0.b, vl256
87; CHECK-NEXT:    ld1b { z0.b }, p0/z, [x0]
88; CHECK-NEXT:    ptrue p0.b, vl128
89; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #128
90; CHECK-NEXT:    st1b { z0.b }, p0, [x1]
91; CHECK-NEXT:    ret
92  %op = load <256 x i8>, <256 x i8>* %a
93  %ret = call <128 x i8> @llvm.experimental.vector.extract.v128i8.v256i8(<256 x i8> %op, i64 128)
94  store <128 x i8> %ret, <128 x i8>* %b
95  ret void
96}
97
98; i16
99
100; Don't use SVE for 64-bit vectors.
101define <2 x i16> @extract_subvector_v4i16(<4 x i16> %op) vscale_range(2,0) #0 {
102; CHECK-LABEL: extract_subvector_v4i16:
103; CHECK:       // %bb.0:
104; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
105; CHECK-NEXT:    umov w8, v0.h[2]
106; CHECK-NEXT:    umov w9, v0.h[3]
107; CHECK-NEXT:    fmov s0, w8
108; CHECK-NEXT:    mov v0.s[1], w9
109; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
110; CHECK-NEXT:    ret
111  %ret = call <2 x i16> @llvm.experimental.vector.extract.v2i16.v4i16(<4 x i16> %op, i64 2)
112  ret <2 x i16> %ret
113}
114
115; Don't use SVE for 128-bit vectors.
116define <4 x i16> @extract_subvector_v8i16(<8 x i16> %op) vscale_range(2,0) #0 {
117; CHECK-LABEL: extract_subvector_v8i16:
118; CHECK:       // %bb.0:
119; CHECK-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
120; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
121; CHECK-NEXT:    ret
122  %ret = call <4 x i16> @llvm.experimental.vector.extract.v4i16.v8i16(<8 x i16> %op, i64 4)
123  ret <4 x i16> %ret
124}
125
126define void @extract_subvector_v16i16(<16 x i16>* %a, <8 x i16>* %b) vscale_range(2,0) #0 {
127; CHECK-LABEL: extract_subvector_v16i16:
128; CHECK:       // %bb.0:
129; CHECK-NEXT:    ptrue p0.h, vl16
130; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
131; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #16
132; CHECK-NEXT:    str q0, [x1]
133; CHECK-NEXT:    ret
134  %op = load <16 x i16>, <16 x i16>* %a
135  %ret = call <8 x i16> @llvm.experimental.vector.extract.v8i16.v16i16(<16 x i16> %op, i64 8)
136  store <8 x i16> %ret, <8 x i16>* %b
137  ret void
138}
139
140define void @extract_subvector_v32i16(<32 x i16>* %a, <16 x i16>* %b) #0 {
141; VBITS_GE_256-LABEL: extract_subvector_v32i16:
142; VBITS_GE_256:       // %bb.0:
143; VBITS_GE_256-NEXT:    mov x8, #16
144; VBITS_GE_256-NEXT:    ptrue p0.h, vl16
145; VBITS_GE_256-NEXT:    ld1h { z0.h }, p0/z, [x0, x8, lsl #1]
146; VBITS_GE_256-NEXT:    st1h { z0.h }, p0, [x1]
147; VBITS_GE_256-NEXT:    ret
148;
149; VBITS_GE_512-LABEL: extract_subvector_v32i16:
150; VBITS_GE_512:       // %bb.0:
151; VBITS_GE_512-NEXT:    ptrue p0.h, vl32
152; VBITS_GE_512-NEXT:    ld1h { z0.h }, p0/z, [x0]
153; VBITS_GE_512-NEXT:    ptrue p0.h, vl16
154; VBITS_GE_512-NEXT:    ext z0.b, z0.b, z0.b, #32
155; VBITS_GE_512-NEXT:    st1h { z0.h }, p0, [x1]
156; VBITS_GE_512-NEXT:    ret
157  %op = load <32 x i16>, <32 x i16>* %a
158  %ret = call <16 x i16> @llvm.experimental.vector.extract.v16i16.v32i16(<32 x i16> %op, i64 16)
159  store <16 x i16> %ret, <16 x i16>* %b
160  ret void
161}
162
163define void @extract_subvector_v64i16(<64 x i16>* %a, <32 x i16>* %b) vscale_range(8,0) #0 {
164; CHECK-LABEL: extract_subvector_v64i16:
165; CHECK:       // %bb.0:
166; CHECK-NEXT:    ptrue p0.h, vl64
167; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
168; CHECK-NEXT:    ptrue p0.h, vl32
169; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #64
170; CHECK-NEXT:    st1h { z0.h }, p0, [x1]
171; CHECK-NEXT:    ret
172  %op = load <64 x i16>, <64 x i16>* %a
173  %ret = call <32 x i16> @llvm.experimental.vector.extract.v32i16.v64i16(<64 x i16> %op, i64 32)
174  store <32 x i16> %ret, <32 x i16>* %b
175  ret void
176}
177
178define void @extract_subvector_v128i16(<128 x i16>* %a, <64 x i16>* %b) vscale_range(16,0) #0 {
179; CHECK-LABEL: extract_subvector_v128i16:
180; CHECK:       // %bb.0:
181; CHECK-NEXT:    ptrue p0.h, vl128
182; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
183; CHECK-NEXT:    ptrue p0.h, vl64
184; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #128
185; CHECK-NEXT:    st1h { z0.h }, p0, [x1]
186; CHECK-NEXT:    ret
187  %op = load <128 x i16>, <128 x i16>* %a
188  %ret = call <64 x i16> @llvm.experimental.vector.extract.v64i16.v128i16(<128 x i16> %op, i64 64)
189  store <64 x i16> %ret, <64 x i16>* %b
190  ret void
191}
192
193; i32
194
195; Don't use SVE for 64-bit vectors.
196define <1 x i32> @extract_subvector_v2i32(<2 x i32> %op) vscale_range(2,0) #0 {
197; CHECK-LABEL: extract_subvector_v2i32:
198; CHECK:       // %bb.0:
199; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
200; CHECK-NEXT:    dup v0.2s, v0.s[1]
201; CHECK-NEXT:    ret
202  %ret = call <1 x i32> @llvm.experimental.vector.extract.v1i32.v2i32(<2 x i32> %op, i64 1)
203  ret <1 x i32> %ret
204}
205
206; Don't use SVE for 128-bit vectors.
207define <2 x i32> @extract_subvector_v4i32(<4 x i32> %op) vscale_range(2,0) #0 {
208; CHECK-LABEL: extract_subvector_v4i32:
209; CHECK:       // %bb.0:
210; CHECK-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
211; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
212; CHECK-NEXT:    ret
213  %ret = call <2 x i32> @llvm.experimental.vector.extract.v2i32.v4i32(<4 x i32> %op, i64 2)
214  ret <2 x i32> %ret
215}
216
217define void @extract_subvector_v8i32(<8 x i32>* %a, <4 x i32>* %b) vscale_range(2,0) #0 {
218; CHECK-LABEL: extract_subvector_v8i32:
219; CHECK:       // %bb.0:
220; CHECK-NEXT:    ptrue p0.s, vl8
221; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
222; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #16
223; CHECK-NEXT:    str q0, [x1]
224; CHECK-NEXT:    ret
225  %op = load <8 x i32>, <8 x i32>* %a
226  %ret = call <4 x i32> @llvm.experimental.vector.extract.v4i32.v8i32(<8 x i32> %op, i64 4)
227  store <4 x i32> %ret, <4 x i32>* %b
228  ret void
229}
230
231define void @extract_subvector_v16i32(<16 x i32>* %a, <8 x i32>* %b) #0 {
232; VBITS_GE_256-LABEL: extract_subvector_v16i32:
233; VBITS_GE_256:       // %bb.0:
234; VBITS_GE_256-NEXT:    mov x8, #8
235; VBITS_GE_256-NEXT:    ptrue p0.s, vl8
236; VBITS_GE_256-NEXT:    ld1w { z0.s }, p0/z, [x0, x8, lsl #2]
237; VBITS_GE_256-NEXT:    st1w { z0.s }, p0, [x1]
238; VBITS_GE_256-NEXT:    ret
239;
240; VBITS_GE_512-LABEL: extract_subvector_v16i32:
241; VBITS_GE_512:       // %bb.0:
242; VBITS_GE_512-NEXT:    ptrue p0.s, vl16
243; VBITS_GE_512-NEXT:    ld1w { z0.s }, p0/z, [x0]
244; VBITS_GE_512-NEXT:    ptrue p0.s, vl8
245; VBITS_GE_512-NEXT:    ext z0.b, z0.b, z0.b, #32
246; VBITS_GE_512-NEXT:    st1w { z0.s }, p0, [x1]
247; VBITS_GE_512-NEXT:    ret
248  %op = load <16 x i32>, <16 x i32>* %a
249  %ret = call <8 x i32> @llvm.experimental.vector.extract.v8i32.v16i32(<16 x i32> %op, i64 8)
250  store <8 x i32> %ret, <8 x i32>* %b
251  ret void
252}
253
254define void @extract_subvector_v32i32(<32 x i32>* %a, <16 x i32>* %b) vscale_range(8,0) #0 {
255; CHECK-LABEL: extract_subvector_v32i32:
256; CHECK:       // %bb.0:
257; CHECK-NEXT:    ptrue p0.s, vl32
258; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
259; CHECK-NEXT:    ptrue p0.s, vl16
260; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #64
261; CHECK-NEXT:    st1w { z0.s }, p0, [x1]
262; CHECK-NEXT:    ret
263  %op = load <32 x i32>, <32 x i32>* %a
264  %ret = call <16 x i32> @llvm.experimental.vector.extract.v16i32.v32i32(<32 x i32> %op, i64 16)
265  store <16 x i32> %ret, <16 x i32>* %b
266  ret void
267}
268
269define void @extract_subvector_v64i32(<64 x i32>* %a, <32 x i32>* %b) vscale_range(16,0) #0 {
270; CHECK-LABEL: extract_subvector_v64i32:
271; CHECK:       // %bb.0:
272; CHECK-NEXT:    ptrue p0.s, vl64
273; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
274; CHECK-NEXT:    ptrue p0.s, vl32
275; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #128
276; CHECK-NEXT:    st1w { z0.s }, p0, [x1]
277; CHECK-NEXT:    ret
278  %op = load <64 x i32>, <64 x i32>* %a
279  %ret = call <32 x i32> @llvm.experimental.vector.extract.v32i32.v64i32(<64 x i32> %op, i64 32)
280  store <32 x i32> %ret, <32 x i32>* %b
281  ret void
282}
283
284; i64
285
286; Don't use SVE for 128-bit vectors.
287define <1 x i64> @extract_subvector_v2i64(<2 x i64> %op) vscale_range(2,0) #0 {
288; CHECK-LABEL: extract_subvector_v2i64:
289; CHECK:       // %bb.0:
290; CHECK-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
291; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
292; CHECK-NEXT:    ret
293  %ret = call <1 x i64> @llvm.experimental.vector.extract.v1i64.v2i64(<2 x i64> %op, i64 1)
294  ret <1 x i64> %ret
295}
296
297define void @extract_subvector_v4i64(<4 x i64>* %a, <2 x i64>* %b) vscale_range(2,0) #0 {
298; CHECK-LABEL: extract_subvector_v4i64:
299; CHECK:       // %bb.0:
300; CHECK-NEXT:    ptrue p0.d, vl4
301; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0]
302; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #16
303; CHECK-NEXT:    str q0, [x1]
304; CHECK-NEXT:    ret
305  %op = load <4 x i64>, <4 x i64>* %a
306  %ret = call <2 x i64> @llvm.experimental.vector.extract.v2i64.v4i64(<4 x i64> %op, i64 2)
307  store <2 x i64> %ret, <2 x i64>* %b
308  ret void
309}
310
311define void @extract_subvector_v8i64(<8 x i64>* %a, <4 x i64>* %b) vscale_range(2,0) #0 {
312; CHECK-LABEL: extract_subvector_v8i64:
313; CHECK:       // %bb.0:
314; CHECK-NEXT:    mov x8, #4
315; CHECK-NEXT:    ptrue p0.d, vl4
316; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0, x8, lsl #3]
317; CHECK-NEXT:    st1d { z0.d }, p0, [x1]
318; CHECK-NEXT:    ret
319  %op = load <8 x i64>, <8 x i64>* %a
320  %ret = call <4 x i64> @llvm.experimental.vector.extract.v4i64.v8i64(<8 x i64> %op, i64 4)
321  store <4 x i64> %ret, <4 x i64>* %b
322  ret void
323}
324
325define void @extract_subvector_v16i64(<16 x i64>* %a, <8 x i64>* %b) #0 {
326; VBITS_GE_256-LABEL: extract_subvector_v16i64:
327; VBITS_GE_256:       // %bb.0:
328; VBITS_GE_256-NEXT:    mov x8, #8
329; VBITS_GE_256-NEXT:    mov x9, #12
330; VBITS_GE_256-NEXT:    ptrue p0.d, vl4
331; VBITS_GE_256-NEXT:    ld1d { z0.d }, p0/z, [x0, x8, lsl #3]
332; VBITS_GE_256-NEXT:    ld1d { z1.d }, p0/z, [x0, x9, lsl #3]
333; VBITS_GE_256-NEXT:    mov x8, #4
334; VBITS_GE_256-NEXT:    st1d { z1.d }, p0, [x1, x8, lsl #3]
335; VBITS_GE_256-NEXT:    st1d { z0.d }, p0, [x1]
336; VBITS_GE_256-NEXT:    ret
337  %op = load <16 x i64>, <16 x i64>* %a
338  %ret = call <8 x i64> @llvm.experimental.vector.extract.v8i64.v16i64(<16 x i64> %op, i64 8)
339  store <8 x i64> %ret, <8 x i64>* %b
340  ret void
341}
342
343define void @extract_subvector_v32i64(<32 x i64>* %a, <16 x i64>* %b) vscale_range(8,0) #0 {
344; CHECK-LABEL: extract_subvector_v32i64:
345; CHECK:       // %bb.0:
346; CHECK-NEXT:    mov x8, #16
347; CHECK-NEXT:    ptrue p0.d, vl16
348; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0, x8, lsl #3]
349; CHECK-NEXT:    st1d { z0.d }, p0, [x1]
350; CHECK-NEXT:    ret
351  %op = load <32 x i64>, <32 x i64>* %a
352  %ret = call <16 x i64> @llvm.experimental.vector.extract.v16i64.v32i64(<32 x i64> %op, i64 16)
353  store <16 x i64> %ret, <16 x i64>* %b
354  ret void
355}
356
357; f16
358
359; Don't use SVE for 64-bit vectors.
360define <2 x half> @extract_subvector_v4f16(<4 x half> %op) vscale_range(16,0) #0 {
361; CHECK-LABEL: extract_subvector_v4f16:
362; CHECK:       // %bb.0:
363; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
364; CHECK-NEXT:    dup v0.2s, v0.s[1]
365; CHECK-NEXT:    ret
366  %ret = call <2 x half> @llvm.experimental.vector.extract.v2f16.v4f16(<4 x half> %op, i64 2)
367  ret <2 x half> %ret
368}
369
370; Don't use SVE for 128-bit vectors.
371define <4 x half> @extract_subvector_v8f16(<8 x half> %op) vscale_range(2,0) #0 {
372; CHECK-LABEL: extract_subvector_v8f16:
373; CHECK:       // %bb.0:
374; CHECK-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
375; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
376; CHECK-NEXT:    ret
377  %ret = call <4 x half> @llvm.experimental.vector.extract.v4f16.v8f16(<8 x half> %op, i64 4)
378  ret <4 x half> %ret
379}
380
381define void @extract_subvector_v16f16(<16 x half>* %a, <8 x half>* %b) vscale_range(2,0) #0 {
382; CHECK-LABEL: extract_subvector_v16f16:
383; CHECK:       // %bb.0:
384; CHECK-NEXT:    ptrue p0.h, vl16
385; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
386; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #16
387; CHECK-NEXT:    str q0, [x1]
388; CHECK-NEXT:    ret
389  %op = load <16 x half>, <16 x half>* %a
390  %ret = call <8 x half> @llvm.experimental.vector.extract.v8f16.v16f16(<16 x half> %op, i64 8)
391  store <8 x half> %ret, <8 x half>* %b
392  ret void
393}
394
395define void @extract_subvector_v32f16(<32 x half>* %a, <16 x half>* %b) #0 {
396; VBITS_GE_256-LABEL: extract_subvector_v32f16:
397; VBITS_GE_256:       // %bb.0:
398; VBITS_GE_256-NEXT:    mov x8, #16
399; VBITS_GE_256-NEXT:    ptrue p0.h, vl16
400; VBITS_GE_256-NEXT:    ld1h { z0.h }, p0/z, [x0, x8, lsl #1]
401; VBITS_GE_256-NEXT:    st1h { z0.h }, p0, [x1]
402; VBITS_GE_256-NEXT:    ret
403;
404; VBITS_GE_512-LABEL: extract_subvector_v32f16:
405; VBITS_GE_512:       // %bb.0:
406; VBITS_GE_512-NEXT:    ptrue p0.h, vl32
407; VBITS_GE_512-NEXT:    ld1h { z0.h }, p0/z, [x0]
408; VBITS_GE_512-NEXT:    ptrue p0.h, vl16
409; VBITS_GE_512-NEXT:    ext z0.b, z0.b, z0.b, #32
410; VBITS_GE_512-NEXT:    st1h { z0.h }, p0, [x1]
411; VBITS_GE_512-NEXT:    ret
412  %op = load <32 x half>, <32 x half>* %a
413  %ret = call <16 x half> @llvm.experimental.vector.extract.v16f16.v32f16(<32 x half> %op, i64 16)
414  store <16 x half> %ret, <16 x half>* %b
415  ret void
416}
417
418define void @extract_subvector_v64f16(<64 x half>* %a, <32 x half>* %b) vscale_range(8,0) #0 {
419; CHECK-LABEL: extract_subvector_v64f16:
420; CHECK:       // %bb.0:
421; CHECK-NEXT:    ptrue p0.h, vl64
422; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
423; CHECK-NEXT:    ptrue p0.h, vl32
424; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #64
425; CHECK-NEXT:    st1h { z0.h }, p0, [x1]
426; CHECK-NEXT:    ret
427  %op = load <64 x half>, <64 x half>* %a
428  %ret = call <32 x half> @llvm.experimental.vector.extract.v32f16.v64f16(<64 x half> %op, i64 32)
429  store <32 x half> %ret, <32 x half>* %b
430  ret void
431}
432
433define void @extract_subvector_v128f16(<128 x half>* %a, <64 x half>* %b) vscale_range(16,0) #0 {
434; CHECK-LABEL: extract_subvector_v128f16:
435; CHECK:       // %bb.0:
436; CHECK-NEXT:    ptrue p0.h, vl128
437; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
438; CHECK-NEXT:    ptrue p0.h, vl64
439; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #128
440; CHECK-NEXT:    st1h { z0.h }, p0, [x1]
441; CHECK-NEXT:    ret
442  %op = load <128 x half>, <128 x half>* %a
443  %ret = call <64 x half> @llvm.experimental.vector.extract.v64f16.v128f16(<128 x half> %op, i64 64)
444  store <64 x half> %ret, <64 x half>* %b
445  ret void
446}
447
448; f32
449
450; Don't use SVE for 64-bit vectors.
451define <1 x float> @extract_subvector_v2f32(<2 x float> %op) vscale_range(2,0) #0 {
452; CHECK-LABEL: extract_subvector_v2f32:
453; CHECK:       // %bb.0:
454; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
455; CHECK-NEXT:    dup v0.2s, v0.s[1]
456; CHECK-NEXT:    ret
457  %ret = call <1 x float> @llvm.experimental.vector.extract.v1f32.v2f32(<2 x float> %op, i64 1)
458  ret <1 x float> %ret
459}
460
461; Don't use SVE for 128-bit vectors.
462define <2 x float> @extract_subvector_v4f32(<4 x float> %op) vscale_range(2,0) #0 {
463; CHECK-LABEL: extract_subvector_v4f32:
464; CHECK:       // %bb.0:
465; CHECK-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
466; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
467; CHECK-NEXT:    ret
468  %ret = call <2 x float> @llvm.experimental.vector.extract.v2f32.v4f32(<4 x float> %op, i64 2)
469  ret <2 x float> %ret
470}
471
472define void @extract_subvector_v8f32(<8 x float>* %a, <4 x float>* %b) vscale_range(2,0) #0 {
473; CHECK-LABEL: extract_subvector_v8f32:
474; CHECK:       // %bb.0:
475; CHECK-NEXT:    ptrue p0.s, vl8
476; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
477; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #16
478; CHECK-NEXT:    str q0, [x1]
479; CHECK-NEXT:    ret
480  %op = load <8 x float>, <8 x float>* %a
481  %ret = call <4 x float> @llvm.experimental.vector.extract.v4f32.v8f32(<8 x float> %op, i64 4)
482  store <4 x float> %ret, <4 x float>* %b
483  ret void
484}
485
486define void @extract_subvector_v16f32(<16 x float>* %a, <8 x float>* %b) #0 {
487; VBITS_GE_256-LABEL: extract_subvector_v16f32:
488; VBITS_GE_256:       // %bb.0:
489; VBITS_GE_256-NEXT:    mov x8, #8
490; VBITS_GE_256-NEXT:    ptrue p0.s, vl8
491; VBITS_GE_256-NEXT:    ld1w { z0.s }, p0/z, [x0, x8, lsl #2]
492; VBITS_GE_256-NEXT:    st1w { z0.s }, p0, [x1]
493; VBITS_GE_256-NEXT:    ret
494;
495; VBITS_GE_512-LABEL: extract_subvector_v16f32:
496; VBITS_GE_512:       // %bb.0:
497; VBITS_GE_512-NEXT:    ptrue p0.s, vl16
498; VBITS_GE_512-NEXT:    ld1w { z0.s }, p0/z, [x0]
499; VBITS_GE_512-NEXT:    ptrue p0.s, vl8
500; VBITS_GE_512-NEXT:    ext z0.b, z0.b, z0.b, #32
501; VBITS_GE_512-NEXT:    st1w { z0.s }, p0, [x1]
502; VBITS_GE_512-NEXT:    ret
503  %op = load <16 x float>, <16 x float>* %a
504  %ret = call <8 x float> @llvm.experimental.vector.extract.v8f32.v16f32(<16 x float> %op, i64 8)
505  store <8 x float> %ret, <8 x float>* %b
506  ret void
507}
508
509define void @extract_subvector_v32f32(<32 x float>* %a, <16 x float>* %b) vscale_range(8,0) #0 {
510; CHECK-LABEL: extract_subvector_v32f32:
511; CHECK:       // %bb.0:
512; CHECK-NEXT:    ptrue p0.s, vl32
513; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
514; CHECK-NEXT:    ptrue p0.s, vl16
515; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #64
516; CHECK-NEXT:    st1w { z0.s }, p0, [x1]
517; CHECK-NEXT:    ret
518  %op = load <32 x float>, <32 x float>* %a
519  %ret = call <16 x float> @llvm.experimental.vector.extract.v16f32.v32f32(<32 x float> %op, i64 16)
520  store <16 x float> %ret, <16 x float>* %b
521  ret void
522}
523
524define void @extract_subvector_v64f32(<64 x float>* %a, <32 x float>* %b) vscale_range(16,0) #0 {
525; CHECK-LABEL: extract_subvector_v64f32:
526; CHECK:       // %bb.0:
527; CHECK-NEXT:    ptrue p0.s, vl64
528; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
529; CHECK-NEXT:    ptrue p0.s, vl32
530; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #128
531; CHECK-NEXT:    st1w { z0.s }, p0, [x1]
532; CHECK-NEXT:    ret
533  %op = load <64 x float>, <64 x float>* %a
534  %ret = call <32 x float> @llvm.experimental.vector.extract.v32f32.v64f32(<64 x float> %op, i64 32)
535  store <32 x float> %ret, <32 x float>* %b
536  ret void
537}
538
539; f64
540
541; Don't use SVE for 128-bit vectors.
542define <1 x double> @extract_subvector_v2f64(<2 x double> %op) vscale_range(2,0) #0 {
543; CHECK-LABEL: extract_subvector_v2f64:
544; CHECK:       // %bb.0:
545; CHECK-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
546; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
547; CHECK-NEXT:    ret
548  %ret = call <1 x double> @llvm.experimental.vector.extract.v1f64.v2f64(<2 x double> %op, i64 1)
549  ret <1 x double> %ret
550}
551
552define void @extract_subvector_v4f64(<4 x double>* %a, <2 x double>* %b) vscale_range(2,0) #0 {
553; CHECK-LABEL: extract_subvector_v4f64:
554; CHECK:       // %bb.0:
555; CHECK-NEXT:    ptrue p0.d, vl4
556; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0]
557; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #16
558; CHECK-NEXT:    str q0, [x1]
559; CHECK-NEXT:    ret
560  %op = load <4 x double>, <4 x double>* %a
561  %ret = call <2 x double> @llvm.experimental.vector.extract.v2f64.v4f64(<4 x double> %op, i64 2)
562  store <2 x double> %ret, <2 x double>* %b
563  ret void
564}
565
566define void @extract_subvector_v8f64(<8 x double>* %a, <4 x double>* %b) #0 {
567; VBITS_GE_256-LABEL: extract_subvector_v8f64:
568; VBITS_GE_256:       // %bb.0:
569; VBITS_GE_256-NEXT:    mov x8, #4
570; VBITS_GE_256-NEXT:    ptrue p0.d, vl4
571; VBITS_GE_256-NEXT:    ld1d { z0.d }, p0/z, [x0, x8, lsl #3]
572; VBITS_GE_256-NEXT:    st1d { z0.d }, p0, [x1]
573; VBITS_GE_256-NEXT:    ret
574;
575; VBITS_GE_512-LABEL: extract_subvector_v8f64:
576; VBITS_GE_512:       // %bb.0:
577; VBITS_GE_512-NEXT:    ptrue p0.d, vl8
578; VBITS_GE_512-NEXT:    ld1d { z0.d }, p0/z, [x0]
579; VBITS_GE_512-NEXT:    ptrue p0.d, vl4
580; VBITS_GE_512-NEXT:    ext z0.b, z0.b, z0.b, #32
581; VBITS_GE_512-NEXT:    st1d { z0.d }, p0, [x1]
582; VBITS_GE_512-NEXT:    ret
583  %op = load <8 x double>, <8 x double>* %a
584  %ret = call <4 x double> @llvm.experimental.vector.extract.v4f64.v8f64(<8 x double> %op, i64 4)
585  store <4 x double> %ret, <4 x double>* %b
586  ret void
587}
588
589define void @extract_subvector_v16f64(<16 x double>* %a, <8 x double>* %b) vscale_range(8,0) #0 {
590; CHECK-LABEL: extract_subvector_v16f64:
591; CHECK:       // %bb.0:
592; CHECK-NEXT:    ptrue p0.d, vl16
593; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0]
594; CHECK-NEXT:    ptrue p0.d, vl8
595; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #64
596; CHECK-NEXT:    st1d { z0.d }, p0, [x1]
597; CHECK-NEXT:    ret
598  %op = load <16 x double>, <16 x double>* %a
599  %ret = call <8 x double> @llvm.experimental.vector.extract.v8f64.v16f64(<16 x double> %op, i64 8)
600  store <8 x double> %ret, <8 x double>* %b
601  ret void
602}
603
604define void @extract_subvector_v32f64(<32 x double>* %a, <16 x double>* %b) vscale_range(16,0) #0 {
605; CHECK-LABEL: extract_subvector_v32f64:
606; CHECK:       // %bb.0:
607; CHECK-NEXT:    ptrue p0.d, vl32
608; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0]
609; CHECK-NEXT:    ptrue p0.d, vl16
610; CHECK-NEXT:    ext z0.b, z0.b, z0.b, #128
611; CHECK-NEXT:    st1d { z0.d }, p0, [x1]
612; CHECK-NEXT:    ret
613  %op = load <32 x double>, <32 x double>* %a
614  %ret = call <16 x double> @llvm.experimental.vector.extract.v16f64.v32f64(<32 x double> %op, i64 16)
615  store <16 x double> %ret, <16 x double>* %b
616  ret void
617}
618
619declare <4 x i8> @llvm.experimental.vector.extract.v4i8.v8i8(<8 x i8>, i64)
620declare <8 x i8> @llvm.experimental.vector.extract.v8i8.v16i8(<16 x i8>, i64)
621declare <16 x i8> @llvm.experimental.vector.extract.v16i8.v32i8(<32 x i8>, i64)
622declare <32 x i8> @llvm.experimental.vector.extract.v32i8.v64i8(<64 x i8>, i64)
623declare <64 x i8> @llvm.experimental.vector.extract.v64i8.v128i8(<128 x i8>, i64)
624declare <128 x i8> @llvm.experimental.vector.extract.v128i8.v256i8(<256 x i8>, i64)
625
626declare <2 x i16> @llvm.experimental.vector.extract.v2i16.v4i16(<4 x i16>, i64)
627declare <4 x i16> @llvm.experimental.vector.extract.v4i16.v8i16(<8 x i16>, i64)
628declare <8 x i16> @llvm.experimental.vector.extract.v8i16.v16i16(<16 x i16>, i64)
629declare <16 x i16> @llvm.experimental.vector.extract.v16i16.v32i16(<32 x i16>, i64)
630declare <32 x i16> @llvm.experimental.vector.extract.v32i16.v64i16(<64 x i16>, i64)
631declare <64 x i16> @llvm.experimental.vector.extract.v64i16.v128i16(<128 x i16>, i64)
632
633declare <1 x i32> @llvm.experimental.vector.extract.v1i32.v2i32(<2 x i32>, i64)
634declare <2 x i32> @llvm.experimental.vector.extract.v2i32.v4i32(<4 x i32>, i64)
635declare <4 x i32> @llvm.experimental.vector.extract.v4i32.v8i32(<8 x i32>, i64)
636declare <8 x i32> @llvm.experimental.vector.extract.v8i32.v16i32(<16 x i32>, i64)
637declare <16 x i32> @llvm.experimental.vector.extract.v16i32.v32i32(<32 x i32>, i64)
638declare <32 x i32> @llvm.experimental.vector.extract.v32i32.v64i32(<64 x i32>, i64)
639
640declare <1 x i64> @llvm.experimental.vector.extract.v1i64.v2i64(<2 x i64>, i64)
641declare <2 x i64> @llvm.experimental.vector.extract.v2i64.v4i64(<4 x i64>, i64)
642declare <4 x i64> @llvm.experimental.vector.extract.v4i64.v8i64(<8 x i64>, i64)
643declare <8 x i64> @llvm.experimental.vector.extract.v8i64.v16i64(<16 x i64>, i64)
644declare <16 x i64> @llvm.experimental.vector.extract.v16i64.v32i64(<32 x i64>, i64)
645
646declare <2 x half> @llvm.experimental.vector.extract.v2f16.v4f16(<4 x half>, i64)
647declare <4 x half> @llvm.experimental.vector.extract.v4f16.v8f16(<8 x half>, i64)
648declare <8 x half> @llvm.experimental.vector.extract.v8f16.v16f16(<16 x half>, i64)
649declare <16 x half> @llvm.experimental.vector.extract.v16f16.v32f16(<32 x half>, i64)
650declare <32 x half> @llvm.experimental.vector.extract.v32f16.v64f16(<64 x half>, i64)
651declare <64 x half> @llvm.experimental.vector.extract.v64f16.v128f16(<128 x half>, i64)
652
653declare <1 x float> @llvm.experimental.vector.extract.v1f32.v2f32(<2 x float>, i64)
654declare <2 x float> @llvm.experimental.vector.extract.v2f32.v4f32(<4 x float>, i64)
655declare <4 x float> @llvm.experimental.vector.extract.v4f32.v8f32(<8 x float>, i64)
656declare <8 x float> @llvm.experimental.vector.extract.v8f32.v16f32(<16 x float>, i64)
657declare <16 x float> @llvm.experimental.vector.extract.v16f32.v32f32(<32 x float>, i64)
658declare <32 x float> @llvm.experimental.vector.extract.v32f32.v64f32(<64 x float>, i64)
659
660declare <1 x double> @llvm.experimental.vector.extract.v1f64.v2f64(<2 x double>, i64)
661declare <2 x double> @llvm.experimental.vector.extract.v2f64.v4f64(<4 x double>, i64)
662declare <4 x double> @llvm.experimental.vector.extract.v4f64.v8f64(<8 x double>, i64)
663declare <8 x double> @llvm.experimental.vector.extract.v8f64.v16f64(<16 x double>, i64)
664declare <16 x double> @llvm.experimental.vector.extract.v16f64.v32f64(<32 x double>, i64)
665
666attributes #0 = { "target-features"="+sve" }
667