; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 ; RUN: opt < %s -passes=interleaved-access -S | FileCheck %s target triple = "aarch64-linux-gnu" define void @deinterleave_nxi8_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define void @deinterleave_nxi8_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv16i8.p0( splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: [[EXTRACT1:%.*]] = extractvalue { , } [[LDN]], 1 ; CHECK-NEXT: [[EXTRACT2:%.*]] = extractvalue { , } [[LDN]], 0 ; CHECK-NEXT: ret void ; %load = load , ptr %ptr, align 1 %deinterleave = tail call { , } @llvm.vector.deinterleave2.nxv32i8( %load) %extract1 = extractvalue { , } %deinterleave, 1 %extract2 = extractvalue { , } %deinterleave, 0 ret void } define void @deinterleave_nxi16_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define void @deinterleave_nxi16_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv8i16.p0( splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: [[EXTRACT1:%.*]] = extractvalue { , } [[LDN]], 0 ; CHECK-NEXT: [[EXTRACT2:%.*]] = extractvalue { , } [[LDN]], 1 ; CHECK-NEXT: ret void ; %load = load , ptr %ptr, align 2 %deinterleave = tail call { , } @llvm.vector.deinterleave2.nxv16i16( %load) %extract1 = extractvalue { , } %deinterleave, 0 %extract2 = extractvalue { , } %deinterleave, 1 ret void } define void @deinterleave_nx8xi32_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define void @deinterleave_nx8xi32_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv4i32.p0( splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: [[EXTRACT1:%.*]] = extractvalue { , } [[LDN]], 0 ; CHECK-NEXT: [[EXTRACT2:%.*]] = extractvalue { , } [[LDN]], 1 ; CHECK-NEXT: ret void ; %load = load , ptr %ptr, align 4 %deinterleave = tail call { , } @llvm.vector.deinterleave2.nxv8i32( %load) %extract1 = extractvalue { , } %deinterleave, 0 %extract2 = extractvalue { , } %deinterleave, 1 ret void } define void @deinterleave_nxi64_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define void @deinterleave_nxi64_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv2i64.p0( splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: [[EXTRACT1:%.*]] = extractvalue { , } [[LDN]], 0 ; CHECK-NEXT: [[EXTRACT2:%.*]] = extractvalue { , } [[LDN]], 1 ; CHECK-NEXT: ret void ; %load = load , ptr %ptr, align 8 %deinterleave = tail call { , } @llvm.vector.deinterleave2.nxv4i64( %load) %extract1 = extractvalue { , } %deinterleave, 0 %extract2 = extractvalue { , } %deinterleave, 1 ret void } define void @deinterleave_nxfloat_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define void @deinterleave_nxfloat_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv4f32.p0( splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: [[EXTRACT1:%.*]] = extractvalue { , } [[LDN]], 0 ; CHECK-NEXT: [[EXTRACT2:%.*]] = extractvalue { , } [[LDN]], 1 ; CHECK-NEXT: ret void ; %load = load , ptr %ptr, align 4 %deinterleave = tail call { , } @llvm.vector.deinterleave2.nxv8f32( %load) %extract1 = extractvalue { , } %deinterleave, 0 %extract2 = extractvalue { , } %deinterleave, 1 ret void } define void @deinterleave_nxdouble_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define void @deinterleave_nxdouble_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv2f64.p0( splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: [[EXTRACT1:%.*]] = extractvalue { , } [[LDN]], 0 ; CHECK-NEXT: [[EXTRACT2:%.*]] = extractvalue { , } [[LDN]], 1 ; CHECK-NEXT: ret void ; %load = load , ptr %ptr, align 8 %deinterleave = tail call { , } @llvm.vector.deinterleave2.nxv4f64( %load) %extract1 = extractvalue { , } %deinterleave, 0 %extract2 = extractvalue { , } %deinterleave, 1 ret void } define void @deinterleave_nxptr_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define void @deinterleave_nxptr_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv2p0.p0( splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: [[EXTRACT1:%.*]] = extractvalue { , } [[LDN]], 0 ; CHECK-NEXT: [[EXTRACT2:%.*]] = extractvalue { , } [[LDN]], 1 ; CHECK-NEXT: ret void ; %load = load , ptr %ptr, align 8 %deinterleave = tail call { , } @llvm.vector.deinterleave2.nxv4p0( %load) %extract1 = extractvalue { , } %deinterleave, 0 %extract2 = extractvalue { , } %deinterleave, 1 ret void } define void @interleave_nxi8_factor2(ptr %ptr, %l, %r) #0 { ; CHECK-LABEL: define void @interleave_nxi8_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]], [[L:%.*]], [[R:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: call void @llvm.aarch64.sve.st2.nxv16i8.p0( [[L]], [[R]], splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave2.nxv32i8( %l, %r) store %interleave, ptr %ptr, align 1 ret void } define void @interleave_nxi16_factor2(ptr %ptr, %l, %r) #0 { ; CHECK-LABEL: define void @interleave_nxi16_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]], [[L:%.*]], [[R:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: call void @llvm.aarch64.sve.st2.nxv8i16.p0( [[L]], [[R]], splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave2.nxv16i16( %l, %r) store %interleave, ptr %ptr, align 2 ret void } define void @interleave_nxi32_factor2(ptr %ptr, %l, %r) #0 { ; CHECK-LABEL: define void @interleave_nxi32_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]], [[L:%.*]], [[R:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: call void @llvm.aarch64.sve.st2.nxv4i32.p0( [[L]], [[R]], splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave2.nxv8i32( %l, %r) store %interleave, ptr %ptr, align 4 ret void } define void @interleave_nxi64_factor2(ptr %ptr, %l, %r) #0 { ; CHECK-LABEL: define void @interleave_nxi64_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]], [[L:%.*]], [[R:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: call void @llvm.aarch64.sve.st2.nxv2i64.p0( [[L]], [[R]], splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave2.nxv4i64( %l, %r) store %interleave, ptr %ptr, align 8 ret void } define void @interleave_nxfloat_factor2(ptr %ptr, %l, %r) #0 { ; CHECK-LABEL: define void @interleave_nxfloat_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]], [[L:%.*]], [[R:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: call void @llvm.aarch64.sve.st2.nxv4f32.p0( [[L]], [[R]], splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave2.nxv8f32( %l, %r) store %interleave, ptr %ptr, align 4 ret void } define void @interleave_nxdouble_factor2(ptr %ptr, %l, %r) #0 { ; CHECK-LABEL: define void @interleave_nxdouble_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]], [[L:%.*]], [[R:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: call void @llvm.aarch64.sve.st2.nxv2f64.p0( [[L]], [[R]], splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave2.nxv4f64( %l, %r) store %interleave, ptr %ptr, align 4 ret void } define void @interleave_nxptr_factor2(ptr %ptr, %l, %r) #0 { ; CHECK-LABEL: define void @interleave_nxptr_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]], [[L:%.*]], [[R:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: call void @llvm.aarch64.sve.st2.nxv2p0.p0( [[L]], [[R]], splat (i1 true), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave2.nxv4p0( %l, %r) store %interleave, ptr %ptr, align 4 ret void } define void @interleave_nxi8_factor2_masked_store_splatmask(ptr %ptr, %l, %r, i1 %mask) #0 { ; CHECK-LABEL: define void @interleave_nxi8_factor2_masked_store_splatmask ; CHECK-SAME: (ptr [[PTR:%.*]], [[L:%.*]], [[R:%.*]], i1 [[MASK:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[INTERLEAVE:%.*]] = tail call @llvm.vector.interleave2.nxv32i8( [[L]], [[R]]) ; CHECK-NEXT: [[MASK_INS:%.*]] = insertelement poison, i1 [[MASK]], i64 0 ; CHECK-NEXT: [[MASK_SPLAT:%.*]] = shufflevector [[MASK_INS]], poison, zeroinitializer ; CHECK-NEXT: tail call void @llvm.masked.store.nxv32i8.p0( [[INTERLEAVE]], ptr align 1 [[PTR]], [[MASK_SPLAT]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave2.nxv32i8( %l, %r) %mask.ins = insertelement poison, i1 %mask, i64 0 %mask.splat = shufflevector %mask.ins, poison, zeroinitializer tail call void @llvm.masked.store.nxv32i8.p0( %interleave, ptr %ptr, i32 1, %mask.splat) ret void } ;;; Check that we 'legalize' operations that are wider than the target supports. define void @deinterleave_wide_nxi32_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define void @deinterleave_wide_nxi32_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[PTR]], i64 0 ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv4i32.p0( splat (i1 true), ptr [[TMP1]]) ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { , } [[LDN]], 0 ; CHECK-NEXT: [[TMP3:%.*]] = call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP2]], i64 0) ; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[LDN]], 1 ; CHECK-NEXT: [[TMP5:%.*]] = call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP4]], i64 0) ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr , ptr [[PTR]], i64 2 ; CHECK-NEXT: [[LDN1:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv4i32.p0( splat (i1 true), ptr [[TMP6]]) ; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[LDN1]], 0 ; CHECK-NEXT: [[TMP8:%.*]] = call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP3]], [[TMP7]], i64 4) ; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , } [[LDN1]], 1 ; CHECK-NEXT: [[TMP10:%.*]] = call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP5]], [[TMP9]], i64 4) ; CHECK-NEXT: [[TMP11:%.*]] = getelementptr , ptr [[PTR]], i64 4 ; CHECK-NEXT: [[LDN2:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv4i32.p0( splat (i1 true), ptr [[TMP11]]) ; CHECK-NEXT: [[TMP12:%.*]] = extractvalue { , } [[LDN2]], 0 ; CHECK-NEXT: [[TMP13:%.*]] = call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP8]], [[TMP12]], i64 8) ; CHECK-NEXT: [[TMP14:%.*]] = extractvalue { , } [[LDN2]], 1 ; CHECK-NEXT: [[TMP15:%.*]] = call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP10]], [[TMP14]], i64 8) ; CHECK-NEXT: [[TMP16:%.*]] = getelementptr , ptr [[PTR]], i64 6 ; CHECK-NEXT: [[LDN3:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv4i32.p0( splat (i1 true), ptr [[TMP16]]) ; CHECK-NEXT: [[TMP17:%.*]] = extractvalue { , } [[LDN3]], 0 ; CHECK-NEXT: [[TMP18:%.*]] = call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP13]], [[TMP17]], i64 12) ; CHECK-NEXT: [[TMP19:%.*]] = extractvalue { , } [[LDN3]], 1 ; CHECK-NEXT: [[TMP20:%.*]] = call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP15]], [[TMP19]], i64 12) ; CHECK-NEXT: [[TMP21:%.*]] = insertvalue { , } poison, [[TMP18]], 0 ; CHECK-NEXT: [[TMP22:%.*]] = insertvalue { , } [[TMP21]], [[TMP20]], 1 ; CHECK-NEXT: [[EXTRACT1:%.*]] = extractvalue { , } [[TMP22]], 0 ; CHECK-NEXT: [[EXTRACT2:%.*]] = extractvalue { , } [[TMP22]], 1 ; CHECK-NEXT: ret void ; %load = load , ptr %ptr, align 4 %deinterleave = tail call { , } @llvm.vector.deinterleave2.nxv32i32( %load) %extract1 = extractvalue { , } %deinterleave, 0 %extract2 = extractvalue { , } %deinterleave, 1 ret void } define void @deinterleave_wide_nxdouble_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define void @deinterleave_wide_nxdouble_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[PTR]], i64 0 ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv2f64.p0( splat (i1 true), ptr [[TMP1]]) ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { , } [[LDN]], 0 ; CHECK-NEXT: [[TMP3:%.*]] = call @llvm.vector.insert.nxv4f64.nxv2f64( poison, [[TMP2]], i64 0) ; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[LDN]], 1 ; CHECK-NEXT: [[TMP5:%.*]] = call @llvm.vector.insert.nxv4f64.nxv2f64( poison, [[TMP4]], i64 0) ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr , ptr [[PTR]], i64 2 ; CHECK-NEXT: [[LDN1:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv2f64.p0( splat (i1 true), ptr [[TMP6]]) ; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[LDN1]], 0 ; CHECK-NEXT: [[TMP8:%.*]] = call @llvm.vector.insert.nxv4f64.nxv2f64( [[TMP3]], [[TMP7]], i64 2) ; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , } [[LDN1]], 1 ; CHECK-NEXT: [[TMP10:%.*]] = call @llvm.vector.insert.nxv4f64.nxv2f64( [[TMP5]], [[TMP9]], i64 2) ; CHECK-NEXT: [[TMP11:%.*]] = insertvalue { , } poison, [[TMP8]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = insertvalue { , } [[TMP11]], [[TMP10]], 1 ; CHECK-NEXT: [[EXTRACT1:%.*]] = extractvalue { , } [[TMP12]], 0 ; CHECK-NEXT: [[EXTRACT2:%.*]] = extractvalue { , } [[TMP12]], 1 ; CHECK-NEXT: ret void ; %load = load , ptr %ptr, align 8 %deinterleave = tail call { , } @llvm.vector.deinterleave2.nxv8f64( %load) %extract1 = extractvalue { , } %deinterleave, 0 %extract2 = extractvalue { , } %deinterleave, 1 ret void } define void @interleave_wide_nxdouble_factor2(ptr %ptr, %l, %r) #0 { ; CHECK-LABEL: define void @interleave_wide_nxdouble_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]], [[L:%.*]], [[R:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[PTR]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = call @llvm.vector.extract.nxv2f64.nxv4f64( [[L]], i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = call @llvm.vector.extract.nxv2f64.nxv4f64( [[R]], i64 0) ; CHECK-NEXT: call void @llvm.aarch64.sve.st2.nxv2f64.p0( [[TMP2]], [[TMP3]], splat (i1 true), ptr [[TMP1]]) ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr , ptr [[PTR]], i64 2 ; CHECK-NEXT: [[TMP5:%.*]] = call @llvm.vector.extract.nxv2f64.nxv4f64( [[L]], i64 2) ; CHECK-NEXT: [[TMP6:%.*]] = call @llvm.vector.extract.nxv2f64.nxv4f64( [[R]], i64 2) ; CHECK-NEXT: call void @llvm.aarch64.sve.st2.nxv2f64.p0( [[TMP5]], [[TMP6]], splat (i1 true), ptr [[TMP4]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave2.nxv8f64( %l, %r) store %interleave, ptr %ptr, align 4 ret void } define void @deinterleave1_nxi64_factor3(ptr %ptr, * %s1, * %s2, * %s3) #0 { ; CHECK-LABEL: define void @deinterleave1_nxi64_factor3 ; CHECK-SAME: (ptr [[PTR:%.*]], ptr [[S1:%.*]], ptr [[S2:%.*]], ptr [[S3:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[PTR]], i64 0 ; CHECK-NEXT: [[LDN1:%.*]] = call { , , } @llvm.aarch64.sve.ld3.sret.nxv2i64.p0( splat (i1 true), ptr [[TMP1]]) ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { , , } [[LDN1]], 0 ; CHECK-NEXT: [[TMP3:%.*]] = call @llvm.vector.insert.nxv4i64.nxv2i64( poison, [[TMP2]], i64 0) ; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , , } [[LDN1]], 1 ; CHECK-NEXT: [[TMP5:%.*]] = call @llvm.vector.insert.nxv4i64.nxv2i64( poison, [[TMP4]], i64 0) ; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { , , } [[LDN1]], 2 ; CHECK-NEXT: [[TMP7:%.*]] = call @llvm.vector.insert.nxv4i64.nxv2i64( poison, [[TMP6]], i64 0) ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr , ptr [[PTR]], i64 3 ; CHECK-NEXT: [[LDN2:%.*]] = call { , , } @llvm.aarch64.sve.ld3.sret.nxv2i64.p0( splat (i1 true), ptr [[TMP8]]) ; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , } [[LDN2]], 0 ; CHECK-NEXT: [[TMP10:%.*]] = call @llvm.vector.insert.nxv4i64.nxv2i64( [[TMP3]], [[TMP9]], i64 2) ; CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , } [[LDN2]], 1 ; CHECK-NEXT: [[TMP12:%.*]] = call @llvm.vector.insert.nxv4i64.nxv2i64( [[TMP5]], [[TMP11]], i64 2) ; CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , } [[LDN2]], 2 ; CHECK-NEXT: [[TMP14:%.*]] = call @llvm.vector.insert.nxv4i64.nxv2i64( [[TMP7]], [[TMP13]], i64 2) ; CHECK-NEXT: [[TMP15:%.*]] = insertvalue { , , } poison, [[TMP10]], 0 ; CHECK-NEXT: [[TMP16:%.*]] = insertvalue { , , } [[TMP15]], [[TMP12]], 1 ; CHECK-NEXT: [[TMP17:%.*]] = insertvalue { , , } [[TMP16]], [[TMP14]], 2 ; CHECK-NEXT: [[TMP18:%.*]] = extractvalue { , , } [[TMP17]], 0 ; CHECK-NEXT: [[TMP19:%.*]] = extractvalue { , , } [[TMP17]], 1 ; CHECK-NEXT: [[TMP20:%.*]] = extractvalue { , , } [[TMP17]], 2 ; CHECK-NEXT: store [[TMP18]], ptr [[S1]], align 32 ; CHECK-NEXT: store [[TMP19]], ptr [[S2]], align 32 ; CHECK-NEXT: store [[TMP20]], ptr [[S3]], align 32 ; CHECK-NEXT: ret void ; %wide.vec = load , ptr %ptr, align 8 %ldN = tail call { , , } @llvm.vector.deinterleave3.nxv12i64( %wide.vec) %3 = extractvalue { , , } %ldN, 0 %4 = extractvalue { , , } %ldN, 1 %5 = extractvalue { , , } %ldN, 2 store %3, * %s1 store %4, * %s2 store %5, * %s3 ret void } define void @deinterleave2_nxi64_factor3(ptr %ptr, * %s1, * %s2, * %s3) #0 { ; CHECK-LABEL: define void @deinterleave2_nxi64_factor3 ; CHECK-SAME: (ptr [[PTR:%.*]], ptr [[S1:%.*]], ptr [[S2:%.*]], ptr [[S3:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[PTR]], i64 0 ; CHECK-NEXT: [[LDN1:%.*]] = call { , , } @llvm.aarch64.sve.ld3.sret.nxv2i64.p0( splat (i1 true), ptr [[TMP1]]) ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { , , } [[LDN1]], 0 ; CHECK-NEXT: [[TMP3:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( poison, [[TMP2]], i64 0) ; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , , } [[LDN1]], 1 ; CHECK-NEXT: [[TMP5:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( poison, [[TMP4]], i64 0) ; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { , , } [[LDN1]], 2 ; CHECK-NEXT: [[TMP7:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( poison, [[TMP6]], i64 0) ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr , ptr [[PTR]], i64 3 ; CHECK-NEXT: [[LDN2:%.*]] = call { , , } @llvm.aarch64.sve.ld3.sret.nxv2i64.p0( splat (i1 true), ptr [[TMP8]]) ; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , } [[LDN2]], 0 ; CHECK-NEXT: [[TMP10:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP3]], [[TMP9]], i64 2) ; CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , } [[LDN2]], 1 ; CHECK-NEXT: [[TMP12:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP5]], [[TMP11]], i64 2) ; CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , } [[LDN2]], 2 ; CHECK-NEXT: [[TMP14:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP7]], [[TMP13]], i64 2) ; CHECK-NEXT: [[TMP15:%.*]] = getelementptr , ptr [[PTR]], i64 6 ; CHECK-NEXT: [[LDN3:%.*]] = call { , , } @llvm.aarch64.sve.ld3.sret.nxv2i64.p0( splat (i1 true), ptr [[TMP15]]) ; CHECK-NEXT: [[TMP16:%.*]] = extractvalue { , , } [[LDN3]], 0 ; CHECK-NEXT: [[TMP17:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP10]], [[TMP16]], i64 4) ; CHECK-NEXT: [[TMP18:%.*]] = extractvalue { , , } [[LDN3]], 1 ; CHECK-NEXT: [[TMP19:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP12]], [[TMP18]], i64 4) ; CHECK-NEXT: [[TMP20:%.*]] = extractvalue { , , } [[LDN3]], 2 ; CHECK-NEXT: [[TMP21:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP14]], [[TMP20]], i64 4) ; CHECK-NEXT: [[TMP22:%.*]] = getelementptr , ptr [[PTR]], i64 9 ; CHECK-NEXT: [[LDN4:%.*]] = call { , , } @llvm.aarch64.sve.ld3.sret.nxv2i64.p0( splat (i1 true), ptr [[TMP22]]) ; CHECK-NEXT: [[TMP23:%.*]] = extractvalue { , , } [[LDN4]], 0 ; CHECK-NEXT: [[TMP24:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP17]], [[TMP23]], i64 6) ; CHECK-NEXT: [[TMP25:%.*]] = extractvalue { , , } [[LDN4]], 1 ; CHECK-NEXT: [[TMP26:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP19]], [[TMP25]], i64 6) ; CHECK-NEXT: [[TMP27:%.*]] = extractvalue { , , } [[LDN4]], 2 ; CHECK-NEXT: [[TMP28:%.*]] = call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP21]], [[TMP27]], i64 6) ; CHECK-NEXT: [[TMP29:%.*]] = insertvalue { , , } poison, [[TMP24]], 0 ; CHECK-NEXT: [[TMP30:%.*]] = insertvalue { , , } [[TMP29]], [[TMP26]], 1 ; CHECK-NEXT: [[TMP31:%.*]] = insertvalue { , , } [[TMP30]], [[TMP28]], 2 ; CHECK-NEXT: [[TMP32:%.*]] = extractvalue { , , } [[TMP31]], 0 ; CHECK-NEXT: [[TMP33:%.*]] = extractvalue { , , } [[TMP31]], 1 ; CHECK-NEXT: [[TMP34:%.*]] = extractvalue { , , } [[TMP31]], 2 ; CHECK-NEXT: store [[TMP32]], ptr [[S1]], align 64 ; CHECK-NEXT: store [[TMP33]], ptr [[S2]], align 64 ; CHECK-NEXT: store [[TMP34]], ptr [[S3]], align 64 ; CHECK-NEXT: ret void ; %wide.vec = load , ptr %ptr, align 8 %ldN = tail call { , , } @llvm.vector.deinterleave3.nxv24i64( %wide.vec) %3 = extractvalue { , , } %ldN, 0 %4 = extractvalue { , , } %ldN, 1 %5 = extractvalue { , , } %ldN, 2 store %3, * %s1 store %4, * %s2 store %5, * %s3 ret void } define void @deinterleave_neg1_nxi64_factor3(ptr %ptr, * %s1, * %s2, * %s3) #0 { ; CHECK-LABEL: define void @deinterleave_neg1_nxi64_factor3 ; CHECK-SAME: (ptr [[PTR:%.*]], ptr [[S1:%.*]], ptr [[S2:%.*]], ptr [[S3:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[WIDE_VEC:%.*]] = load , ptr [[PTR]], align 8 ; CHECK-NEXT: [[LDN:%.*]] = tail call { , , } @llvm.vector.deinterleave3.nxv3i64( [[WIDE_VEC]]) ; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , } [[LDN]], 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { , , } [[LDN]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , } [[LDN]], 2 ; CHECK-NEXT: store [[TMP1]], ptr [[S1]], align 8 ; CHECK-NEXT: store [[TMP2]], ptr [[S2]], align 8 ; CHECK-NEXT: store [[TMP3]], ptr [[S3]], align 8 ; CHECK-NEXT: ret void ; %wide.vec = load , ptr %ptr, align 8 %ldN = tail call { , , } @llvm.vector.deinterleave3.nxv3i64( %wide.vec) %3 = extractvalue { , , } %ldN, 0 %4 = extractvalue { , , } %ldN, 1 %5 = extractvalue { , , } %ldN, 2 store %3, * %s1 store %4, * %s2 store %5, * %s3 ret void } define void @deinterleave_neg2_nxi8_factor3(ptr %ptr, * %s1, * %s2, * %s3) #0 { ; CHECK-LABEL: define void @deinterleave_neg2_nxi8_factor3 ; CHECK-SAME: (ptr [[PTR:%.*]], ptr [[S1:%.*]], ptr [[S2:%.*]], ptr [[S3:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[WIDE_VEC:%.*]] = load , ptr [[PTR]], align 8 ; CHECK-NEXT: [[LDN:%.*]] = tail call { , , } @llvm.vector.deinterleave3.nxv24i8( [[WIDE_VEC]]) ; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , } [[LDN]], 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { , , } [[LDN]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , } [[LDN]], 2 ; CHECK-NEXT: store [[TMP1]], ptr [[S1]], align 8 ; CHECK-NEXT: store [[TMP2]], ptr [[S2]], align 8 ; CHECK-NEXT: store [[TMP3]], ptr [[S3]], align 8 ; CHECK-NEXT: ret void ; %wide.vec = load , ptr %ptr, align 8 %ldN = tail call { , , } @llvm.vector.deinterleave3.nxv12i8( %wide.vec) %3 = extractvalue { , , } %ldN, 0 %4 = extractvalue { , , } %ldN, 1 %5 = extractvalue { , , } %ldN, 2 store %3, * %s1 store %4, * %s2 store %5, * %s3 ret void } define void @interleave1_nxi64_factor3(ptr %ptr, %s1, %s2, %s3) #0 { ; CHECK-LABEL: define void @interleave1_nxi64_factor3 ; CHECK-SAME: (ptr [[PTR:%.*]], [[S1:%.*]], [[S2:%.*]], [[S3:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[PTR]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S1]], i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S2]], i64 0) ; CHECK-NEXT: [[TMP4:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S3]], i64 0) ; CHECK-NEXT: call void @llvm.aarch64.sve.st3.nxv2i64.p0( [[TMP2]], [[TMP3]], [[TMP4]], splat (i1 true), ptr [[TMP1]]) ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr , ptr [[PTR]], i64 3 ; CHECK-NEXT: [[TMP6:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S1]], i64 2) ; CHECK-NEXT: [[TMP7:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S2]], i64 2) ; CHECK-NEXT: [[TMP8:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S3]], i64 2) ; CHECK-NEXT: call void @llvm.aarch64.sve.st3.nxv2i64.p0( [[TMP6]], [[TMP7]], [[TMP8]], splat (i1 true), ptr [[TMP5]]) ; CHECK-NEXT: [[TMP9:%.*]] = getelementptr , ptr [[PTR]], i64 6 ; CHECK-NEXT: [[TMP10:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S1]], i64 4) ; CHECK-NEXT: [[TMP11:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S2]], i64 4) ; CHECK-NEXT: [[TMP12:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S3]], i64 4) ; CHECK-NEXT: call void @llvm.aarch64.sve.st3.nxv2i64.p0( [[TMP10]], [[TMP11]], [[TMP12]], splat (i1 true), ptr [[TMP9]]) ; CHECK-NEXT: [[TMP13:%.*]] = getelementptr , ptr [[PTR]], i64 9 ; CHECK-NEXT: [[TMP14:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S1]], i64 6) ; CHECK-NEXT: [[TMP15:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S2]], i64 6) ; CHECK-NEXT: [[TMP16:%.*]] = call @llvm.vector.extract.nxv2i64.nxv8i64( [[S3]], i64 6) ; CHECK-NEXT: call void @llvm.aarch64.sve.st3.nxv2i64.p0( [[TMP14]], [[TMP15]], [[TMP16]], splat (i1 true), ptr [[TMP13]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave3.nxv24i64( %s1, %s2, %s3) store %interleave, ptr %ptr, align 4 ret void } define void @interleave2_nxi64_factor3(ptr %ptr, %s1, %s2, %s3) #0 { ; CHECK-LABEL: define void @interleave2_nxi64_factor3 ; CHECK-SAME: (ptr [[PTR:%.*]], [[S1:%.*]], [[S2:%.*]], [[S3:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[PTR]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = call @llvm.vector.extract.nxv2i64.nxv4i64( [[S1]], i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = call @llvm.vector.extract.nxv2i64.nxv4i64( [[S2]], i64 0) ; CHECK-NEXT: [[TMP4:%.*]] = call @llvm.vector.extract.nxv2i64.nxv4i64( [[S3]], i64 0) ; CHECK-NEXT: call void @llvm.aarch64.sve.st3.nxv2i64.p0( [[TMP2]], [[TMP3]], [[TMP4]], splat (i1 true), ptr [[TMP1]]) ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr , ptr [[PTR]], i64 3 ; CHECK-NEXT: [[TMP6:%.*]] = call @llvm.vector.extract.nxv2i64.nxv4i64( [[S1]], i64 2) ; CHECK-NEXT: [[TMP7:%.*]] = call @llvm.vector.extract.nxv2i64.nxv4i64( [[S2]], i64 2) ; CHECK-NEXT: [[TMP8:%.*]] = call @llvm.vector.extract.nxv2i64.nxv4i64( [[S3]], i64 2) ; CHECK-NEXT: call void @llvm.aarch64.sve.st3.nxv2i64.p0( [[TMP6]], [[TMP7]], [[TMP8]], splat (i1 true), ptr [[TMP5]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave3.nxv12i64( %s1, %s2, %s3) store %interleave, ptr %ptr, align 4 ret void } define void @interleave_neg_nxi8_factor3(ptr %ptr, %s1, %s2, %s3) #0 { ; CHECK-LABEL: define void @interleave_neg_nxi8_factor3 ; CHECK-SAME: (ptr [[PTR:%.*]], [[S1:%.*]], [[S2:%.*]], [[S3:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[INTERLEAVE:%.*]] = tail call @llvm.vector.interleave3.nxv24i8( [[S1]], [[S2]], [[S3]]) ; CHECK-NEXT: store [[INTERLEAVE]], ptr [[PTR]], align 4 ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.vector.interleave3.nxv24i8( %s1, %s2, %s3) store %interleave, ptr %ptr, align 4 ret void } declare { , } @llvm.vector.deinterleave2.nxv32i8() declare { , } @llvm.vector.deinterleave2.nxv16i16() declare { , } @llvm.vector.deinterleave2.nxv8i32() declare { , } @llvm.vector.deinterleave2.nxv4i64() declare { , } @llvm.vector.deinterleave2.nxv8f32() declare { , } @llvm.vector.deinterleave2.nxv4f64() declare { , } @llvm.vector.deinterleave2.nxv4p0() ; Larger deinterleaves to test 'legalization' declare { , } @llvm.vector.deinterleave2.nxv32i32() declare { , } @llvm.vector.deinterleave2.nxv8f64() declare @llvm.vector.interleave2.nxv32i8(, ) declare @llvm.vector.interleave2.nxv16i16(, ) declare @llvm.vector.interleave2.nxv8i32(, ) declare @llvm.vector.interleave2.nxv4i64(, ) declare @llvm.vector.interleave2.nxv8f32(, ) declare @llvm.vector.interleave2.nxv4f64(, ) declare @llvm.vector.interleave2.nxv4p0(, ) ; Larger interleaves to test 'legalization' declare @llvm.vector.interleave2.nxv8f64(, ) ; De-Interleaves with Factor=3 declare { , , } @llvm.vector.deinterleave3.nxv3i64() declare { , , } @llvm.vector.deinterleave3.nxv12i64() declare { , , } @llvm.vector.deinterleave3.nxv24i64() declare { , , } @llvm.vector.deinterleave3.nxv24i8() ; Interleaves with Factor=3 declare @llvm.vector.interleave3.nxv24i8(, , ) declare @llvm.vector.interleave3.nxv24i64(, , ) declare @llvm.vector.interleave3.nxv12i64(, , ) attributes #0 = { vscale_range(1,16) "target-features"="+sve" }