diff options
author | Kostya Serebryany <kcc@google.com> | 2012-04-10 22:29:17 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2012-04-10 22:29:17 +0000 |
commit | cff60c1409e36079b4bc6ecbda84565143bf00af (patch) | |
tree | 37ee207e2155b163af6bc0da9fa27ebccbe92a1d /lib/Transforms/Instrumentation/ThreadSanitizer.cpp | |
parent | 3aef2ff514c879f98571fb91ddbe1142466a6266 (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.cpp | 53 |
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); |