Index: include/llvm/Analysis/CGSCCPassManager.h =================================================================== --- include/llvm/Analysis/CGSCCPassManager.h +++ include/llvm/Analysis/CGSCCPassManager.h @@ -340,6 +340,11 @@ /// Runs the CGSCC pass across every SCC in the module. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + PassInstrumentation *PI = AM.getPassInstrumentation(M); + if (PI) PI->startPassManager(this, M); + // Setup the CGSCC analysis manager from its proxy. CGSCCAnalysisManager &CGAM = AM.getResult(M).getManager(); @@ -364,10 +369,6 @@ InvalidSCCSet, nullptr, nullptr, InlinedInternalEdges}; - // Request PassInstrumentation from analysis manager, will use it to run - // instrumenting callbacks for the passes later. - PassInstrumentation *PI = AM.getPassInstrumentation(M); - PreservedAnalyses PA = PreservedAnalyses::all(); CG.buildRefSCCs(); for (auto RCI = CG.postorder_ref_scc_begin(), @@ -504,6 +505,9 @@ PA.preserve(); PA.preserve(); PA.preserve(); + + if (PI) + PI->finishPassManager(this, M); return PA; } @@ -605,6 +609,11 @@ /// Runs the function pass across every function in the module. PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR) { + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + PassInstrumentation *PI = AM.getPassInstrumentation(C, CG); + if (PI) PI->startPassManager(this, C); + // Setup the function analysis manager from its proxy. FunctionAnalysisManager &FAM = AM.getResult(C, CG).getManager(); @@ -631,7 +640,6 @@ Function &F = N->getFunction(); - PassInstrumentation *PI = FAM.getPassInstrumentation(F); if (PI && !PI->runBeforePass(&Pass, F)) continue; @@ -672,6 +680,7 @@ // We've also ensured that we updated the call graph along the way. PA.preserve(); + if (PI) PI->finishPassManager(this, C); return PA; } @@ -713,7 +722,10 @@ PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR) { PreservedAnalyses PA = PreservedAnalyses::all(); + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. PassInstrumentation *PI = AM.getPassInstrumentation(InitialC, CG); + if (PI) 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 +769,8 @@ auto CallCounts = ScanSCC(*C, CallHandles); for (int Iteration = 0;; ++Iteration) { + if (PI) + PI->startIteration(this, Iteration); if (PI && !PI->runBeforePass(&Pass, *C)) continue; @@ -850,6 +864,9 @@ PA.intersect(std::move(PassPA)); } + if (PI) + PI->finishPassManager(this, InitialC); + // 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. 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 @@ -21,10 +21,8 @@ /// PassInstrumentation object is intended to have no copies, being /// a single reference point for instrumentation throughout the compilation. /// -/// 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 @@ -143,6 +141,18 @@ bool emptyInstance() const { return Pass == nullptr; } }; +class PassExecutionLocation { + const PassExecutionCounter PC; + +public: + PassExecutionLocation(PassExecutionCounter PC) : PC(PC) {} + PassExecutionLocation(const PassExecutionLocation &) = default; + + PassExecutionCounter getPC() { return PC; } + + operator int() const { return PC; } +}; + /// This class provides 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 @@ -151,10 +161,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: PassInstrumentation() {} @@ -167,22 +179,30 @@ /// 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 &); + bool runBeforePass(PassInstanceID PassID, const IRUnitT &IR); /// 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) const; template - void runBeforeAnalysis(PassInstanceID PassID, const IRUnitT &) const; + void runBeforeAnalysis(PassInstanceID PassID, const IRUnitT &IR) const; template - void runAfterAnalysis(PassInstanceID PassID, const IRUnitT &) const; + void runAfterAnalysis(PassInstanceID PassID, const IRUnitT &IR) 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); } @@ -208,6 +228,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); + } + bool empty() const; private: @@ -221,6 +254,9 @@ SmallVector, 4> AfterAnalysisCallbacks; SmallVector, 2> StartPipelineCallbacks; SmallVector, 2> EndPipelineCallbacks; + SmallVector, 2> StartPMCallbacks; + SmallVector, 2> FinishPMCallbacks; + SmallVector, 2> StartIterationCallbacks; }; } // namespace llvm Index: include/llvm/IR/PassManager.h =================================================================== --- include/llvm/IR/PassManager.h +++ include/llvm/IR/PassManager.h @@ -450,7 +450,8 @@ // instrumenting callbacks for the passes later. PassInstrumentation *PI = AM.getPassInstrumentation(IR, std::tuple(ExtraArgs...)); - + if (PI) + PI->startPassManager(this, IR); if (DebugLogging) dbgs() << "Starting " << getTypeName() << " pass manager run.\n"; @@ -493,6 +494,8 @@ // need to inspect each one individually. PA.preserveSet>(); + if (PI) + PI->finishPassManager(this, IR); if (DebugLogging) dbgs() << "Finished " << getTypeName() << " pass manager run.\n"; @@ -1290,12 +1293,14 @@ /// Runs the function pass across every function in the module. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { - FunctionAnalysisManager &FAM = - AM.getResult(M).getManager(); - // Request PassInstrumentation from analysis manager, will use it to run // instrumenting callbacks for the passes later. PassInstrumentation *PI = AM.getPassInstrumentation(M); + if (PI) + PI->startPassManager(this, M); + + FunctionAnalysisManager &FAM = + AM.getResult(M).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); for (Function &F : M) { @@ -1329,6 +1334,10 @@ // invalidation we needed to do above. PA.preserveSet>(); PA.preserve(); + + if (PI) + PI->finishPassManager(this, M); + return PA; } @@ -1423,9 +1432,14 @@ // to extract AnalysisManager's arguments out of the whole Args set. PassInstrumentation *PI = AM.getPassInstrumentation(IR, std::tuple(Args...)); - + if (PI) + PI->startPassManager(this, IR); auto PA = PreservedAnalyses::all(); for (int i = 0; i < Count; ++i) { + // Tell PassInstrumentation that we started a new iteration. + if (PI) + PI->startIteration(this, i); + // Check the PassInstrumentation's BeforePass callbacks before running the // pass, skip its execution completely if asked to (callback returns // false). @@ -1435,6 +1449,8 @@ if (PI) PI->runAfterPass(&P, IR); } + if (PI) + 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 @@ -277,6 +277,7 @@ // directly build up function analyses after this as the function pass // manager handles all the invalidation at that layer. PassInstrumentation *PI = AM.getPassInstrumentation(F); + if (PI) PI->startPassManager(this, F); PreservedAnalyses PA = PreservedAnalyses::all(); // Check the PassInstrumentation's BeforePass callbacks before running the @@ -389,6 +390,8 @@ PA.preserve(); PA.preserve(); PA.preserve(); + + if (PI) PI->finishPassManager(this, F); return PA; } Index: lib/Analysis/CGSCCPassManager.cpp =================================================================== --- lib/Analysis/CGSCCPassManager.cpp +++ lib/Analysis/CGSCCPassManager.cpp @@ -57,6 +57,7 @@ // Request PassInstrumentation from analysis manager, will use it to run // instrumenting callbacks for the passes later. PassInstrumentation *PI = AM.getPassInstrumentation(InitialC, G); + if (PI) PI->startPassManager(this, InitialC); PreservedAnalyses PA = PreservedAnalyses::all(); @@ -114,6 +115,8 @@ // one individually. PA.preserveSet>(); + if (PI) + 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 @@ -27,7 +27,8 @@ bool shouldRun = true; for (auto &C : BeforePassCallbacks) - shouldRun &= C(PassID, llvm::Any(&IR), PC); + shouldRun &= + C(PassID, llvm::Any(&IR), PassExecutionLocation(PC)); return shouldRun; } @@ -35,21 +36,21 @@ void PassInstrumentation::runAfterPass(PassInstanceID PassID, const IRUnitT &IR) const { for (auto &C : AfterPassCallbacks) - C(PassID, llvm::Any(&IR), PC); + C(PassID, llvm::Any(&IR), PassExecutionLocation(PC)); } template void PassInstrumentation::runBeforeAnalysis(PassInstanceID PassID, - const IRUnitT &IR) const { + const IRUnitT &IR) const { for (auto &C : BeforeAnalysisCallbacks) - C(PassID, llvm::Any(&IR), PC); + C(PassID, llvm::Any(&IR), PassExecutionLocation(PC)); } template void PassInstrumentation::runAfterAnalysis(PassInstanceID PassID, - const IRUnitT &IR) const { + const IRUnitT &IR) const { for (auto &C : AfterAnalysisCallbacks) - C(PassID, llvm::Any(&IR), PC); + C(PassID, llvm::Any(&IR), PassExecutionLocation(PC)); } void PassInstrumentation::startPipeline() const { @@ -62,10 +63,31 @@ C(); } +template +void PassInstrumentation::startPassManager(PassInstanceID PM, + const IRUnitT &IR) const { + for (auto &C : StartPMCallbacks) + C(PM, llvm::Any(&IR), PassExecutionLocation(PC)); +} +template +void PassInstrumentation::finishPassManager(PassInstanceID PM, + const IRUnitT &IR) const { + for (auto &C : FinishPMCallbacks) + C(PM, llvm::Any(&IR), PassExecutionLocation(PC)); +} + +void PassInstrumentation::startIteration(PassInstanceID PM, + int Iteration) const { + for (auto &C : StartIterationCallbacks) + C(PM, Iteration, PassExecutionLocation(PC)); +} + bool PassInstrumentation::empty() const { return BeforePassCallbacks.empty() && AfterPassCallbacks.empty() && BeforeAnalysisCallbacks.empty() && AfterAnalysisCallbacks.empty() && - StartPipelineCallbacks.empty() && EndPipelineCallbacks.empty(); + StartPipelineCallbacks.empty() && EndPipelineCallbacks.empty() && + StartPMCallbacks.empty() && FinishPMCallbacks.empty() && + StartIterationCallbacks.empty(); } template bool PassInstrumentation::runBeforePass(PassInstanceID PassID, @@ -103,7 +125,28 @@ const Loop &IR) const; template void PassInstrumentation::runAfterAnalysis(PassInstanceID PassID, - const LazyCallGraph::SCC &IR) const; + const LazyCallGraph::SCC &IR) const; +template void PassInstrumentation::startPassManager(PassInstanceID PassID, + const Module &IR) const; +template void +PassInstrumentation::startPassManager(PassInstanceID PassID, + const Function &IR) const; +template void PassInstrumentation::startPassManager(PassInstanceID PassID, + const Loop &IR) const; +template void +PassInstrumentation::startPassManager(PassInstanceID PassID, + const LazyCallGraph::SCC &IR) const; +template void +PassInstrumentation::finishPassManager(PassInstanceID PassID, + const Module &IR) const; +template void +PassInstrumentation::finishPassManager(PassInstanceID PassID, + const Function &IR) const; +template void PassInstrumentation::finishPassManager(PassInstanceID PassID, + const Loop &IR) const; +template void +PassInstrumentation::finishPassManager(PassInstanceID PassID, + const LazyCallGraph::SCC &IR) const; AnalysisKey PassInstrumentationProxy::Key; Index: lib/Transforms/Scalar/LoopPassManager.cpp =================================================================== --- lib/Transforms/Scalar/LoopPassManager.cpp +++ lib/Transforms/Scalar/LoopPassManager.cpp @@ -33,6 +33,8 @@ // Request PassInstrumentation from analysis manager, will use it to run // instrumenting callbacks for the passes later. PassInstrumentation *PI = AM.getPassInstrumentation(L, AR); + if (PI) PI->startPassManager(this, L); + for (auto &Pass : Passes) { if (DebugLogging) dbgs() << "Running pass: " << Pass->name() << " on " << L; @@ -84,6 +86,8 @@ // be preserved, but unrolling should invalidate the parent loop's analyses. PA.preserveSet>(); + if (PI) PI->finishPassManager(this, L); + if (DebugLogging) dbgs() << "Finished Loop pass manager run.\n";