(Not sure who the best reviewer is, so I've put chandlerc based on CODE_OWNERS and dblaikie based on llvm-dev discussion).
The following trace is taken from Visual Studio by putting Watchpoints in ManagedStaticBase::RegisterManagedStatic, ManagedStaticBase::destroy, and llvm_shutdown
Allocating ManagedStatic 0x0x04ab19d0 {ManagedStatic<llvm::PassRegistry> PassRegistryObj}
Allocating ManagedStatic 0x0x04ab19dc {ManagedStatic<llvm::sys::SmartRWMutex<1> > Lock}
Allocating ManagedStatic 0x0x04ab2d34 {ManagedStatic<llvm::SmallPtrSet<llvm::cl::OptionCategory *,16> > RegisteredOptionCategories}
Allocating ManagedStatic 0x0x04ab2f08 {ManagedStatic<std::string> LibSupportInfoOutputFilename}
Allocating ManagedStatic 0x0x04ab2dd8 {ManagedStatic<llvm::sys::ThreadLocal<llvm::PrettyStackTraceEntry const > > PrettyStackTraceHead}
Allocating ManagedStatic 0x0x04ab2f14 {ManagedStatic<llvm::sys::SmartMutex<1> > TimerLock}
llvm_shutdown
Destroying ManagedStatic 0x0x04ab2f14 {ManagedStatic<llvm::sys::SmartMutex<1> > TimerLock}
Destroying ManagedStatic 0x0x04ab2dd8 {ManagedStatic<llvm::sys::ThreadLocal<llvm::PrettyStackTraceEntry const > > PrettyStackTraceHead} {...}
Destroying ManagedStatic 0x0x04ab2f08 {ManagedStatic<std::string> LibSupportInfoOutputFilename}
Destroying ManagedStatic 0x0x04ab2d34 {ManagedStatic<llvm::SmallPtrSet<llvm::cl::OptionCategory *,16> > RegisteredOptionCategories}
Destroying ManagedStatic 0x0x04ab19dc {ManagedStatic<llvm::sys::SmartRWMutex<1> > Lock}
Destroying ManagedStatic 0x0x04ab19d0 {ManagedStatic<llvm::PassRegistry> PassRegistryObj}
Allocating ManagedStatic 0x0x04ab19dc {ManagedStatic<llvm::sys::SmartRWMutex<1> > Lock}
Destroying ManagedStatic 0x0x04ab19dc {ManagedStatic<llvm::sys::SmartRWMutex<1> > Lock}
Allocating ManagedStatic 0x0x04ab19d0 {ManagedStatic<llvm::PassRegistry> PassRegistryObj}
Allocating ManagedStatic 0x0x04ab19dc {ManagedStatic<llvm::sys::SmartRWMutex<1> > Lock}
From this you can see that ManagedStatics are allocated during llvm_shutdown, and that one of them is the PassRegistry, which has already been allocated and destroyed.
This patch addresses this by introducing a StaticPassRegistry, and having RegisterPass<> write its entries to the StaticPassRegistry. Once main is entered, StaticPassRegistry becomes immutable and its entries are transferred over to the PassRegistry. By doing this, we can guarantee that PassRegistry won't be access during static initialization, and thus we can change PassRegistry's mutex to be a raw static instead of a ManagedStatic.
Eventually, the goal here is to get to a point where ManagedStatic can enforce true once-only initialization of ManagedStatics using std::call_once, guaranteeing that once a ManagedStatic is destroyed it is never allocated again, and also fixing existing race conditions in the implementation of ManagedStatic.