aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2016-03-29 23:19:40 +0000
committerAnna Zaks <ganna@apple.com>2016-03-29 23:19:40 +0000
commit1a470b6f7cc2530db8ef28222e5b094f7fdc8825 (patch)
tree4e2bd091d48056621241bf1beedac822f63c7cac /llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
parent0d234c382e87e57c083dc6853233b097e8b31f9c (diff)
downloadllvm-1a470b6f7cc2530db8ef28222e5b094f7fdc8825.zip
llvm-1a470b6f7cc2530db8ef28222e5b094f7fdc8825.tar.gz
llvm-1a470b6f7cc2530db8ef28222e5b094f7fdc8825.tar.bz2
[tsan] Do not instrument reads/writes to instruction profile counters.
We have known races on profile counters, which can be reproduced by enabling -fsanitize=thread and -fprofile-instr-generate simultaneously on a multi-threaded program. This patch avoids reporting those races by not instrumenting the reads and writes coming from the instruction profiler. llvm-svn: 264805
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp')
-rw-r--r--llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp26
1 files changed, 25 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
index e73a4b2..38d87cb 100644
--- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -36,6 +36,7 @@
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
+#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
@@ -243,6 +244,24 @@ static bool isVtableAccess(Instruction *I) {
return false;
}
+// Do not instrument known races/"benign races" that come from compiler
+// instrumentatin. The user has no way of suppressing them.
+bool shouldInstrumentReadWriteFromAddress(Value *Addr) {
+ // Peel off GEPs and BitCasts.
+ Addr = Addr->stripInBoundsOffsets();
+
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) {
+ if (GV->hasSection()) {
+ StringRef SectionName = GV->getSection();
+ // Check if the global is in the PGO counters section.
+ if (SectionName.endswith(getInstrProfCountersSectionName(
+ /*AddSegment=*/false)))
+ return false;
+ }
+ }
+ return true;
+}
+
bool ThreadSanitizer::addrPointsToConstantData(Value *Addr) {
// If this is a GEP, just analyze its pointer operand.
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr))
@@ -285,10 +304,15 @@ void ThreadSanitizer::chooseInstructionsToInstrument(
E = Local.rend(); It != E; ++It) {
Instruction *I = *It;
if (StoreInst *Store = dyn_cast<StoreInst>(I)) {
- WriteTargets.insert(Store->getPointerOperand());
+ Value *Addr = Store->getPointerOperand();
+ if (!shouldInstrumentReadWriteFromAddress(Addr))
+ continue;
+ WriteTargets.insert(Addr);
} else {
LoadInst *Load = cast<LoadInst>(I);
Value *Addr = Load->getPointerOperand();
+ if (!shouldInstrumentReadWriteFromAddress(Addr))
+ continue;
if (WriteTargets.count(Addr)) {
// We will write to this temp, so no reason to analyze the read.
NumOmittedReadsBeforeWrite++;