From: Erik Eckstein Date: Wed, 4 Mar 2015 18:57:11 +0000 (+0000) Subject: Add a lock() function in PassRegistry to speed up multi-thread synchronization. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=953be88190e2937fa546a9adf01b90e5d362123e;p=oota-llvm.git Add a lock() function in PassRegistry to speed up multi-thread synchronization. When calling lock() after all passes are registered, the PassRegistry doesn't need a mutex anymore to look up passes. This speeds up multithreaded llvm execution by ~5% (tested with 4 threads). In an asserts build of llvm this has an even bigger impact. Note that it's not required to use the lock function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231276 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/PassRegistry.h b/include/llvm/PassRegistry.h index 8c28ef5e7e6..13fc01a9de2 100644 --- a/include/llvm/PassRegistry.h +++ b/include/llvm/PassRegistry.h @@ -41,6 +41,9 @@ struct PassRegistrationListener; class PassRegistry { mutable sys::SmartRWMutex Lock; + /// Only if false, synchronization must use the Lock mutex. + std::atomic locked; + /// PassInfoMap - Keep track of the PassInfo object for each registered pass. typedef DenseMap MapType; MapType PassInfoMap; @@ -52,7 +55,7 @@ class PassRegistry { std::vector Listeners; public: - PassRegistry() {} + PassRegistry() : locked(false) {} ~PassRegistry(); /// getPassRegistry - Access the global registry object, which is @@ -60,6 +63,10 @@ public: /// llvm_shutdown. static PassRegistry *getPassRegistry(); + /// Enables fast thread synchronization in getPassInfo(). + /// After calling lock() no more passes may be registered. + void lock() { locked = true; } + /// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass' /// type identifier (&MyPass::ID). const PassInfo *getPassInfo(const void *TI) const; diff --git a/lib/IR/PassRegistry.cpp b/lib/IR/PassRegistry.cpp index b879fef3f4a..6002e6849d7 100644 --- a/lib/IR/PassRegistry.cpp +++ b/lib/IR/PassRegistry.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/PassRegistry.h" +#include "llvm/ADT/Optional.h" #include "llvm/IR/Function.h" #include "llvm/PassSupport.h" #include "llvm/Support/Compiler.h" @@ -39,13 +40,23 @@ PassRegistry *PassRegistry::getPassRegistry() { PassRegistry::~PassRegistry() {} const PassInfo *PassRegistry::getPassInfo(const void *TI) const { - sys::SmartScopedReader Guard(Lock); + // We don't need thread synchronization after the PassRegistry is locked + // (that means: is read-only). + Optional> Guard; + if (!locked) + Guard.emplace(Lock); + MapType::const_iterator I = PassInfoMap.find(TI); return I != PassInfoMap.end() ? I->second : nullptr; } const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const { - sys::SmartScopedReader Guard(Lock); + // We don't need thread synchronization after the PassRegistry is locked + // (that means: is read-only). + Optional> Guard; + if (!locked) + Guard.emplace(Lock); + StringMapType::const_iterator I = PassInfoStringMap.find(Arg); return I != PassInfoStringMap.end() ? I->second : nullptr; } @@ -55,6 +66,9 @@ const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const { // void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) { + + assert(!locked && "Trying to register a pass in a locked PassRegistry"); + sys::SmartScopedWriter Guard(Lock); bool Inserted = PassInfoMap.insert(std::make_pair(PI.getTypeInfo(), &PI)).second; @@ -68,6 +82,8 @@ void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) { if (ShouldFree) ToFree.push_back(std::unique_ptr(&PI)); + + assert(!locked && "PassRegistry locked during registering a pass"); } void PassRegistry::enumerateWith(PassRegistrationListener *L) {