aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2012-04-10 22:29:17 +0000
committerKostya Serebryany <kcc@google.com>2012-04-10 22:29:17 +0000
commitcff60c1409e36079b4bc6ecbda84565143bf00af (patch)
tree37ee207e2155b163af6bc0da9fa27ebccbe92a1d /lib/Transforms/Instrumentation/ThreadSanitizer.cpp
parent3aef2ff514c879f98571fb91ddbe1142466a6266 (diff)
[tsan] two more compile-time optimizations:
- don't isntrument reads from constant globals. Saves ~1.5% of instrumented instructions on CPU2006 (counting static instructions, not their execution). - don't insrument reads from vtable (which is a global constant too). Saves ~5%. I did not measure the run-time impact of this, but it is certainly non-negative. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154444 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Instrumentation/ThreadSanitizer.cpp')
-rw-r--r--lib/Transforms/Instrumentation/ThreadSanitizer.cpp53
1 files changed, 42 insertions, 11 deletions
diff --git a/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
index bbadf1a9c9..8bb337eb2b 100644
--- a/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -58,6 +58,8 @@ struct ThreadSanitizerStats {
size_t NumOmittedReadsBeforeWrite;
size_t NumAccessesWithBadSize;
size_t NumInstrumentedVtableWrites;
+ size_t NumOmittedReadsFromConstantGlobals;
+ size_t NumOmittedReadsFromVtable;
};
/// ThreadSanitizer: instrument the code in module to find races.
@@ -72,6 +74,7 @@ struct ThreadSanitizer : public FunctionPass {
private:
void choseInstructionsToInstrument(SmallVectorImpl<Instruction*> &Local,
SmallVectorImpl<Instruction*> &All);
+ bool addrPointsToConstantData(Value *Addr);
TargetData *TD;
OwningPtr<FunctionBlackList> BL;
@@ -145,11 +148,44 @@ bool ThreadSanitizer::doFinalization(Module &M) {
<< "; vt " << stats.NumInstrumentedVtableWrites
<< "; bs " << stats.NumAccessesWithBadSize
<< "; rbw " << stats.NumOmittedReadsBeforeWrite
+ << "; rcg " << stats.NumOmittedReadsFromConstantGlobals
+ << "; rvt " << stats.NumOmittedReadsFromVtable
<< "\n";
}
return true;
}
+static bool isVtableAccess(Instruction *I) {
+ if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa)) {
+ if (Tag->getNumOperands() < 1) return false;
+ if (MDString *Tag1 = dyn_cast<MDString>(Tag->getOperand(0))) {
+ if (Tag1->getString() == "vtable pointer") return true;
+ }
+ }
+ return false;
+}
+
+bool ThreadSanitizer::addrPointsToConstantData(Value *Addr) {
+ // If this is a GEP, just analyze its pointer operand.
+ if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr))
+ Addr = GEP->getPointerOperand();
+
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) {
+ if (GV->isConstant()) {
+ // Reads from constant globals can not race with any writes.
+ stats.NumOmittedReadsFromConstantGlobals++;
+ return true;
+ }
+ } else if(LoadInst *L = dyn_cast<LoadInst>(Addr)) {
+ if (isVtableAccess(L)) {
+ // Reads from a vtable pointer can not race with any writes.
+ stats.NumOmittedReadsFromVtable++;
+ return true;
+ }
+ }
+ return false;
+}
+
// Instrumenting some of the accesses may be proven redundant.
// Currently handled:
// - read-before-write (within same BB, no calls between)
@@ -173,11 +209,16 @@ void ThreadSanitizer::choseInstructionsToInstrument(
WriteTargets.insert(Store->getPointerOperand());
} else {
LoadInst *Load = cast<LoadInst>(I);
- if (WriteTargets.count(Load->getPointerOperand())) {
+ Value *Addr = Load->getPointerOperand();
+ if (WriteTargets.count(Addr)) {
// We will write to this temp, so no reason to analyze the read.
stats.NumOmittedReadsBeforeWrite++;
continue;
}
+ if (addrPointsToConstantData(Addr)) {
+ // Addr points to some constant data -- it can not race with any writes.
+ continue;
+ }
}
All.push_back(I);
}
@@ -236,16 +277,6 @@ bool ThreadSanitizer::runOnFunction(Function &F) {
return Res;
}
-static bool isVtableAccess(Instruction *I) {
- if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa)) {
- if (Tag->getNumOperands() < 1) return false;
- if (MDString *Tag1 = dyn_cast<MDString>(Tag->getOperand(0))) {
- if (Tag1->getString() == "vtable pointer") return true;
- }
- }
- return false;
-}
-
bool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) {
IRBuilder<> IRB(I);
bool IsWrite = isa<StoreInst>(*I);