Add a lock() function in PassRegistry to speed up multi-thread synchronization.
authorErik Eckstein <eeckstein@apple.com>
Wed, 4 Mar 2015 18:57:11 +0000 (18:57 +0000)
committerErik Eckstein <eeckstein@apple.com>
Wed, 4 Mar 2015 18:57:11 +0000 (18:57 +0000)
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

include/llvm/PassRegistry.h
lib/IR/PassRegistry.cpp

index 8c28ef5e7e614e9de71e18eb5462ecb2349eb5ea..13fc01a9de2174d28480cb09c82feeea1ebb996a 100644 (file)
@@ -41,6 +41,9 @@ struct PassRegistrationListener;
 class PassRegistry {
   mutable sys::SmartRWMutex<true> Lock;
 
+  /// Only if false, synchronization must use the Lock mutex.
+  std::atomic<bool> locked;
+
   /// PassInfoMap - Keep track of the PassInfo object for each registered pass.
   typedef DenseMap<const void *, const PassInfo *> MapType;
   MapType PassInfoMap;
@@ -52,7 +55,7 @@ class PassRegistry {
   std::vector<PassRegistrationListener *> 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;
index b879fef3f4a725128f0fea00b36c91f0c1e9a3dd..6002e6849d7072da4d5109f61ca8ce063cc16921 100644 (file)
@@ -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<true> Guard(Lock);
+  // We don't need thread synchronization after the PassRegistry is locked
+  // (that means: is read-only).
+  Optional<sys::SmartScopedReader<true>> 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<true> Guard(Lock);
+  // We don't need thread synchronization after the PassRegistry is locked
+  // (that means: is read-only).
+  Optional<sys::SmartScopedReader<true>> 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<true> 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<const PassInfo>(&PI));
+
+  assert(!locked && "PassRegistry locked during registering a pass");
 }
 
 void PassRegistry::enumerateWith(PassRegistrationListener *L) {