519 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -aarch64-sve-vector-bits-min=256 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_2563; RUN: llc -aarch64-sve-vector-bits-min=512 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_5124; RUN: llc -aarch64-sve-vector-bits-min=2048 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_5125 6target triple = "aarch64-unknown-linux-gnu"7 8;9; truncate i16 -> i810;11 12define <16 x i8> @trunc_v16i16_v16i8(ptr %in) vscale_range(2,0) #0 {13; CHECK-LABEL: trunc_v16i16_v16i8:14; CHECK: // %bb.0:15; CHECK-NEXT: ptrue p0.h, vl1616; CHECK-NEXT: ld1h { z0.h }, p0/z, [x0]17; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b18; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z019; CHECK-NEXT: ret20 %a = load <16 x i16>, ptr %in21 %b = trunc <16 x i16> %a to <16 x i8>22 ret <16 x i8> %b23}24 25; NOTE: Extra 'add' is to prevent the truncate being combined with the store.26define void @trunc_v32i16_v32i8(ptr %in, ptr %out) #0 {27; VBITS_GE_256-LABEL: trunc_v32i16_v32i8:28; VBITS_GE_256: // %bb.0:29; VBITS_GE_256-NEXT: ptrue p0.h, vl1630; VBITS_GE_256-NEXT: mov x8, #16 // =0x1031; VBITS_GE_256-NEXT: ld1h { z0.h }, p0/z, [x0, x8, lsl #1]32; VBITS_GE_256-NEXT: ld1h { z1.h }, p0/z, [x0]33; VBITS_GE_256-NEXT: ptrue p0.b, vl1634; VBITS_GE_256-NEXT: uzp1 z0.b, z0.b, z0.b35; VBITS_GE_256-NEXT: uzp1 z1.b, z1.b, z1.b36; VBITS_GE_256-NEXT: splice z1.b, p0, z1.b, z0.b37; VBITS_GE_256-NEXT: ptrue p0.b, vl3238; VBITS_GE_256-NEXT: add z0.b, z1.b, z1.b39; VBITS_GE_256-NEXT: st1b { z0.b }, p0, [x1]40; VBITS_GE_256-NEXT: ret41;42; VBITS_GE_512-LABEL: trunc_v32i16_v32i8:43; VBITS_GE_512: // %bb.0:44; VBITS_GE_512-NEXT: ptrue p0.h, vl3245; VBITS_GE_512-NEXT: ld1h { z0.h }, p0/z, [x0]46; VBITS_GE_512-NEXT: ptrue p0.b, vl3247; VBITS_GE_512-NEXT: uzp1 z0.b, z0.b, z0.b48; VBITS_GE_512-NEXT: add z0.b, z0.b, z0.b49; VBITS_GE_512-NEXT: st1b { z0.b }, p0, [x1]50; VBITS_GE_512-NEXT: ret51 %a = load <32 x i16>, ptr %in52 %b = trunc <32 x i16> %a to <32 x i8>53 %c = add <32 x i8> %b, %b54 store <32 x i8> %c, ptr %out55 ret void56}57 58; NOTE: Extra 'add' is to prevent the truncate being combined with the store.59define void @trunc_v64i16_v64i8(ptr %in, ptr %out) vscale_range(8,0) #0 {60; CHECK-LABEL: trunc_v64i16_v64i8:61; CHECK: // %bb.0:62; CHECK-NEXT: ptrue p0.h, vl6463; CHECK-NEXT: ld1h { z0.h }, p0/z, [x0]64; CHECK-NEXT: ptrue p0.b, vl6465; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b66; CHECK-NEXT: add z0.b, z0.b, z0.b67; CHECK-NEXT: st1b { z0.b }, p0, [x1]68; CHECK-NEXT: ret69 %a = load <64 x i16>, ptr %in70 %b = trunc <64 x i16> %a to <64 x i8>71 %c = add <64 x i8> %b, %b72 store <64 x i8> %c, ptr %out73 ret void74}75 76; NOTE: Extra 'add' is to prevent the truncate being combined with the store.77define void @trunc_v128i16_v128i8(ptr %in, ptr %out) vscale_range(16,0) #0 {78; CHECK-LABEL: trunc_v128i16_v128i8:79; CHECK: // %bb.0:80; CHECK-NEXT: ptrue p0.h, vl12881; CHECK-NEXT: ld1h { z0.h }, p0/z, [x0]82; CHECK-NEXT: ptrue p0.b, vl12883; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b84; CHECK-NEXT: add z0.b, z0.b, z0.b85; CHECK-NEXT: st1b { z0.b }, p0, [x1]86; CHECK-NEXT: ret87 %a = load <128 x i16>, ptr %in88 %b = trunc <128 x i16> %a to <128 x i8>89 %c = add <128 x i8> %b, %b90 store <128 x i8> %c, ptr %out91 ret void92}93 94;95; truncate i32 -> i896;97 98define <8 x i8> @trunc_v8i32_v8i8(ptr %in) vscale_range(2,0) #0 {99; CHECK-LABEL: trunc_v8i32_v8i8:100; CHECK: // %bb.0:101; CHECK-NEXT: ptrue p0.s, vl8102; CHECK-NEXT: ld1w { z0.s }, p0/z, [x0]103; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h104; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b105; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0106; CHECK-NEXT: ret107 %a = load <8 x i32>, ptr %in108 %b = trunc <8 x i32> %a to <8 x i8>109 ret <8 x i8> %b110}111 112define <16 x i8> @trunc_v16i32_v16i8(ptr %in) #0 {113; VBITS_GE_256-LABEL: trunc_v16i32_v16i8:114; VBITS_GE_256: // %bb.0:115; VBITS_GE_256-NEXT: ptrue p0.s, vl8116; VBITS_GE_256-NEXT: mov x8, #8 // =0x8117; VBITS_GE_256-NEXT: ld1w { z0.s }, p0/z, [x0, x8, lsl #2]118; VBITS_GE_256-NEXT: ld1w { z1.s }, p0/z, [x0]119; VBITS_GE_256-NEXT: uzp1 z0.h, z0.h, z0.h120; VBITS_GE_256-NEXT: uzp1 z1.h, z1.h, z1.h121; VBITS_GE_256-NEXT: uzp1 z2.b, z0.b, z0.b122; VBITS_GE_256-NEXT: uzp1 z0.b, z1.b, z1.b123; VBITS_GE_256-NEXT: mov v0.d[1], v2.d[0]124; VBITS_GE_256-NEXT: // kill: def $q0 killed $q0 killed $z0125; VBITS_GE_256-NEXT: ret126;127; VBITS_GE_512-LABEL: trunc_v16i32_v16i8:128; VBITS_GE_512: // %bb.0:129; VBITS_GE_512-NEXT: ptrue p0.s, vl16130; VBITS_GE_512-NEXT: ld1w { z0.s }, p0/z, [x0]131; VBITS_GE_512-NEXT: uzp1 z0.h, z0.h, z0.h132; VBITS_GE_512-NEXT: uzp1 z0.b, z0.b, z0.b133; VBITS_GE_512-NEXT: // kill: def $q0 killed $q0 killed $z0134; VBITS_GE_512-NEXT: ret135 %a = load <16 x i32>, ptr %in136 %b = trunc <16 x i32> %a to <16 x i8>137 ret <16 x i8> %b138}139 140; NOTE: Extra 'add' is to prevent the truncate being combined with the store.141define void @trunc_v32i32_v32i8(ptr %in, ptr %out) vscale_range(8,0) #0 {142; CHECK-LABEL: trunc_v32i32_v32i8:143; CHECK: // %bb.0:144; CHECK-NEXT: ptrue p0.s, vl32145; CHECK-NEXT: ld1w { z0.s }, p0/z, [x0]146; CHECK-NEXT: ptrue p0.b, vl32147; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h148; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b149; CHECK-NEXT: add z0.b, z0.b, z0.b150; CHECK-NEXT: st1b { z0.b }, p0, [x1]151; CHECK-NEXT: ret152 %a = load <32 x i32>, ptr %in153 %b = trunc <32 x i32> %a to <32 x i8>154 %c = add <32 x i8> %b, %b155 store <32 x i8> %c, ptr %out156 ret void157}158 159; NOTE: Extra 'add' is to prevent the truncate being combined with the store.160define void @trunc_v64i32_v64i8(ptr %in, ptr %out) vscale_range(16,0) #0 {161; CHECK-LABEL: trunc_v64i32_v64i8:162; CHECK: // %bb.0:163; CHECK-NEXT: ptrue p0.s, vl64164; CHECK-NEXT: ld1w { z0.s }, p0/z, [x0]165; CHECK-NEXT: ptrue p0.b, vl64166; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h167; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b168; CHECK-NEXT: add z0.b, z0.b, z0.b169; CHECK-NEXT: st1b { z0.b }, p0, [x1]170; CHECK-NEXT: ret171 %a = load <64 x i32>, ptr %in172 %b = trunc <64 x i32> %a to <64 x i8>173 %c = add <64 x i8> %b, %b174 store <64 x i8> %c, ptr %out175 ret void176}177 178;179; truncate i32 -> i16180;181 182define <8 x i16> @trunc_v8i32_v8i16(ptr %in) vscale_range(2,0) #0 {183; CHECK-LABEL: trunc_v8i32_v8i16:184; CHECK: // %bb.0:185; CHECK-NEXT: ptrue p0.s, vl8186; CHECK-NEXT: ld1w { z0.s }, p0/z, [x0]187; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h188; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0189; CHECK-NEXT: ret190 %a = load <8 x i32>, ptr %in191 %b = trunc <8 x i32> %a to <8 x i16>192 ret <8 x i16> %b193}194 195; NOTE: Extra 'add' is to prevent the truncate being combined with the store.196define void @trunc_v16i32_v16i16(ptr %in, ptr %out) #0 {197; VBITS_GE_256-LABEL: trunc_v16i32_v16i16:198; VBITS_GE_256: // %bb.0:199; VBITS_GE_256-NEXT: ptrue p0.s, vl8200; VBITS_GE_256-NEXT: mov x8, #8 // =0x8201; VBITS_GE_256-NEXT: ld1w { z0.s }, p0/z, [x0, x8, lsl #2]202; VBITS_GE_256-NEXT: ld1w { z1.s }, p0/z, [x0]203; VBITS_GE_256-NEXT: ptrue p0.h, vl8204; VBITS_GE_256-NEXT: uzp1 z0.h, z0.h, z0.h205; VBITS_GE_256-NEXT: uzp1 z1.h, z1.h, z1.h206; VBITS_GE_256-NEXT: splice z1.h, p0, z1.h, z0.h207; VBITS_GE_256-NEXT: ptrue p0.h, vl16208; VBITS_GE_256-NEXT: add z0.h, z1.h, z1.h209; VBITS_GE_256-NEXT: st1h { z0.h }, p0, [x1]210; VBITS_GE_256-NEXT: ret211;212; VBITS_GE_512-LABEL: trunc_v16i32_v16i16:213; VBITS_GE_512: // %bb.0:214; VBITS_GE_512-NEXT: ptrue p0.s, vl16215; VBITS_GE_512-NEXT: ld1w { z0.s }, p0/z, [x0]216; VBITS_GE_512-NEXT: ptrue p0.h, vl16217; VBITS_GE_512-NEXT: uzp1 z0.h, z0.h, z0.h218; VBITS_GE_512-NEXT: add z0.h, z0.h, z0.h219; VBITS_GE_512-NEXT: st1h { z0.h }, p0, [x1]220; VBITS_GE_512-NEXT: ret221 %a = load <16 x i32>, ptr %in222 %b = trunc <16 x i32> %a to <16 x i16>223 %c = add <16 x i16> %b, %b224 store <16 x i16> %c, ptr %out225 ret void226}227 228; NOTE: Extra 'add' is to prevent the truncate being combined with the store.229define void @trunc_v32i32_v32i16(ptr %in, ptr %out) vscale_range(8,0) #0 {230; CHECK-LABEL: trunc_v32i32_v32i16:231; CHECK: // %bb.0:232; CHECK-NEXT: ptrue p0.s, vl32233; CHECK-NEXT: ld1w { z0.s }, p0/z, [x0]234; CHECK-NEXT: ptrue p0.h, vl32235; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h236; CHECK-NEXT: add z0.h, z0.h, z0.h237; CHECK-NEXT: st1h { z0.h }, p0, [x1]238; CHECK-NEXT: ret239 %a = load <32 x i32>, ptr %in240 %b = trunc <32 x i32> %a to <32 x i16>241 %c = add <32 x i16> %b, %b242 store <32 x i16> %c, ptr %out243 ret void244}245 246; NOTE: Extra 'add' is to prevent the truncate being combined with the store.247define void @trunc_v64i32_v64i16(ptr %in, ptr %out) vscale_range(16,0) #0 {248; CHECK-LABEL: trunc_v64i32_v64i16:249; CHECK: // %bb.0:250; CHECK-NEXT: ptrue p0.s, vl64251; CHECK-NEXT: ld1w { z0.s }, p0/z, [x0]252; CHECK-NEXT: ptrue p0.h, vl64253; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h254; CHECK-NEXT: add z0.h, z0.h, z0.h255; CHECK-NEXT: st1h { z0.h }, p0, [x1]256; CHECK-NEXT: ret257 %a = load <64 x i32>, ptr %in258 %b = trunc <64 x i32> %a to <64 x i16>259 %c = add <64 x i16> %b, %b260 store <64 x i16> %c, ptr %out261 ret void262}263 264;265; truncate i64 -> i8266;267 268; NOTE: v4i8 is not legal so result i8 elements are held within i16 containers.269define <4 x i8> @trunc_v4i64_v4i8(ptr %in) vscale_range(2,0) #0 {270; CHECK-LABEL: trunc_v4i64_v4i8:271; CHECK: // %bb.0:272; CHECK-NEXT: ptrue p0.d, vl4273; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]274; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s275; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h276; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0277; CHECK-NEXT: ret278 %a = load <4 x i64>, ptr %in279 %b = trunc <4 x i64> %a to <4 x i8>280 ret <4 x i8> %b281}282 283define <8 x i8> @trunc_v8i64_v8i8(ptr %in) #0 {284; VBITS_GE_256-LABEL: trunc_v8i64_v8i8:285; VBITS_GE_256: // %bb.0:286; VBITS_GE_256-NEXT: ptrue p0.d, vl4287; VBITS_GE_256-NEXT: mov x8, #4 // =0x4288; VBITS_GE_256-NEXT: ld1d { z0.d }, p0/z, [x0, x8, lsl #3]289; VBITS_GE_256-NEXT: ld1d { z1.d }, p0/z, [x0]290; VBITS_GE_256-NEXT: ptrue p0.s, vl4291; VBITS_GE_256-NEXT: uzp1 z0.s, z0.s, z0.s292; VBITS_GE_256-NEXT: uzp1 z1.s, z1.s, z1.s293; VBITS_GE_256-NEXT: splice z1.s, p0, z1.s, z0.s294; VBITS_GE_256-NEXT: uzp1 z0.h, z1.h, z1.h295; VBITS_GE_256-NEXT: uzp1 z0.b, z0.b, z0.b296; VBITS_GE_256-NEXT: // kill: def $d0 killed $d0 killed $z0297; VBITS_GE_256-NEXT: ret298;299; VBITS_GE_512-LABEL: trunc_v8i64_v8i8:300; VBITS_GE_512: // %bb.0:301; VBITS_GE_512-NEXT: ptrue p0.d, vl8302; VBITS_GE_512-NEXT: ld1d { z0.d }, p0/z, [x0]303; VBITS_GE_512-NEXT: uzp1 z0.s, z0.s, z0.s304; VBITS_GE_512-NEXT: uzp1 z0.h, z0.h, z0.h305; VBITS_GE_512-NEXT: uzp1 z0.b, z0.b, z0.b306; VBITS_GE_512-NEXT: // kill: def $d0 killed $d0 killed $z0307; VBITS_GE_512-NEXT: ret308 %a = load <8 x i64>, ptr %in309 %b = trunc <8 x i64> %a to <8 x i8>310 ret <8 x i8> %b311}312 313define <16 x i8> @trunc_v16i64_v16i8(ptr %in) vscale_range(8,0) #0 {314; CHECK-LABEL: trunc_v16i64_v16i8:315; CHECK: // %bb.0:316; CHECK-NEXT: ptrue p0.d, vl16317; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]318; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s319; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h320; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b321; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0322; CHECK-NEXT: ret323 %a = load <16 x i64>, ptr %in324 %b = trunc <16 x i64> %a to <16 x i8>325 ret <16 x i8> %b326}327 328; NOTE: Extra 'add' is to prevent the truncate being combined with the store.329define void @trunc_v32i64_v32i8(ptr %in, ptr %out) vscale_range(16,0) #0 {330; CHECK-LABEL: trunc_v32i64_v32i8:331; CHECK: // %bb.0:332; CHECK-NEXT: ptrue p0.d, vl32333; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]334; CHECK-NEXT: ptrue p0.b, vl32335; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s336; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h337; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b338; CHECK-NEXT: add z0.b, z0.b, z0.b339; CHECK-NEXT: st1b { z0.b }, p0, [x1]340; CHECK-NEXT: ret341 %a = load <32 x i64>, ptr %in342 %b = trunc <32 x i64> %a to <32 x i8>343 %c = add <32 x i8> %b, %b344 store <32 x i8> %c, ptr %out345 ret void346}347 348;349; truncate i64 -> i16350;351 352define <4 x i16> @trunc_v4i64_v4i16(ptr %in) vscale_range(2,0) #0 {353; CHECK-LABEL: trunc_v4i64_v4i16:354; CHECK: // %bb.0:355; CHECK-NEXT: ptrue p0.d, vl4356; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]357; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s358; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h359; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0360; CHECK-NEXT: ret361 %a = load <4 x i64>, ptr %in362 %b = trunc <4 x i64> %a to <4 x i16>363 ret <4 x i16> %b364}365 366define <8 x i16> @trunc_v8i64_v8i16(ptr %in) #0 {367; VBITS_GE_256-LABEL: trunc_v8i64_v8i16:368; VBITS_GE_256: // %bb.0:369; VBITS_GE_256-NEXT: ptrue p0.d, vl4370; VBITS_GE_256-NEXT: mov x8, #4 // =0x4371; VBITS_GE_256-NEXT: ld1d { z0.d }, p0/z, [x0, x8, lsl #3]372; VBITS_GE_256-NEXT: ld1d { z1.d }, p0/z, [x0]373; VBITS_GE_256-NEXT: uzp1 z0.s, z0.s, z0.s374; VBITS_GE_256-NEXT: uzp1 z1.s, z1.s, z1.s375; VBITS_GE_256-NEXT: uzp1 z2.h, z0.h, z0.h376; VBITS_GE_256-NEXT: uzp1 z0.h, z1.h, z1.h377; VBITS_GE_256-NEXT: mov v0.d[1], v2.d[0]378; VBITS_GE_256-NEXT: // kill: def $q0 killed $q0 killed $z0379; VBITS_GE_256-NEXT: ret380;381; VBITS_GE_512-LABEL: trunc_v8i64_v8i16:382; VBITS_GE_512: // %bb.0:383; VBITS_GE_512-NEXT: ptrue p0.d, vl8384; VBITS_GE_512-NEXT: ld1d { z0.d }, p0/z, [x0]385; VBITS_GE_512-NEXT: uzp1 z0.s, z0.s, z0.s386; VBITS_GE_512-NEXT: uzp1 z0.h, z0.h, z0.h387; VBITS_GE_512-NEXT: // kill: def $q0 killed $q0 killed $z0388; VBITS_GE_512-NEXT: ret389 %a = load <8 x i64>, ptr %in390 %b = trunc <8 x i64> %a to <8 x i16>391 ret <8 x i16> %b392}393 394; NOTE: Extra 'add' is to prevent the truncate being combined with the store.395define void @trunc_v16i64_v16i16(ptr %in, ptr %out) vscale_range(8,0) #0 {396; CHECK-LABEL: trunc_v16i64_v16i16:397; CHECK: // %bb.0:398; CHECK-NEXT: ptrue p0.d, vl16399; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]400; CHECK-NEXT: ptrue p0.h, vl16401; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s402; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h403; CHECK-NEXT: add z0.h, z0.h, z0.h404; CHECK-NEXT: st1h { z0.h }, p0, [x1]405; CHECK-NEXT: ret406 %a = load <16 x i64>, ptr %in407 %b = trunc <16 x i64> %a to <16 x i16>408 %c = add <16 x i16> %b, %b409 store <16 x i16> %c, ptr %out410 ret void411}412 413; NOTE: Extra 'add' is to prevent the truncate being combined with the store.414define void @trunc_v32i64_v32i16(ptr %in, ptr %out) vscale_range(16,0) #0 {415; CHECK-LABEL: trunc_v32i64_v32i16:416; CHECK: // %bb.0:417; CHECK-NEXT: ptrue p0.d, vl32418; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]419; CHECK-NEXT: ptrue p0.h, vl32420; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s421; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h422; CHECK-NEXT: add z0.h, z0.h, z0.h423; CHECK-NEXT: st1h { z0.h }, p0, [x1]424; CHECK-NEXT: ret425 %a = load <32 x i64>, ptr %in426 %b = trunc <32 x i64> %a to <32 x i16>427 %c = add <32 x i16> %b, %b428 store <32 x i16> %c, ptr %out429 ret void430}431 432;433; truncate i64 -> i32434;435 436define <4 x i32> @trunc_v4i64_v4i32(ptr %in) vscale_range(2,0) #0 {437; CHECK-LABEL: trunc_v4i64_v4i32:438; CHECK: // %bb.0:439; CHECK-NEXT: ptrue p0.d, vl4440; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]441; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s442; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0443; CHECK-NEXT: ret444 %a = load <4 x i64>, ptr %in445 %b = trunc <4 x i64> %a to <4 x i32>446 ret <4 x i32> %b447}448 449; NOTE: Extra 'add' is to prevent the truncate being combined with the store.450define void @trunc_v8i64_v8i32(ptr %in, ptr %out) #0 {451; VBITS_GE_256-LABEL: trunc_v8i64_v8i32:452; VBITS_GE_256: // %bb.0:453; VBITS_GE_256-NEXT: ptrue p0.d, vl4454; VBITS_GE_256-NEXT: mov x8, #4 // =0x4455; VBITS_GE_256-NEXT: ld1d { z0.d }, p0/z, [x0, x8, lsl #3]456; VBITS_GE_256-NEXT: ld1d { z1.d }, p0/z, [x0]457; VBITS_GE_256-NEXT: ptrue p0.s, vl4458; VBITS_GE_256-NEXT: uzp1 z0.s, z0.s, z0.s459; VBITS_GE_256-NEXT: uzp1 z1.s, z1.s, z1.s460; VBITS_GE_256-NEXT: splice z1.s, p0, z1.s, z0.s461; VBITS_GE_256-NEXT: ptrue p0.s, vl8462; VBITS_GE_256-NEXT: add z0.s, z1.s, z1.s463; VBITS_GE_256-NEXT: st1w { z0.s }, p0, [x1]464; VBITS_GE_256-NEXT: ret465;466; VBITS_GE_512-LABEL: trunc_v8i64_v8i32:467; VBITS_GE_512: // %bb.0:468; VBITS_GE_512-NEXT: ptrue p0.d, vl8469; VBITS_GE_512-NEXT: ld1d { z0.d }, p0/z, [x0]470; VBITS_GE_512-NEXT: ptrue p0.s, vl8471; VBITS_GE_512-NEXT: uzp1 z0.s, z0.s, z0.s472; VBITS_GE_512-NEXT: add z0.s, z0.s, z0.s473; VBITS_GE_512-NEXT: st1w { z0.s }, p0, [x1]474; VBITS_GE_512-NEXT: ret475 %a = load <8 x i64>, ptr %in476 %b = trunc <8 x i64> %a to <8 x i32>477 %c = add <8 x i32> %b, %b478 store <8 x i32> %c, ptr %out479 ret void480}481 482; NOTE: Extra 'add' is to prevent the truncate being combined with the store.483define void @trunc_v16i64_v16i32(ptr %in, ptr %out) vscale_range(8,0) #0 {484; CHECK-LABEL: trunc_v16i64_v16i32:485; CHECK: // %bb.0:486; CHECK-NEXT: ptrue p0.d, vl16487; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]488; CHECK-NEXT: ptrue p0.s, vl16489; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s490; CHECK-NEXT: add z0.s, z0.s, z0.s491; CHECK-NEXT: st1w { z0.s }, p0, [x1]492; CHECK-NEXT: ret493 %a = load <16 x i64>, ptr %in494 %b = trunc <16 x i64> %a to <16 x i32>495 %c = add <16 x i32> %b, %b496 store <16 x i32> %c, ptr %out497 ret void498}499 500; NOTE: Extra 'add' is to prevent the truncate being combined with the store.501define void @trunc_v32i64_v32i32(ptr %in, ptr %out) vscale_range(16,0) #0 {502; CHECK-LABEL: trunc_v32i64_v32i32:503; CHECK: // %bb.0:504; CHECK-NEXT: ptrue p0.d, vl32505; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]506; CHECK-NEXT: ptrue p0.s, vl32507; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s508; CHECK-NEXT: add z0.s, z0.s, z0.s509; CHECK-NEXT: st1w { z0.s }, p0, [x1]510; CHECK-NEXT: ret511 %a = load <32 x i64>, ptr %in512 %b = trunc <32 x i64> %a to <32 x i32>513 %c = add <32 x i32> %b, %b514 store <32 x i32> %c, ptr %out515 ret void516}517 518attributes #0 = { nounwind "target-features"="+sve" }519