llvm.org GIT mirror llvm / 4cfcb90
Merging r227299: ------------------------------------------------------------------------ r227299 | chandlerc | 2015-01-28 01:47:21 -0800 (Wed, 28 Jan 2015) | 48 lines [LPM] A targeted but somewhat horrible fix to the legacy pass manager's querying of the pass registry. The pass manager relies on the static registry of PassInfo objects to perform all manner of its functionality. I don't understand why it does much of this. My very vague understanding is that this registry is touched both during static initialization *and* while each pass is being constructed. As a consequence it is hard to make accessing it not require a acquiring some lock. This lock ends up in the hot path of setting up, tearing down, and invaliditing analyses in the legacy pass manager. On most systems you can observe this as a non-trivial % of the time spent in 'ninja check-llvm'. However, I haven't really seen it be more than 1% in extreme cases of compiling more real-world software, including LTO. Unfortunately, some of the GPU JITs are seeing this taking essentially all of their time because they have very small IR running through a small pass pipeline very many times (at least, this is the vague understanding I have of it). This patch tries to minimize the cost of looking up PassInfo objects by leveraging the fact that the objects themselves are immutable and they are allocated separately on the heap and so don't have their address change. It also requires a change I made the last time I tried to debug this problem which removed the ability to de-register a pass from the registry. This patch creates a single access path to these objects inside the PMTopLevelManager which memoizes the result of querying the registry. This is somewhat gross as I don't really know if PMTopLevelManager is the *right* place to put it, and I dislike using a mutable member to memoize things, but it seems to work. For long-lived pass managers this should completely eliminate the cost of acquiring locks to look into the pass registry once the memoized cache is warm. For 'ninja check' I measured about 1.5% reduction in CPU time and in total time on a machine with 32 hardware threads. For normal compilation, I don't know how much this will help, sadly. We will still pay the cost while we populate the memoized cache. I don't think it will hurt though, and for LTO or compiles with many small functions it should still be a win. However, for tight loops around a pass manager with many passes and small modules, this will help tremendously. On the AArch64 backend I saw nearly 50% reductions in time to complete 2000 cycles of spinning up and tearing down the pipeline. Measurements from Owen of an actual long-lived pass manager show more along the lines of 10% improvements. Differential Revision: http://reviews.llvm.org/D7213 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_36@227331 91177308-0d34-0410-b5e6-96231b3b80d8 Hans Wennborg 5 years ago
2 changed file(s) with 31 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
194194 /// then return NULL.
195195 Pass *findAnalysisPass(AnalysisID AID);
196196
197 /// Retrieve the PassInfo for an analysis.
198 const PassInfo *findAnalysisPassInfo(AnalysisID AID) const;
199
197200 /// Find analysis usage information for the pass P.
198201 AnalysisUsage *findAnalysisUsage(Pass *P);
199202
250253 SmallVector ImmutablePasses;
251254
252255 DenseMap AnUsageMap;
256
257 /// Collection of PassInfo objects found via analysis IDs and in this top
258 /// level manager. This is used to memoize queries to the pass registry.
259 /// FIXME: This is an egregious hack because querying the pass registry is
260 /// either slow or racy.
261 mutable DenseMap AnalysisPassInfos;
253262 };
254263
255264
599599 // If P is an analysis pass and it is available then do not
600600 // generate the analysis again. Stale analysis info should not be
601601 // available at this point.
602 const PassInfo *PI =
603 PassRegistry::getPassRegistry()->getPassInfo(P->getPassID());
602 const PassInfo *PI = findAnalysisPassInfo(P->getPassID());
604603 if (PI && PI->isAnalysis() && findAnalysisPass(P->getPassID())) {
605604 delete P;
606605 return;
618617
619618 Pass *AnalysisPass = findAnalysisPass(*I);
620619 if (!AnalysisPass) {
621 const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(*I);
620 const PassInfo *PI = findAnalysisPassInfo(*I);
622621
623622 if (!PI) {
624623 // Pass P is not in the global PassRegistry
715714 return *I;
716715
717716 // If Pass not found then check the interfaces implemented by Immutable Pass
718 const PassInfo *PassInf =
719 PassRegistry::getPassRegistry()->getPassInfo(PI);
717 const PassInfo *PassInf = findAnalysisPassInfo(PI);
720718 assert(PassInf && "Expected all immutable passes to be initialized");
721719 const std::vector &ImmPI =
722720 PassInf->getInterfacesImplemented();
730728 return nullptr;
731729 }
732730
731 const PassInfo *PMTopLevelManager::findAnalysisPassInfo(AnalysisID AID) const {
732 const PassInfo *&PI = AnalysisPassInfos[AID];
733 if (!PI)
734 PI = PassRegistry::getPassRegistry()->getPassInfo(AID);
735 else
736 assert(PI == PassRegistry::getPassRegistry()->getPassInfo(AID) &&
737 "The pass info pointer changed for an analysis ID!");
738
739 return PI;
740 }
741
733742 // Print passes managed by this top level manager.
734743 void PMTopLevelManager::dumpPasses() const {
735744
758767 dbgs() << "Pass Arguments: ";
759768 for (SmallVectorImpl::const_iterator I =
760769 ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)
761 if (const PassInfo *PI =
762 PassRegistry::getPassRegistry()->getPassInfo((*I)->getPassID())) {
770 if (const PassInfo *PI = findAnalysisPassInfo((*I)->getPassID())) {
763771 assert(PI && "Expected all immutable passes to be initialized");
764772 if (!PI->isAnalysisGroup())
765773 dbgs() << " -" << PI->getPassArgument();
823831
824832 // This pass is the current implementation of all of the interfaces it
825833 // implements as well.
826 const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(PI);
834 const PassInfo *PInf = TPM->findAnalysisPassInfo(PI);
827835 if (!PInf) return;
828836 const std::vector &II = PInf->getInterfacesImplemented();
829837 for (unsigned i = 0, e = II.size(); i != e; ++i)
956964 }
957965
958966 AnalysisID PI = P->getPassID();
959 if (const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(PI)) {
967 if (const PassInfo *PInf = TPM->findAnalysisPassInfo(PI)) {
960968 // Remove the pass itself (if it is not already removed).
961969 AvailableAnalysis.erase(PI);
962970
10361044 for (SmallVectorImpl::iterator
10371045 I = ReqAnalysisNotAvailable.begin(),
10381046 E = ReqAnalysisNotAvailable.end() ;I != E; ++I) {
1039 const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(*I);
1047 const PassInfo *PI = TPM->findAnalysisPassInfo(*I);
10401048 Pass *AnalysisPass = PI->createPass();
10411049 this->addLowerLevelRequiredPass(P, AnalysisPass);
10421050 }
11411149 PMD->dumpPassArguments();
11421150 else
11431151 if (const PassInfo *PI =
1144 PassRegistry::getPassRegistry()->getPassInfo((*I)->getPassID()))
1152 TPM->findAnalysisPassInfo((*I)->getPassID()))
11451153 if (!PI->isAnalysisGroup())
11461154 dbgs() << " -" << PI->getPassArgument();
11471155 }
12171225 dbgs() << (const void*)P << std::string(getDepth()*2+3, ' ') << Msg << " Analyses:";
12181226 for (unsigned i = 0; i != Set.size(); ++i) {
12191227 if (i) dbgs() << ',';
1220 const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(Set[i]);
1228 const PassInfo *PInf = TPM->findAnalysisPassInfo(Set[i]);
12211229 if (!PInf) {
12221230 // Some preserved passes, such as AliasAnalysis, may not be initialized by
12231231 // all drivers.
16571665
16581666 OnTheFlyManagers[P] = FPP;
16591667 }
1660 const PassInfo * RequiredPassPI =
1661 PassRegistry::getPassRegistry()->getPassInfo(RequiredPass->getPassID());
1668 const PassInfo *RequiredPassPI =
1669 TPM->findAnalysisPassInfo(RequiredPass->getPassID());
16621670
16631671 Pass *FoundPass = nullptr;
16641672 if (RequiredPassPI && RequiredPassPI->isAnalysis()) {