diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -13902,9 +13902,24 @@ case Intrinsic::aarch64_neon_ld3r: case Intrinsic::aarch64_neon_ld4r: { Info.opc = ISD::INTRINSIC_W_CHAIN; - // Conservatively set memVT to the entire set of vectors loaded. - uint64_t NumElts = DL.getTypeSizeInBits(I.getType()) / 64; - Info.memVT = EVT::getVectorVT(I.getType()->getContext(), MVT::i64, NumElts); + unsigned VNumPerVec = 0; + // ldx return struct with the same vec type + Type *RetTy = I.getType(); + auto *StructTy = cast(RetTy); + unsigned VecNum = StructTy->getNumElements(); + Type *VecTy = StructTy->getElementType(0); + MVT VecVT = MVT::getVT(VecTy); + MVT EleVT = VecVT.getVectorElementType(); + + if (Intrinsic == Intrinsic::aarch64_neon_ld2lane || + Intrinsic == Intrinsic::aarch64_neon_ld3lane || + Intrinsic == Intrinsic::aarch64_neon_ld4lane) + VNumPerVec = 1; + else + VNumPerVec = VecVT.getVectorNumElements(); + + Info.memVT = + EVT::getVectorVT(I.getType()->getContext(), EleVT, VecNum * VNumPerVec); Info.ptrVal = I.getArgOperand(I.arg_size() - 1); Info.offset = 0; Info.align.reset(); @@ -13922,15 +13937,29 @@ case Intrinsic::aarch64_neon_st3lane: case Intrinsic::aarch64_neon_st4lane: { Info.opc = ISD::INTRINSIC_VOID; - // Conservatively set memVT to the entire set of vectors stored. - unsigned NumElts = 0; + unsigned VecNum = 0; + unsigned VNumPerVec = 0; + // all the vector type is same + Type *VecTy = I.getArgOperand(0)->getType(); + MVT VecVT = MVT::getVT(VecTy); + MVT EleVT = VecVT.getVectorElementType(); + for (const Value *Arg : I.args()) { Type *ArgTy = Arg->getType(); if (!ArgTy->isVectorTy()) break; - NumElts += DL.getTypeSizeInBits(ArgTy) / 64; + VecNum += 1; } - Info.memVT = EVT::getVectorVT(I.getType()->getContext(), MVT::i64, NumElts); + + if (Intrinsic == Intrinsic::aarch64_neon_st2lane || + Intrinsic == Intrinsic::aarch64_neon_st3lane || + Intrinsic == Intrinsic::aarch64_neon_st4lane) + VNumPerVec = 1; + else + VNumPerVec = VecVT.getVectorNumElements(); + + Info.memVT = + EVT::getVectorVT(I.getType()->getContext(), EleVT, VecNum * VNumPerVec); Info.ptrVal = I.getArgOperand(I.arg_size() - 1); Info.offset = 0; Info.align.reset(); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -2370,7 +2370,7 @@ } ; CHECK-LABEL: name: test_llvm.aarch64.neon.ld3.v4i32.p0i32 -; CHECK: %1:_(<4 x s32>), %2:_(<4 x s32>), %3:_(<4 x s32>) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.neon.ld3), %0(p0) :: (load (s384) from %ir.ptr, align 64) +; CHECK: %1:_(<4 x s32>), %2:_(<4 x s32>), %3:_(<4 x s32>) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.neon.ld3), %0(p0) :: (load (<12 x s32>) from %ir.ptr, align 64) define void @test_llvm.aarch64.neon.ld3.v4i32.p0i32(ptr %ptr) { %arst = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0(ptr %ptr) ret void diff --git a/llvm/test/CodeGen/AArch64/arm64-neon-st-lane-aa.ll b/llvm/test/CodeGen/AArch64/arm64-neon-st-lane-aa.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/arm64-neon-st-lane-aa.ll @@ -0,0 +1,34 @@ +; RUN: llc < %s -mtriple=arm64-none-linux-gnu -mattr=+neon -O2 | FileCheck %s + +; st2 must before two ldrb. +; The situation that put one ldrb before st2 because of the conservative memVT set for st2lane, +; which lead to basic-aa goes wrong. + +define dso_local i32 @test_vst2_lane_u8([2 x <8 x i8>] %vectors.coerce) local_unnamed_addr { +; CHECK-LABEL: test_vst2_lane_u8: +; CHECK: st2 { v0.b, v1.b }[6], [x8] +; CHECK-NEXT: umov w8, v1.b[6] +; CHECK-NEXT: ldrb w9, [sp, #12] +; CHECK-NEXT: ldrb w11, [sp, #13] +entry: + %temp = alloca [2 x i8], align 4 + %vectors.coerce.fca.0.extract = extractvalue [2 x <8 x i8>] %vectors.coerce, 0 + %vectors.coerce.fca.1.extract = extractvalue [2 x <8 x i8>] %vectors.coerce, 1 + call void @llvm.lifetime.start.p0(i64 2, ptr nonnull %temp) #4 + call void @llvm.aarch64.neon.st2lane.v8i8.p0(<8 x i8> %vectors.coerce.fca.0.extract, <8 x i8> %vectors.coerce.fca.1.extract, i64 6, ptr nonnull %temp) + %0 = load i8, ptr %temp, align 4 + %vget_lane = extractelement <8 x i8> %vectors.coerce.fca.0.extract, i64 6 + %cmp8.not = icmp ne i8 %0, %vget_lane + %arrayidx3.1 = getelementptr inbounds [2 x i8], ptr %temp, i64 0, i64 1 + %1 = load i8, ptr %arrayidx3.1, align 1 + %vget_lane.1 = extractelement <8 x i8> %vectors.coerce.fca.1.extract, i64 6 + %cmp8.not.1 = icmp ne i8 %1, %vget_lane.1 + %or.cond = select i1 %cmp8.not, i1 true, i1 %cmp8.not.1 + %cmp.lcssa = zext i1 %or.cond to i32 + call void @llvm.lifetime.end.p0(i64 2, ptr nonnull %temp) #4 + ret i32 %cmp.lcssa +} + +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2 +declare void @llvm.aarch64.neon.st2lane.v8i8.p0(<8 x i8>, <8 x i8>, i64, ptr nocapture) #2 +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2 diff --git a/llvm/test/CodeGen/AArch64/multi-vector-store-size.ll b/llvm/test/CodeGen/AArch64/multi-vector-store-size.ll --- a/llvm/test/CodeGen/AArch64/multi-vector-store-size.ll +++ b/llvm/test/CodeGen/AArch64/multi-vector-store-size.ll @@ -23,8 +23,6 @@ %cr = fadd <4 x float> %cl, %dl %dr = fadd <4 x float> %dl, %al -; The sizes below are conservative. AArch64TargetLowering -; conservatively assumes the entire vector is stored. tail call void @llvm.aarch64.neon.st2.v4f32.p0(<4 x float> %ar, <4 x float> %br, ptr %res) ; CHECK: ST2Twov4s {{.*}} :: (store (s256) {{.*}}) tail call void @llvm.aarch64.neon.st3.v4f32.p0(<4 x float> %ar, <4 x float> %br, <4 x float> %cr, ptr %res) @@ -46,8 +44,6 @@ %cr = fadd <4 x float> %cl, %dl %dr = fadd <4 x float> %dl, %al -; The sizes below are conservative. AArch64TargetLowering -; conservatively assumes the entire vector is stored. tail call void @llvm.aarch64.neon.st1x2.v4f32.p0(<4 x float> %ar, <4 x float> %br, ptr %res) ; CHECK: ST1Twov4s {{.*}} :: (store (s256) {{.*}}) tail call void @llvm.aarch64.neon.st1x3.v4f32.p0(<4 x float> %ar, <4 x float> %br, <4 x float> %cr, ptr %res) @@ -69,14 +65,12 @@ %cr = fadd <4 x float> %cl, %dl %dr = fadd <4 x float> %dl, %al -; The sizes below are conservative. AArch64TargetLowering -; conservatively assumes the entire vector is stored. tail call void @llvm.aarch64.neon.st2lane.v4f32.p0(<4 x float> %ar, <4 x float> %br, i64 1, ptr %res) -; CHECK: ST2i32 {{.*}} :: (store (s256) {{.*}}) +; CHECK: ST2i32 {{.*}} :: (store (s64) {{.*}}) tail call void @llvm.aarch64.neon.st3lane.v4f32.p0(<4 x float> %ar, <4 x float> %br, <4 x float> %cr, i64 1, ptr %res) -; CHECK: ST3i32 {{.*}} :: (store (s384) {{.*}}) +; CHECK: ST3i32 {{.*}} :: (store (s96) {{.*}}) tail call void @llvm.aarch64.neon.st4lane.v4f32.p0(<4 x float> %ar, <4 x float> %br, <4 x float> %cr, <4 x float> %dr, i64 1, ptr %res) -; CHECK: ST4i32 {{.*}} :: (store (s512) {{.*}}) +; CHECK: ST4i32 {{.*}} :: (store (s128) {{.*}}) ret void }