[PATCH] D83949: [TSan] Do not compound reads and writes when separated by atomics
Marco Elver via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 16 06:48:16 PDT 2020
melver created this revision.
melver added reviewers: dvyukov, glider.
Herald added subscribers: llvm-commits, jfb, hiraditya.
Herald added a project: LLVM.
Do not compound reads and writes to the same address when separated by
atomic operations, including fences.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D83949
Files:
llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
llvm/test/Instrumentation/ThreadSanitizer/read_before_write.ll
Index: llvm/test/Instrumentation/ThreadSanitizer/read_before_write.ll
===================================================================
--- llvm/test/Instrumentation/ThreadSanitizer/read_before_write.ll
+++ llvm/test/Instrumentation/ThreadSanitizer/read_before_write.ll
@@ -37,6 +37,50 @@
declare void @foo()
+define void @IncrementWithFence(i32* nocapture %ptr) nounwind uwtable sanitize_thread {
+entry:
+ %0 = load i32, i32* %ptr, align 4
+ %inc = add nsw i32 %0, 1
+ fence seq_cst
+ store i32 %inc, i32* %ptr, align 4
+ ret void
+}
+
+; CHECK-LABEL: define void @IncrementWithFence
+; CHECK: __tsan_read4
+; CHECK: __tsan_atomic_thread_fence
+; CHECK: __tsan_write4
+; CHECK: ret void
+
+define void @IncrementWithAtomic(i32* nocapture %ptr) nounwind uwtable sanitize_thread {
+entry:
+ %0 = load i32, i32* %ptr, align 4
+ %inc = add nsw i32 %0, 1
+ %1 = load atomic i32, i32* %ptr acquire, align 4
+ store i32 %inc, i32* %ptr, align 4
+ ret void
+}
+
+; CHECK-LABEL: define void @IncrementWithAtomic
+; CHECK: __tsan_read4
+; CHECK: __tsan_atomic32_load
+; CHECK: __tsan_write4
+; CHECK: ret void
+
+define void @IncrementWithAsm(i32* nocapture %ptr) nounwind uwtable sanitize_thread {
+entry:
+ %0 = load i32, i32* %ptr, align 4
+ %inc = add nsw i32 %0, 1
+ call void asm sideeffect "", ""()
+ store i32 %inc, i32* %ptr, align 4
+ ret void
+}
+
+; CHECK-LABEL: define void @IncrementWithAsm
+; CHECK: __tsan_read4
+; CHECK: __tsan_write4
+; CHECK: ret void
+
define void @VolatileLoad(i32* nocapture %ptr) nounwind uwtable sanitize_thread {
entry:
%0 = load volatile i32, i32* %ptr, align 4
Index: llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
===================================================================
--- llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -546,19 +546,27 @@
// Traverse all instructions, collect loads/stores/returns, check for calls.
for (auto &BB : F) {
for (auto &Inst : BB) {
- if (isAtomic(&Inst))
+ bool Barrier = false;
+
+ if (isAtomic(&Inst)) {
AtomicAccesses.push_back(&Inst);
- else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
+ Barrier = true;
+ } else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst)) {
LocalLoadsAndStores.push_back(&Inst);
- else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
+ } else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
if (CallInst *CI = dyn_cast<CallInst>(&Inst))
maybeMarkSanitizerLibraryCallNoBuiltin(CI, &TLI);
if (isa<MemIntrinsic>(Inst))
MemIntrinCalls.push_back(&Inst);
HasCalls = true;
+ Barrier = true;
+ }
+
+ if (Barrier)
+ // Flush instructions found so far, avoiding compounding instrumentation
+ // with any instructions that follow.
chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
DL);
- }
}
chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores, DL);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D83949.278457.patch
Type: text/x-patch
Size: 3125 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200716/aa18bf0c/attachment.bin>
More information about the llvm-commits
mailing list