[PATCH] D115167: [DSE] Use precise loc for memset_chk writing to local objects.
Florian Hahn via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 8 07:53:47 PST 2021
fhahn updated this revision to Diff 392782.
fhahn added a comment.
In D115167#3177439 <https://reviews.llvm.org/D115167#3177439>, @efriedma wrote:
> In D115167#3176652 <https://reviews.llvm.org/D115167#3176652>, @fhahn wrote:
>
>> It might have been overly conservative on my side. I was thinking about cases where a failing `memset_chk` aborts the current thread/process but not other threads or processes that may access the same (shared) memory. But if that's not an issue the restriction can be removed.
>
> memset_chk aborts the whole process. Throwing an exception on an out-of-bounds access is a popular model in other contexts, but memset_chk is not defined that way. It's meant purely as a hardening measure.
>
> memset_chk should not be used on memory shared with other processes. Accesses to such memory should be volatile or atomic; otherwise, weird stuff can happen for a variety of reasons...
Sounds good, thanks! I remove the local-object restriction and added a comment explaining why using the precise bound is fine here.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D115167/new/
https://reviews.llvm.org/D115167
Files:
llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
llvm/test/Transforms/DeadStoreElimination/libcalls.ll
Index: llvm/test/Transforms/DeadStoreElimination/libcalls.ll
===================================================================
--- llvm/test/Transforms/DeadStoreElimination/libcalls.ll
+++ 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:%.*]])
Index: llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1022,7 +1022,7 @@
return I.first->second;
}
- Optional<MemoryLocation> getLocForWriteEx(Instruction *I) const {
+ Optional<MemoryLocation> getLocForWriteEx(Instruction *I) {
if (!I->mayWriteToMemory())
return None;
@@ -1032,6 +1032,19 @@
!CB->onlyAccessesInaccessibleMemOrArgMem())
return None;
+ LibFunc F;
+ if (TLI.getLibFunc(*CB, F) && TLI.has(F) && F == LibFunc_memset_chk) {
+ // For the uses in DSE, it is safe to use the precise location instead
+ // of an upper bound. DSE uses the location information to remove
+ // earlier or later stores with the assumption that the memset_chk
+ // executes. So it either writes exactly the number of specified bytes
+ // or the program gets aborted.
+ if (const auto *Len = dyn_cast<ConstantInt>(CB->getArgOperand(2))) {
+ Value *Ptr = CB->getArgOperand(0);
+ return MemoryLocation(Ptr, LocationSize::precise(Len->getZExtValue()),
+ CB->getAAMetadata());
+ }
+ }
return MemoryLocation::getForDest(CB, TLI);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D115167.392782.patch
Type: text/x-patch
Size: 3699 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211208/1b0ff7e6/attachment.bin>
More information about the llvm-commits
mailing list