diff --git a/llvm/lib/Analysis/MemoryLocation.cpp b/llvm/lib/Analysis/MemoryLocation.cpp --- a/llvm/lib/Analysis/MemoryLocation.cpp +++ b/llvm/lib/Analysis/MemoryLocation.cpp @@ -158,6 +158,7 @@ break; case Intrinsic::memset: case Intrinsic::memcpy: + case Intrinsic::memcpy_inline: case Intrinsic::memmove: assert((ArgIdx == 0 || ArgIdx == 1) && "Invalid argument index for memory intrinsic"); diff --git a/llvm/test/Transforms/DeadStoreElimination/MSSA/memintrinsics.ll b/llvm/test/Transforms/DeadStoreElimination/MSSA/memintrinsics.ll --- a/llvm/test/Transforms/DeadStoreElimination/MSSA/memintrinsics.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MSSA/memintrinsics.ll @@ -2,48 +2,57 @@ ; RUN: opt -S -dse < %s | FileCheck %s declare void @llvm.memcpy.p0i8.p0i8.i8(i8* nocapture, i8* nocapture, i8, i1) nounwind +declare void @llvm.memcpy.inline.p0i8.p0i8.i8(i8* nocapture, i8* nocapture, i8, i1) nounwind declare void @llvm.memmove.p0i8.p0i8.i8(i8* nocapture, i8* nocapture, i8, i1) nounwind declare void @llvm.memset.p0i8.i8(i8* nocapture, i8, i8, i1) nounwind -define void @test1() { +define void @test1(i8* noalias %A, i8* noalias %B) { ; CHECK-LABEL: @test1( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i8(i8* [[A:%.*]], i8* [[B:%.*]], i8 12, i1 false) ; CHECK-NEXT: ret void ; - %A = alloca i8 - %B = alloca i8 - store i8 0, i8* %A ;; Written to by memcpy - call void @llvm.memcpy.p0i8.p0i8.i8(i8* %A, i8* %B, i8 -1, i1 false) + call void @llvm.memcpy.p0i8.p0i8.i8(i8* %A, i8* %B, i8 12, i1 false) ret void } -define void @test2() { +; FIXME: We should eliminate this dead store. +define void @test2(i8* noalias %A, i8* noalias %B) { ; CHECK-LABEL: @test2( +; CHECK-NEXT: store i8 0, i8* [[A:%.*]], align 1 +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i8(i8* [[A]], i8* [[B:%.*]], i8 12, i1 false) ; CHECK-NEXT: ret void ; - %A = alloca i8 - %B = alloca i8 + store i8 0, i8* %A ;; Written to by memmove + + call void @llvm.memmove.p0i8.p0i8.i8(i8* %A, i8* %B, i8 12, i1 false) + ret void +} + +define void @test2a(i8* %A, i8* %B) { +; CHECK-LABEL: @test2a( +; CHECK-NEXT: store i8 0, i8* [[A:%.*]], align 1 +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i8(i8* [[A]], i8* [[B:%.*]], i8 12, i1 false) +; CHECK-NEXT: ret void +; store i8 0, i8* %A ;; Written to by memmove - call void @llvm.memmove.p0i8.p0i8.i8(i8* %A, i8* %B, i8 -1, i1 false) + call void @llvm.memmove.p0i8.p0i8.i8(i8* %A, i8* %B, i8 12, i1 false) ret void } -define void @test3() { +define void @test3(i8* noalias %A) { ; CHECK-LABEL: @test3( -; CHECK-NEXT: [[B:%.*]] = alloca i8, align 1 +; CHECK-NEXT: call void @llvm.memset.p0i8.i8(i8* [[A:%.*]], i8 0, i8 12, i1 false) ; CHECK-NEXT: ret void ; - %A = alloca i8 - %B = alloca i8 - store i8 0, i8* %A ;; Written to by memset - call void @llvm.memset.p0i8.i8(i8* %A, i8 0, i8 -1, i1 false) + call void @llvm.memset.p0i8.i8(i8* %A, i8 0, i8 12, i1 false) ret void } @@ -97,3 +106,15 @@ ret void } + +define void @test7(i8* noalias %A, i8* noalias %B) { +; CHECK-LABEL: @test7( +; CHECK-NEXT: call void @llvm.memcpy.inline.p0i8.p0i8.i8(i8* [[A:%.*]], i8* [[B:%.*]], i8 12, i1 false) +; CHECK-NEXT: ret void +; + store i8 0, i8* %A ;; Written to by memcpy + + call void @llvm.memcpy.inline.p0i8.p0i8.i8(i8* %A, i8* %B, i8 12, i1 false) + + ret void +} diff --git a/llvm/test/Transforms/DeadStoreElimination/MSSA/memset-and-memcpy.ll b/llvm/test/Transforms/DeadStoreElimination/MSSA/memset-and-memcpy.ll --- a/llvm/test/Transforms/DeadStoreElimination/MSSA/memset-and-memcpy.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MSSA/memset-and-memcpy.ll @@ -94,19 +94,29 @@ } define void @test_memset_memcpy_inline(i8* noalias %P, i8* noalias %Q) { +; CHECK-LABEL: @test_memset_memcpy_inline( +; CHECK-NEXT: tail call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i1 false) +; CHECK-NEXT: ret void +; tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 false) tail call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i1 false) - ret void + ret void } define void @test_store_memcpy_inline(i8* noalias %P, i8* noalias %Q) { +; CHECK-LABEL: @test_store_memcpy_inline( +; CHECK-NEXT: [[P_4:%.*]] = getelementptr i8, i8* [[P:%.*]], i64 4 +; CHECK-NEXT: store i8 4, i8* [[P_4]], align 1 +; CHECK-NEXT: tail call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* align 1 [[P]], i8* align 1 [[Q:%.*]], i64 4, i1 false) +; CHECK-NEXT: ret void +; store i8 0, i8* %P %P.1 = getelementptr i8, i8* %P, i64 1 store i8 1, i8* %P.1 %P.4 = getelementptr i8, i8* %P, i64 4 store i8 4, i8* %P.4 tail call void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 4, i1 false) - ret void + ret void } declare void @llvm.memcpy.inline.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64 immarg, i1 immarg)