Index: include/llvm/Analysis/CGSCCPassManager.h =================================================================== --- include/llvm/Analysis/CGSCCPassManager.h +++ include/llvm/Analysis/CGSCCPassManager.h @@ -369,6 +369,7 @@ // Request PassInstrumentation from analysis manager, will use it to run // instrumenting callbacks for the passes later. PassInstrumentation PI = AM.getPassInstrumentation(M); + PI.startPassManager(this, M); PreservedAnalyses PA = PreservedAnalyses::all(); CG.buildRefSCCs(); @@ -504,6 +505,8 @@ PA.preserve(); PA.preserve(); PA.preserve(); + + PI.finishPassManager(this, M); return PA; } @@ -609,6 +612,9 @@ FunctionAnalysisManager &FAM = AM.getResult(C, CG).getManager(); + PassInstrumentation PI = AM.getPassInstrumentation(C, CG); + PI.startPassManager(this, C); + SmallVector Nodes; for (LazyCallGraph::Node &N : C) Nodes.push_back(&N); @@ -631,7 +637,6 @@ Function &F = N->getFunction(); - PassInstrumentation PI = FAM.getPassInstrumentation(F); if (!PI.runBeforePass(&Pass, F)) continue; @@ -671,6 +676,7 @@ // We've also ensured that we updated the call graph along the way. PA.preserve(); + PI.finishPassManager(this, C); return PA; } @@ -714,6 +720,7 @@ PreservedAnalyses PA = PreservedAnalyses::all(); PassInstrumentation PI = AM.getPassInstrumentation(InitialC, CG); + PI.startPassManager(this, InitialC); // The SCC may be refined while we are running passes over it, so set up // a pointer that we can update. @@ -757,6 +764,7 @@ auto CallCounts = ScanSCC(*C, CallHandles); for (int Iteration = 0;; ++Iteration) { + PI.startIteration(this, Iteration); if (!PI.runBeforePass(&Pass, *C)) continue; @@ -852,6 +860,7 @@ // Note that we don't add any preserved entries here unlike a more normal // "pass manager" because we only handle invalidation *between* iterations, // not after the last iteration. + PI.finishPassManager(this, InitialC); return PA; } Index: include/llvm/Analysis/PrintIR.h =================================================================== --- include/llvm/Analysis/PrintIR.h +++ include/llvm/Analysis/PrintIR.h @@ -24,11 +24,11 @@ /// IR-printing wrapper to be installed into PassInstrumentation as BeforePass /// callback -bool printBeforePass(PassInstanceID PassID, Any, PassExecutionCounter); +bool printBeforePass(PassInstanceID PassID, Any, PassExecutionLocation); /// IR-printing wrapper to be installed into PassInstrumentation as AfterPass /// callback -bool printAfterPass(PassInstanceID PassID, Any, PassExecutionCounter); +bool printAfterPass(PassInstanceID PassID, Any, PassExecutionLocation); } // namespace PrintIR Index: include/llvm/IR/PassInstrumentation.h =================================================================== --- include/llvm/IR/PassInstrumentation.h +++ include/llvm/IR/PassInstrumentation.h @@ -24,10 +24,8 @@ /// PassInstrumentation to be easily copyable, which is necessary since it is /// intended to be queried through the analysis framework. /// -/// PassExecutionCounter class tracks pass execution. Currently it is a simple -/// counter, to be enhanced with more sophisticated schemes of tracking the -/// exact execution location as soon as the need for more sophisticated -/// instrumentations arives. +/// PassExecutionLocation class tracks pass execution. Currently it consists of +/// a simple counter plus tracked instance of a current pass manager. /// /// Intended scheme of use for Pass Instrumentation is as follows: /// - register instrumentation callbacks. @@ -151,6 +149,29 @@ bool emptyInstance() const { return Pass == nullptr; } }; +class PassExecutionLocation { + const PassExecutionCounter PC; + PassInstanceID InnerPassManager; + +public: + PassExecutionLocation(PassExecutionCounter PC) : PC(PC) {} + PassExecutionLocation(PassExecutionCounter PC, PassInstanceID PM) : PC(PC) { + setPassManager(PM); + } + PassExecutionLocation(const PassExecutionLocation &) = default; + + void setPassManager(PassInstanceID PM) { + assert(InnerPassManager.emptyInstance() && "invalid initialization"); + assert(!PM.emptyInstance() && "invalid initialization"); + InnerPassManager = PM; + } + + PassExecutionCounter getPC() { return PC; } + PassInstanceID getPM() { return InnerPassManager; } + + operator int() const { return PC; } +}; + /// This class provides actual implementation for pass instrumentation /// interface. It manages callbacks registration, as well as passes control to /// the registered callbacks when Pass Managers call a specific instrumentation @@ -159,10 +180,12 @@ public: // Before/After callbacks accept IRUnits, so they need to take them // as pointers, wrapped with llvm::Any - using BeforePassFunc = bool(PassInstanceID, Any, PassExecutionCounter); - using AfterPassFunc = void(PassInstanceID, Any, PassExecutionCounter); - using BeforeAnalysisFunc = void(PassInstanceID, Any, PassExecutionCounter); - using AfterAnalysisFunc = void(PassInstanceID, Any, PassExecutionCounter); + using BeforePassFunc = bool(PassInstanceID, Any, PassExecutionLocation); + using AfterPassFunc = void(PassInstanceID, Any, PassExecutionLocation); + using BeforeAnalysisFunc = void(PassInstanceID, Any, PassExecutionLocation); + using AfterAnalysisFunc = void(PassInstanceID, Any, PassExecutionLocation); + using PassManagerFunc = void(PassInstanceID, Any, PassExecutionLocation); + using PMIterationFunc = void(PassInstanceID, int, PassExecutionLocation); public: PassInstrumentationImpl() {} @@ -171,22 +194,34 @@ /// pass instance to be executed and constant reference to IR it operates on. /// \Returns true if pass is allowed to be executed. template - bool runBeforePass(PassInstanceID PassID, const IRUnitT &) const; + bool runBeforePass(PassInstanceID PassID, const IRUnitT &IR, + PassInstanceID MainPassID) const; /// AfterPass instrumentation point - takes \p PassID identifier for the /// pass instance to be executed and constant reference to IR it operates on. template - void runAfterPass(PassInstanceID PassID, const IRUnitT &) const; + void runAfterPass(PassInstanceID PassID, const IRUnitT &IR, + PassInstanceID MainPassID) const; template - void runBeforeAnalysis(PassInstanceID PassID, const IRUnitT &) const; + void runBeforeAnalysis(PassInstanceID PassID, const IRUnitT &IR, + PassInstanceID MainPassID) const; template - void runAfterAnalysis(PassInstanceID PassID, const IRUnitT &) const; + void runAfterAnalysis(PassInstanceID PassID, const IRUnitT &IR, + PassInstanceID MainPassID) const; void startPipeline() const; void endPipeline() const; + template + void startPassManager(PassInstanceID PM, const IRUnitT &IR) const; + + template + void finishPassManager(PassInstanceID PM, const IRUnitT &IR) const; + + void startIteration(PassInstanceID PM, int Iteration) const; + void registerBeforePassCallback(const std::function &C) { BeforePassCallbacks.push_back(C); } @@ -212,6 +247,19 @@ EndPipelineCallbacks.push_back(C); } + void + registerStartPassManagerCallback(const std::function &C) { + StartPMCallbacks.push_back(C); + } + void + registerFinishPassManagerCallback(const std::function &C) { + FinishPMCallbacks.push_back(C); + } + + void registerStartIterationCallback(const std::function &C) { + StartIterationCallbacks.push_back(C); + } + PassExecutionCounter &getPC() { return PC; } private: @@ -225,6 +273,9 @@ SmallVector, 4> AfterAnalysisCallbacks; SmallVector, 2> StartPipelineCallbacks; SmallVector, 2> EndPipelineCallbacks; + SmallVector, 2> StartPMCallbacks; + SmallVector, 2> FinishPMCallbacks; + SmallVector, 2> StartIterationCallbacks; }; /// This class provides the main interface for pass instrumentation. @@ -232,6 +283,7 @@ /// to be invoked by PassManagers. template class PassInstrumentation { PassInstrumentationImpl *Impl; + PassInstanceID MainPassID{}; public: PassInstrumentation() : Impl(nullptr) {} @@ -250,31 +302,35 @@ PassInstrumentation &operator=(const PassInstrumentation &PI) { Impl = PI.Impl; + MainPassID = PassInstanceID(); return *this; } PassInstrumentation &operator=(PassInstrumentation &&PI) { Impl = PI.Impl; + MainPassID = PassInstanceID(); return *this; } // pass-instrumentation calls bool runBeforePass(PassInstanceID PassID, const IRUnitT &IR) { - return (Impl ? Impl->runBeforePass(PassID, IR) : true); + if (!Impl) + return true; + return Impl->runBeforePass(PassID, IR, MainPassID); } void runAfterPass(PassInstanceID PassID, const IRUnitT &IR) { if (Impl) - Impl->runAfterPass(PassID, IR); + Impl->runAfterPass(PassID, IR, MainPassID); } void runBeforeAnalysis(PassInstanceID PassID, const IRUnitT &IR) { if (Impl) - Impl->runBeforeAnalysis(PassID, IR); + Impl->runBeforeAnalysis(PassID, IR, MainPassID); } void runAfterAnalysis(PassInstanceID PassID, const IRUnitT &IR) { if (Impl) - Impl->runAfterAnalysis(PassID, IR); + Impl->runAfterAnalysis(PassID, IR, MainPassID); } void startPipeline() { @@ -287,6 +343,35 @@ Impl->endPipeline(); } + template + void startPassManager(PassManagerT *PM, const OtherIRUnitT &IR) { + if (!Impl) + return; + assert(MainPassID.emptyInstance() && "MainPassID should be empty"); + MainPassID = PM; + Impl->startPassManager(MainPassID, IR); + } + + template + void finishPassManager(PassManagerT *PM, const OtherIRUnitT &IR) { + if (!Impl) + return; + assert(!MainPassID.emptyInstance() && "MainPassID not initialized"); + assert(MainPassID.getInstance() == PM && + "MainPassID is improperly initialized"); + Impl->finishPassManager(MainPassID, IR); + } + + template + void startIteration(PassManagerT *PM, int Iteration) { + if (!Impl) + return; + assert(!MainPassID.emptyInstance() && "MainPassID not initialized"); + assert(MainPassID.getInstance() == PM && + "MainPassID is improperly initialized"); + Impl->startIteration(MainPassID, Iteration); + } + void registerBeforePassCallback( const std::function &C) { assert(Impl); @@ -316,7 +401,7 @@ Impl->registerStartPipelineCallback(C); } - void registerEndPpelineCallback(const std::function &C) { + void registerEndPipelineCallback(const std::function &C) { assert(Impl); Impl->registerEndPipelineCallback(C); } Index: include/llvm/IR/PassManager.h =================================================================== --- include/llvm/IR/PassManager.h +++ include/llvm/IR/PassManager.h @@ -453,7 +453,7 @@ // instrumenting callbacks for the passes later. PassInstrumentation PI = AM.getPassInstrumentation(IR, std::tuple(ExtraArgs...)); - + PI.startPassManager(this, IR); if (DebugLogging) dbgs() << "Starting " << getTypeName() << " pass manager run.\n"; @@ -495,6 +495,7 @@ // need to inspect each one individually. PA.preserveSet>(); + PI.finishPassManager(this, IR); if (DebugLogging) dbgs() << "Finished " << getTypeName() << " pass manager run.\n"; @@ -1293,6 +1294,7 @@ // Request PassInstrumentation from analysis manager, will use it to run // instrumenting callbacks for the passes later. PassInstrumentation PI = AM.getPassInstrumentation(M); + PI.startPassManager(this, M); PreservedAnalyses PA = PreservedAnalyses::all(); for (Function &F : M) { @@ -1325,6 +1327,9 @@ // invalidation we needed to do above. PA.preserveSet>(); PA.preserve(); + + PI.finishPassManager(this, M); + return PA; } @@ -1419,9 +1424,12 @@ // to extract AnalysisManager's arguments out of the whole Args set. PassInstrumentation PI = AM.getPassInstrumentation(IR, std::tuple(Args...)); - + PI.startPassManager(this, IR); auto PA = PreservedAnalyses::all(); for (int i = 0; i < Count; ++i) { + // Tell PassInstrumentation that we started a new iteration. + PI.startIteration(this, i); + // Check the PassInstrumentation's BeforePass callbacks before running the // pass, skip its execution completely if asked to (callback returns // false). @@ -1430,6 +1438,7 @@ PA.intersect(P.run(IR, AM, std::forward(Args)...)); PI.runAfterPass(&P, IR); } + PI.finishPassManager(this, IR); return PA; } Index: include/llvm/Transforms/Scalar/LoopPassManager.h =================================================================== --- include/llvm/Transforms/Scalar/LoopPassManager.h +++ include/llvm/Transforms/Scalar/LoopPassManager.h @@ -326,7 +326,7 @@ // Request PassInstrumentation from analysis manager, will use it to run // instrumenting callbacks for the passes later. PassInstrumentation PI = AM.getPassInstrumentation(F); - + PI.startPassManager(this, F); do { Loop *L = Worklist.pop_back_val(); @@ -384,6 +384,8 @@ PA.preserve(); PA.preserve(); PA.preserve(); + + PI.finishPassManager(this, F); return PA; } Index: lib/Analysis/CGSCCPassManager.cpp =================================================================== --- lib/Analysis/CGSCCPassManager.cpp +++ lib/Analysis/CGSCCPassManager.cpp @@ -60,6 +60,7 @@ PassInstrumentation PI = AM.getPassInstrumentation(InitialC, G); + PI.startPassManager(this, InitialC); PreservedAnalyses PA = PreservedAnalyses::all(); if (DebugLogging) @@ -115,6 +116,7 @@ // one individually. PA.preserveSet>(); + PI.finishPassManager(this, InitialC); if (DebugLogging) dbgs() << "Finished CGSCC pass manager run.\n"; Index: lib/Analysis/PrintIR.cpp =================================================================== --- lib/Analysis/PrintIR.cpp +++ lib/Analysis/PrintIR.cpp @@ -74,7 +74,7 @@ } bool PrintIR::printBeforePass(PassInstanceID PassID, Any IR, - PassExecutionCounter PC) { + PassExecutionLocation PC) { StringRef PassName = PassID.Name; if (!llvm::shouldPrintBeforePass(PassName)) return true; @@ -88,7 +88,7 @@ } bool PrintIR::printAfterPass(PassInstanceID PassID, Any IR, - PassExecutionCounter PC) { + PassExecutionLocation PC) { StringRef PassName = PassID.Name; if (!llvm::shouldPrintAfterPass(PassName)) return false; Index: lib/IR/PassInstrumentation.cpp =================================================================== --- lib/IR/PassInstrumentation.cpp +++ lib/IR/PassInstrumentation.cpp @@ -16,35 +16,38 @@ template bool PassInstrumentationImpl::runBeforePass(PassInstanceID PassID, - const IRUnitT &IR) const { + const IRUnitT &IR, + PassInstanceID MainPassID) const { ++PC; bool shouldRun = true; for (auto &C : BeforePassCallbacks) - shouldRun &= C(PassID, llvm::Any(&IR), PC); + shouldRun &= + C(PassID, llvm::Any(&IR), PassExecutionLocation(PC, MainPassID)); return shouldRun; } template void PassInstrumentationImpl::runAfterPass(PassInstanceID PassID, - const IRUnitT &IR) const { + const IRUnitT &IR, + PassInstanceID MainPassID) const { for (auto &C : AfterPassCallbacks) - C(PassID, llvm::Any(&IR), PC); + C(PassID, llvm::Any(&IR), PassExecutionLocation(PC, MainPassID)); } template -void PassInstrumentationImpl::runBeforeAnalysis(PassInstanceID PassID, - const IRUnitT &IR) const { +void PassInstrumentationImpl::runBeforeAnalysis( + PassInstanceID PassID, const IRUnitT &IR, PassInstanceID MainPassID) const { for (auto &C : BeforeAnalysisCallbacks) - C(PassID, llvm::Any(&IR), PC); + C(PassID, llvm::Any(&IR), PassExecutionLocation(PC)); } template -void PassInstrumentationImpl::runAfterAnalysis(PassInstanceID PassID, - const IRUnitT &IR) const { +void PassInstrumentationImpl::runAfterAnalysis( + PassInstanceID PassID, const IRUnitT &IR, PassInstanceID MainPassID) const { for (auto &C : AfterAnalysisCallbacks) - C(PassID, llvm::Any(&IR), PC); + C(PassID, llvm::Any(&IR), PassExecutionLocation(PC)); } void PassInstrumentationImpl::startPipeline() const { @@ -57,43 +60,94 @@ C(); } -template bool PassInstrumentationImpl::runBeforePass(PassInstanceID PassID, - const Module &IR) const; -template bool PassInstrumentationImpl::runBeforePass(PassInstanceID PassID, - const Function &IR) const; -template bool PassInstrumentationImpl::runBeforePass(PassInstanceID PassID, - const Loop &IR) const; +template +void PassInstrumentationImpl::startPassManager(PassInstanceID PM, + const IRUnitT &IR) const { + for (auto &C : StartPMCallbacks) + C(PM, llvm::Any(&IR), PassExecutionLocation(PC, PM)); +} +template +void PassInstrumentationImpl::finishPassManager(PassInstanceID PM, + const IRUnitT &IR) const { + for (auto &C : FinishPMCallbacks) + C(PM, llvm::Any(&IR), PassExecutionLocation(PC, PM)); +} + +void PassInstrumentationImpl::startIteration(PassInstanceID PM, + int Iteration) const { + for (auto &C : StartIterationCallbacks) + C(PM, Iteration, PassExecutionLocation(PC, PM)); +} + +template bool +PassInstrumentationImpl::runBeforePass(PassInstanceID PassID, const Module &IR, + PassInstanceID MainPassID) const; +template bool PassInstrumentationImpl::runBeforePass( + PassInstanceID PassID, const Function &IR, PassInstanceID MainPassID) const; +template bool +PassInstrumentationImpl::runBeforePass(PassInstanceID PassID, const Loop &IR, + PassInstanceID MainPassID) const; template bool PassInstrumentationImpl::runBeforePass(PassInstanceID PassID, - const LazyCallGraph::SCC &IR) const; -template void PassInstrumentationImpl::runAfterPass(PassInstanceID PassID, - const Module &IR) const; -template void PassInstrumentationImpl::runAfterPass(PassInstanceID PassID, - const Function &IR) const; -template void PassInstrumentationImpl::runAfterPass(PassInstanceID PassID, - const Loop &IR) const; + const LazyCallGraph::SCC &IR, + PassInstanceID MainPassID) const; +template void +PassInstrumentationImpl::runAfterPass(PassInstanceID PassID, const Module &IR, + PassInstanceID MainPassID) const; +template void +PassInstrumentationImpl::runAfterPass(PassInstanceID PassID, const Function &IR, + PassInstanceID MainPassID) const; +template void +PassInstrumentationImpl::runAfterPass(PassInstanceID PassID, const Loop &IR, + PassInstanceID MainPassID) const; template void PassInstrumentationImpl::runAfterPass(PassInstanceID PassID, - const LazyCallGraph::SCC &IR) const; + const LazyCallGraph::SCC &IR, + PassInstanceID MainPassID) const; -template void PassInstrumentationImpl::runBeforeAnalysis(PassInstanceID PassID, - const Module &IR) const; -template void PassInstrumentationImpl::runBeforeAnalysis(PassInstanceID PassID, - const Function &IR) const; -template void PassInstrumentationImpl::runBeforeAnalysis(PassInstanceID PassID, - const Loop &IR) const; +template void PassInstrumentationImpl::runBeforeAnalysis( + PassInstanceID PassID, const Module &IR, PassInstanceID MainPassID) const; +template void PassInstrumentationImpl::runBeforeAnalysis( + PassInstanceID PassID, const Function &IR, PassInstanceID MainPassID) const; +template void PassInstrumentationImpl::runBeforeAnalysis( + PassInstanceID PassID, const Loop &IR, PassInstanceID MainPassID) const; template void PassInstrumentationImpl::runBeforeAnalysis(PassInstanceID PassID, - const LazyCallGraph::SCC &IR) const; -template void PassInstrumentationImpl::runAfterAnalysis(PassInstanceID PassID, + const LazyCallGraph::SCC &IR, + PassInstanceID MainPassID) const; +template void PassInstrumentationImpl::runAfterAnalysis( + PassInstanceID PassID, const Module &IR, PassInstanceID MainPassID) const; +template void PassInstrumentationImpl::runAfterAnalysis( + PassInstanceID PassID, const Function &IR, PassInstanceID MainPassID) const; +template void +PassInstrumentationImpl::runAfterAnalysis(PassInstanceID PassID, const Loop &IR, + PassInstanceID MainPassID) const; +template void +PassInstrumentationImpl::runAfterAnalysis(PassInstanceID PassID, + const LazyCallGraph::SCC &IR, + PassInstanceID MainPassID) const; + +template void PassInstrumentationImpl::startPassManager(PassInstanceID PassID, const Module &IR) const; -template void PassInstrumentationImpl::runAfterAnalysis(PassInstanceID PassID, - const Function &IR) const; -template void PassInstrumentationImpl::runAfterAnalysis(PassInstanceID PassID, +template void +PassInstrumentationImpl::startPassManager(PassInstanceID PassID, + const Function &IR) const; +template void PassInstrumentationImpl::startPassManager(PassInstanceID PassID, const Loop &IR) const; template void -PassInstrumentationImpl::runAfterAnalysis(PassInstanceID PassID, +PassInstrumentationImpl::startPassManager(PassInstanceID PassID, const LazyCallGraph::SCC &IR) const; +template void +PassInstrumentationImpl::finishPassManager(PassInstanceID PassID, + const Module &IR) const; +template void +PassInstrumentationImpl::finishPassManager(PassInstanceID PassID, + const Function &IR) const; +template void PassInstrumentationImpl::finishPassManager(PassInstanceID PassID, + const Loop &IR) const; +template void +PassInstrumentationImpl::finishPassManager(PassInstanceID PassID, + const LazyCallGraph::SCC &IR) const; template class PassInstrumentationAnalysis; template class PassInstrumentationAnalysis; Index: lib/Transforms/Scalar/LoopPassManager.cpp =================================================================== --- lib/Transforms/Scalar/LoopPassManager.cpp +++ lib/Transforms/Scalar/LoopPassManager.cpp @@ -35,6 +35,8 @@ // Request PassInstrumentation from analysis manager, will use it to run // instrumenting callbacks for the passes later. PassInstrumentation PI = AM.getPassInstrumentation(L, AR); + PI.startPassManager(this, L); + for (auto &Pass : Passes) { if (DebugLogging) dbgs() << "Running pass: " << Pass->name() << " on " << L; @@ -85,6 +87,8 @@ // be preserved, but unrolling should invalidate the parent loop's analyses. PA.preserveSet>(); + PI.finishPassManager(this, L); + if (DebugLogging) dbgs() << "Finished Loop pass manager run.\n";