diff --git a/llvm/include/llvm/Analysis/MemoryLocation.h b/llvm/include/llvm/Analysis/MemoryLocation.h --- a/llvm/include/llvm/Analysis/MemoryLocation.h +++ b/llvm/include/llvm/Analysis/MemoryLocation.h @@ -253,10 +253,14 @@ static MemoryLocation getForDest(const MemIntrinsic *MI); static MemoryLocation getForDest(const AtomicMemIntrinsic *MI); static MemoryLocation getForDest(const AnyMemIntrinsic *MI); + /// The result returned is only correct in contexts where \p CI is guaranteed + /// to execute. static Optional getForDest(const CallBase *CI, const TargetLibraryInfo &TLI); /// Return a location representing a particular argument of a call. + /// The result returned is only correct in contexts where \p Call is + /// guaranteed to execute. static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI); static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, 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 @@ -137,6 +137,7 @@ LibFunc LF; if (TLI.getLibFunc(*CB, LF) && TLI.has(LF)) { switch (LF) { + case LibFunc_memset_chk: case LibFunc_strncpy: case LibFunc_strcpy: case LibFunc_strcat: @@ -254,7 +255,7 @@ if (const auto *Len = dyn_cast(Call->getArgOperand(2))) { // memset_chk writes at most Len bytes. It may write less, if Len // exceeds the specified max size and aborts. - Size = LocationSize::upperBound(Len->getZExtValue()); + Size = LocationSize::precise(Len->getZExtValue()); } return MemoryLocation(Arg, Size, AATags); } diff --git a/llvm/test/Transforms/DeadStoreElimination/libcalls.ll b/llvm/test/Transforms/DeadStoreElimination/libcalls.ll --- a/llvm/test/Transforms/DeadStoreElimination/libcalls.ll +++ b/llvm/test/Transforms/DeadStoreElimination/libcalls.ll @@ -468,8 +468,7 @@ ; strncpy -> __memset_chk, full overwrite define void @dse_strncpy_memset_chk_test1(i8* noalias %out, i8* noalias %in, i64 %n) { ; CHECK-LABEL: @dse_strncpy_memset_chk_test1( -; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @strncpy(i8* [[OUT:%.*]], i8* [[IN:%.*]], i64 100) -; CHECK-NEXT: [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT]], i32 42, i64 100, i64 [[N:%.*]]) +; CHECK-NEXT: [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT:%.*]], i32 42, i64 100, i64 [[N:%.*]]) ; CHECK-NEXT: ret void ; %call = tail call i8* @strncpy(i8* %out, i8* %in, i64 100) @@ -481,8 +480,7 @@ define void @dse_memset_chk_cannot_eliminates_store(i8* %out, i64 %n) { ; CHECK-LABEL: @dse_memset_chk_cannot_eliminates_store( -; CHECK-NEXT: store i8 10, i8* [[OUT:%.*]], align 1 -; CHECK-NEXT: [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT]], i32 42, i64 100, i64 [[N:%.*]]) +; CHECK-NEXT: [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT:%.*]], i32 42, i64 100, i64 [[N:%.*]]) ; CHECK-NEXT: ret void ; store i8 10, i8* %out @@ -494,7 +492,6 @@ ; CHECK-LABEL: @dse_memset_chk_eliminates_store_local_object_escapes_after( ; CHECK-NEXT: [[A:%.*]] = alloca [200 x i8], align 1 ; CHECK-NEXT: [[OUT:%.*]] = bitcast [200 x i8]* [[A]] to i8* -; CHECK-NEXT: store i8 10, i8* [[OUT]], align 1 ; CHECK-NEXT: [[OUT_100:%.*]] = getelementptr i8, i8* [[OUT]], i64 100 ; CHECK-NEXT: store i8 10, i8* [[OUT_100]], align 1 ; CHECK-NEXT: [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT]], i32 42, i64 100, i64 [[N:%.*]]) @@ -516,7 +513,6 @@ ; CHECK-NEXT: [[A:%.*]] = alloca [200 x i8], align 1 ; CHECK-NEXT: [[OUT:%.*]] = bitcast [200 x i8]* [[A]] to i8* ; CHECK-NEXT: call void @use(i8* [[OUT]]) -; CHECK-NEXT: store i8 10, i8* [[OUT]], align 1 ; CHECK-NEXT: [[OUT_100:%.*]] = getelementptr i8, i8* [[OUT]], i64 100 ; CHECK-NEXT: store i8 0, i8* [[OUT_100]], align 1 ; CHECK-NEXT: [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT]], i32 42, i64 100, i64 [[N:%.*]])