diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h index 7ddaf05604b..70b3ea9bad4 100644 --- a/include/llvm/Analysis/CGSCCPassManager.h +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -195,6 +195,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "CGSCCAnalysisManagerModuleProxy"; } + explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} // We have to explicitly define all the special member functions because MSVC @@ -265,6 +267,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerCGSCCProxy"; } + ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC @@ -417,6 +421,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerCGSCCProxy"; } + explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -487,6 +493,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "CGSCCAnalysisManagerFunctionProxy"; } + CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} // We have to explicitly define all the special member functions because MSVC diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h index 4008bb71643..f5697dfe054 100644 --- a/include/llvm/Analysis/LazyCallGraph.h +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -252,6 +252,12 @@ public: /// \brief Test if this SCC is a descendant of \a C. bool isDescendantOf(const SCC &C) const; + /// \brief Short name useful for debugging or logging. + /// + /// We use the name of the first function in the SCC to name the SCC for + /// the purposes of debugging and logging. + StringRef getName() const { return (*begin())->getFunction().getName(); } + ///@{ /// \name Mutation API /// @@ -537,6 +543,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "Lazy CallGraph Analysis"; } + /// \brief Compute the \c LazyCallGraph for the module \c M. /// /// This just builds the set of entry points to the call graph. The rest is diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index db792efca36..b2bf73ffe8b 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -557,6 +557,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerModuleProxy"; } + explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -663,6 +665,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerFunctionProxy"; } + ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h index fb9c210dba2..1b43a72c408 100644 --- a/include/llvm/IR/PassManagerInternal.h +++ b/include/llvm/IR/PassManagerInternal.h @@ -256,6 +256,9 @@ struct AnalysisPassConcept { /// users. virtual std::unique_ptr> run(IRUnitT IR, AnalysisManagerT *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; }; /// \brief Wrapper to model the analysis pass concept. @@ -299,6 +302,11 @@ struct AnalysisPassModel return make_unique(Pass.run(IR, AM)); } + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + PassT Pass; }; @@ -333,6 +341,11 @@ struct AnalysisPassModel return make_unique(Pass.run(IR)); } + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + PassT Pass; }; diff --git a/lib/Analysis/CGSCCPassManager.cpp b/lib/Analysis/CGSCCPassManager.cpp index 7be0afb70b4..4d569a972fe 100644 --- a/lib/Analysis/CGSCCPassManager.cpp +++ b/lib/Analysis/CGSCCPassManager.cpp @@ -84,11 +84,18 @@ void CGSCCAnalysisManager::invalidateImpl(void *PassID, LazyCallGraph::SCC &C) { if (RI == CGSCCAnalysisResults.end()) return; + if (DebugPM) + dbgs() << "Invalidating CGSCC analysis: " << lookupPass(PassID).name() + << "\n"; CGSCCAnalysisResultLists[&C].erase(RI->second); } void CGSCCAnalysisManager::invalidateImpl(LazyCallGraph::SCC &C, const PreservedAnalyses &PA) { + if (DebugPM) + dbgs() << "Invalidating all non-preserved analyses for SCC: " << C.getName() + << "\n"; + // Clear all the invalidated results associated specifically with this // function. SmallVector InvalidatedPassIDs; @@ -97,6 +104,10 @@ void CGSCCAnalysisManager::invalidateImpl(LazyCallGraph::SCC &C, E = ResultsList.end(); I != E;) if (I->second->invalidate(C, PA)) { + if (DebugPM) + dbgs() << "Invalidating CGSCC analysis: " << lookupPass(I->first).name() + << "\n"; + InvalidatedPassIDs.push_back(I->first); I = ResultsList.erase(I); } else { diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp index 121ec001fd1..c7638bb7fce 100644 --- a/lib/IR/PassManager.cpp +++ b/lib/IR/PassManager.cpp @@ -52,8 +52,12 @@ ModuleAnalysisManager::getResultImpl(void *PassID, Module &M) { // If we don't have a cached result for this module, look up the pass and run // it to produce a result, which we then add to the cache. - if (Inserted) - RI->second = lookupPass(PassID).run(M, this); + if (Inserted) { + auto &P = lookupPass(PassID); + if (DebugPM) + dbgs() << "Running module analysis: " << P.name() << "\n"; + RI->second = P.run(M, this); + } return *RI->second; } @@ -66,18 +70,30 @@ ModuleAnalysisManager::getCachedResultImpl(void *PassID, Module &M) const { } void ModuleAnalysisManager::invalidateImpl(void *PassID, Module &M) { + if (DebugPM) + dbgs() << "Invalidating module analysis: " << lookupPass(PassID).name() + << "\n"; ModuleAnalysisResults.erase(PassID); } void ModuleAnalysisManager::invalidateImpl(Module &M, const PreservedAnalyses &PA) { + if (DebugPM) + dbgs() << "Invalidating all non-preserved analyses for module: " + << M.getModuleIdentifier() << "\n"; + // FIXME: This is a total hack based on the fact that erasure doesn't // invalidate iteration for DenseMap. for (ModuleAnalysisResultMapT::iterator I = ModuleAnalysisResults.begin(), E = ModuleAnalysisResults.end(); I != E; ++I) - if (I->second->invalidate(M, PA)) + if (I->second->invalidate(M, PA)) { + if (DebugPM) + dbgs() << "Invalidating module analysis: " + << lookupPass(I->first).name() << "\n"; + ModuleAnalysisResults.erase(I); + } } PreservedAnalyses FunctionPassManager::run(Function &F, @@ -128,8 +144,11 @@ FunctionAnalysisManager::getResultImpl(void *PassID, Function &F) { // If we don't have a cached result for this function, look up the pass and // run it to produce a result, which we then add to the cache. if (Inserted) { + auto &P = lookupPass(PassID); + if (DebugPM) + dbgs() << "Running function analysis: " << P.name() << "\n"; FunctionAnalysisResultListT &ResultList = FunctionAnalysisResultLists[&F]; - ResultList.emplace_back(PassID, lookupPass(PassID).run(F, this)); + ResultList.emplace_back(PassID, P.run(F, this)); RI->second = std::prev(ResultList.end()); } @@ -149,11 +168,18 @@ void FunctionAnalysisManager::invalidateImpl(void *PassID, Function &F) { if (RI == FunctionAnalysisResults.end()) return; + if (DebugPM) + dbgs() << "Invalidating function analysis: " << lookupPass(PassID).name() + << "\n"; FunctionAnalysisResultLists[&F].erase(RI->second); } void FunctionAnalysisManager::invalidateImpl(Function &F, const PreservedAnalyses &PA) { + if (DebugPM) + dbgs() << "Invalidating all non-preserved analyses for function: " + << F.getName() << "\n"; + // Clear all the invalidated results associated specifically with this // function. SmallVector InvalidatedPassIDs; @@ -162,6 +188,10 @@ void FunctionAnalysisManager::invalidateImpl(Function &F, E = ResultsList.end(); I != E;) if (I->second->invalidate(F, PA)) { + if (DebugPM) + dbgs() << "Invalidating function analysis: " + << lookupPass(I->first).name() << "\n"; + InvalidatedPassIDs.push_back(I->first); I = ResultsList.erase(I); } else { diff --git a/test/Other/new-pass-manager.ll b/test/Other/new-pass-manager.ll index 2c565e6944c..f9fc444dbf1 100644 --- a/test/Other/new-pass-manager.ll +++ b/test/Other/new-pass-manager.ll @@ -28,6 +28,8 @@ ; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PRINT ; CHECK-FUNCTION-PRINT: Starting module pass manager ; CHECK-FUNCTION-PRINT: Running module pass: VerifierPass +; CHECK-FUNCTION-PRINT: Running module pass: ModuleToFunctionPassAdaptor +; CHECK-FUNCTION-PRINT: Running module analysis: FunctionAnalysisManagerModuleProxy ; CHECK-FUNCTION-PRINT: Starting function pass manager ; CHECK-FUNCTION-PRINT: Running function pass: PrintFunctionPass ; CHECK-FUNCTION-PRINT-NOT: ModuleID @@ -84,6 +86,14 @@ ; CHECK-NO-VERIFY-NOT: VerifierPass ; CHECK-NO-VERIFY: Finished module pass manager +; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager -passes='cgscc(no-op-cgscc)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-LCG-ANALYSIS +; CHECK-LCG-ANALYSIS: Starting module pass manager +; CHECK-LCG-ANALYSIS: Running module pass: ModuleToPostOrderCGSCCPassAdaptor +; CHECK-LCG-ANALYSIS: Running module analysis: CGSCCAnalysisManagerModuleProxy +; CHECK-LCG-ANALYSIS: Running module analysis: Lazy CallGraph Analysis +; CHECK-LCG-ANALYSIS: Starting CGSCC pass manager run. + define void @foo() { ret void } diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp index d641e36ac6a..41af0b0bd25 100644 --- a/unittests/IR/PassManagerTest.cpp +++ b/unittests/IR/PassManagerTest.cpp @@ -29,6 +29,9 @@ public: /// \brief Returns an opaque, unique ID for this pass type. static void *ID() { return (void *)&PassID; } + /// \brief Returns the name of the analysis. + static StringRef name() { return "TestFunctionAnalysis"; } + TestFunctionAnalysis(int &Runs) : Runs(Runs) {} /// \brief Run the analysis pass over the function and return a result. @@ -60,6 +63,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "TestModuleAnalysis"; } + TestModuleAnalysis(int &Runs) : Runs(Runs) {} Result run(Module &M, ModuleAnalysisManager *AM) {