Index: include/llvm/PassRegistry.h =================================================================== --- include/llvm/PassRegistry.h +++ include/llvm/PassRegistry.h @@ -41,6 +41,9 @@ 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 @@ std::vector Listeners; public: - PassRegistry() {} + PassRegistry() : locked(false) {} ~PassRegistry(); /// getPassRegistry - Access the global registry object, which is @@ -60,6 +63,10 @@ /// 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; Index: lib/IR/PassRegistry.cpp =================================================================== --- lib/IR/PassRegistry.cpp +++ lib/IR/PassRegistry.cpp @@ -39,15 +39,29 @@ PassRegistry::~PassRegistry() {} const PassInfo *PassRegistry::getPassInfo(const void *TI) const { - sys::SmartScopedReader Guard(Lock); - MapType::const_iterator I = PassInfoMap.find(TI); - return I != PassInfoMap.end() ? I->second : nullptr; + if (locked) { + // We don't need thread synchronization because the PassInfoMap is read-only + // after the PassRegistry is locked. + MapType::const_iterator I = PassInfoMap.find(TI); + return I != PassInfoMap.end() ? I->second : nullptr; + } else { + sys::SmartScopedReader Guard(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); - StringMapType::const_iterator I = PassInfoStringMap.find(Arg); - return I != PassInfoStringMap.end() ? I->second : nullptr; + if (locked) { + // We don't need thread synchronization because the PassInfoStringMap is + // read-only after the PassRegistry is locked. + StringMapType::const_iterator I = PassInfoStringMap.find(Arg); + return I != PassInfoStringMap.end() ? I->second : nullptr; + } else { + sys::SmartScopedReader Guard(Lock); + StringMapType::const_iterator I = PassInfoStringMap.find(Arg); + return I != PassInfoStringMap.end() ? I->second : nullptr; + } } //===----------------------------------------------------------------------===// @@ -55,6 +69,9 @@ // 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 +85,8 @@ if (ShouldFree) ToFree.push_back(std::unique_ptr(&PI)); + + assert(!locked && "PassRegistry locked during registering a pass"); } void PassRegistry::enumerateWith(PassRegistrationListener *L) {