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