; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 ; RUN: opt < %s -interleaved-access -S | FileCheck %s ; RUN: opt < %s -passes=interleaved-access -S | FileCheck %s target triple = "aarch64-linux-gnu" define { , } @deinterleave_nxi8_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define { , } @deinterleave_nxi8_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv16i8( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret { , } [[LDN]] ; %load = load , ptr %ptr, align 1 %deinterleave = tail call { , } @llvm.experimental.vector.deinterleave2.nxv32i8( %load) ret { , } %deinterleave } define { , } @deinterleave_nxi16_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define { , } @deinterleave_nxi16_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv8i16( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret { , } [[LDN]] ; %load = load , ptr %ptr, align 2 %deinterleave = tail call { , } @llvm.experimental.vector.deinterleave2.nxv16i16( %load) ret { , } %deinterleave } define { , } @deinterleave_nx8xi32_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define { , } @deinterleave_nx8xi32_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv4i32( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret { , } [[LDN]] ; %load = load , ptr %ptr, align 4 %deinterleave = tail call { , } @llvm.experimental.vector.deinterleave2.nxv8i32( %load) ret { , } %deinterleave } define { , } @deinterleave_nxi64_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define { , } @deinterleave_nxi64_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv2i64( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret { , } [[LDN]] ; %load = load , ptr %ptr, align 8 %deinterleave = tail call { , } @llvm.experimental.vector.deinterleave2.nxv4i64( %load) ret { , } %deinterleave } define { , } @deinterleave_nxfloat_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define { , } @deinterleave_nxfloat_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv4f32( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret { , } [[LDN]] ; %load = load , ptr %ptr, align 4 %deinterleave = tail call { , } @llvm.experimental.vector.deinterleave2.nxv8f32( %load) ret { , } %deinterleave } define { , } @deinterleave_nxdouble_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define { , } @deinterleave_nxdouble_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv2f64( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret { , } [[LDN]] ; %load = load , ptr %ptr, align 8 %deinterleave = tail call { , } @llvm.experimental.vector.deinterleave2.nxv4f64( %load) ret { , } %deinterleave } define { , } @deinterleave_nxptr_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define { , } @deinterleave_nxptr_factor2 ; CHECK-SAME: (ptr [[PTR:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[LDN:%.*]] = call { , } @llvm.aarch64.sve.ld2.sret.nxv2p0( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret { , } [[LDN]] ; %load = load , ptr %ptr, align 8 %deinterleave = tail call { , } @llvm.experimental.vector.deinterleave2.nxv4p0( %load) ret { , } %deinterleave } 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( [[L]], [[R]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.experimental.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( [[L]], [[R]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.experimental.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( [[L]], [[R]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.experimental.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( [[L]], [[R]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.experimental.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( [[L]], [[R]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.experimental.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( [[L]], [[R]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.experimental.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( [[L]], [[R]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[PTR]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.experimental.vector.interleave2.nxv4p0( %l, %r) store %interleave, ptr %ptr, align 4 ret void } ;;; Check that we 'legalize' operations that are wider than the target supports. define { , } @deinterleave_wide_nxi32_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define { , } @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( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), 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( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), 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( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), 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( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), 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: ret { , } [[TMP22]] ; %load = load , ptr %ptr, align 4 %deinterleave = tail call { , } @llvm.experimental.vector.deinterleave2.nxv32i32( %load) ret { , } %deinterleave } define { , } @deinterleave_wide_nxdouble_factor2(ptr %ptr) #0 { ; CHECK-LABEL: define { , } @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( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), 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( shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), 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: ret { , } [[TMP12]] ; %load = load , ptr %ptr, align 8 %deinterleave = tail call { , } @llvm.experimental.vector.deinterleave2.nxv8f64( %load) ret { , } %deinterleave } 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( [[TMP2]], [[TMP3]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), 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( [[TMP5]], [[TMP6]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer), ptr [[TMP4]]) ; CHECK-NEXT: ret void ; %interleave = tail call @llvm.experimental.vector.interleave2.nxv8f64( %l, %r) store %interleave, ptr %ptr, align 4 ret void } declare { , } @llvm.experimental.vector.deinterleave2.nxv32i8() declare { , } @llvm.experimental.vector.deinterleave2.nxv16i16() declare { , } @llvm.experimental.vector.deinterleave2.nxv8i32() declare { , } @llvm.experimental.vector.deinterleave2.nxv4i64() declare { , } @llvm.experimental.vector.deinterleave2.nxv8f32() declare { , } @llvm.experimental.vector.deinterleave2.nxv4f64() declare { , } @llvm.experimental.vector.deinterleave2.nxv4p0() ; Larger deinterleaves to test 'legalization' declare { , } @llvm.experimental.vector.deinterleave2.nxv32i32() declare { , } @llvm.experimental.vector.deinterleave2.nxv8f64() declare @llvm.experimental.vector.interleave2.nxv32i8(, ) declare @llvm.experimental.vector.interleave2.nxv16i16(, ) declare @llvm.experimental.vector.interleave2.nxv8i32(, ) declare @llvm.experimental.vector.interleave2.nxv4i64(, ) declare @llvm.experimental.vector.interleave2.nxv8f32(, ) declare @llvm.experimental.vector.interleave2.nxv4f64(, ) declare @llvm.experimental.vector.interleave2.nxv4p0(, ) ; Larger interleaves to test 'legalization' declare @llvm.experimental.vector.interleave2.nxv8f64(, ) attributes #0 = { vscale_range(1,16) "target-features"="+sve" }