diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -1022,7 +1022,7 @@ return I.first->second; } - Optional getLocForWriteEx(Instruction *I) const { + Optional getLocForWriteEx(Instruction *I) { if (!I->mayWriteToMemory()) return None; @@ -1032,6 +1032,22 @@ !CB->onlyAccessesInaccessibleMemOrArgMem()) return None; + LibFunc F; + if (TLI.getLibFunc(*CB, F) && TLI.has(F) && F == LibFunc_memset_chk) { + // Use the precise location size specified by the 3rd argument, if the + // accessed object is not visible to the caller at all or does not + // escape before the call. Even if memset_chk terminates, no-one will be + // able to read the accessed memory. + if (const auto *Len = dyn_cast(CB->getArgOperand(2))) { + Value *Ptr = CB->getArgOperand(0); + const Value *UO = getUnderlyingObject(Ptr); + if (isInvisibleToCallerAfterRet(UO) || + EI.isNotCapturedBeforeOrAt(UO, CB)) + return MemoryLocation(Ptr, + LocationSize::precise(Len->getZExtValue()), + CB->getAAMetadata()); + } + } return MemoryLocation::getForDest(CB, TLI); } 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 @@ -494,7 +494,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 +515,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:%.*]])