Index: include/llvm/IR/PassInstrumentation.h =================================================================== --- include/llvm/IR/PassInstrumentation.h +++ include/llvm/IR/PassInstrumentation.h @@ -149,7 +149,7 @@ /// point. class PassInstrumentation { public: - // Before/After Pass callbacks accept IRUnits, so they need to take them + // 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); @@ -174,6 +174,12 @@ template void runAfterPass(PassInstanceID PassID, const IRUnitT &) const; + template + void runBeforeAnalysis(PassInstanceID PassID, const IRUnitT &) const; + + template + void runAfterAnalysis(PassInstanceID PassID, const IRUnitT &) const; + void startPipeline() const; void endPipeline() const; @@ -185,6 +191,16 @@ AfterPassCallbacks.push_back(C); } + void + registerBeforeAnalysisCallback(const std::function &C) { + BeforeAnalysisCallbacks.push_back(C); + } + + void + registerAfterAnalysisCallback(const std::function &C) { + AfterAnalysisCallbacks.push_back(C); + } + void registerStartPipelineCallback(const std::function &C) { StartPipelineCallbacks.push_back(C); } @@ -201,6 +217,8 @@ SmallVector, 4> BeforePassCallbacks; SmallVector, 4> AfterPassCallbacks; + SmallVector, 4> BeforeAnalysisCallbacks; + SmallVector, 4> AfterAnalysisCallbacks; SmallVector, 2> StartPipelineCallbacks; SmallVector, 2> EndPipelineCallbacks; }; Index: include/llvm/IR/PassManager.h =================================================================== --- include/llvm/IR/PassManager.h +++ include/llvm/IR/PassManager.h @@ -951,9 +951,19 @@ if (DebugLogging) dbgs() << "Running analysis: " << P.name() << " on " << IR.getName() << "\n"; + + PassInstrumentation* PI = nullptr; + if (ID != PassInstrumentationProxy::ID()) { + PI = getPassInstrumentation(IR, std::tuple(ExtraArgs...)); + if (PI) PI->runBeforeAnalysis(&P, IR); + } + AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...)); + if (PI) + PI->runAfterAnalysis(&P, IR); + // P.run may have inserted elements into AnalysisResults and invalidated // RI. RI = AnalysisResults.find({ID, &IR}); Index: lib/IR/PassInstrumentation.cpp =================================================================== --- lib/IR/PassInstrumentation.cpp +++ lib/IR/PassInstrumentation.cpp @@ -38,6 +38,20 @@ C(PassID, llvm::Any(&IR), PC); } +template +void PassInstrumentation::runBeforeAnalysis(PassInstanceID PassID, + const IRUnitT &IR) const { + for (auto &C : BeforeAnalysisCallbacks) + C(PassID, llvm::Any(&IR), PC); +} + +template +void PassInstrumentation::runAfterAnalysis(PassInstanceID PassID, + const IRUnitT &IR) const { + for (auto &C : AfterAnalysisCallbacks) + C(PassID, llvm::Any(&IR), PC); +} + void PassInstrumentation::startPipeline() const { for (auto &C : StartPipelineCallbacks) C(); @@ -50,7 +64,8 @@ bool PassInstrumentation::empty() const { return BeforePassCallbacks.empty() && AfterPassCallbacks.empty() && - StartPipelineCallbacks.empty() && EndPipelineCallbacks.empty(); + BeforeAnalysisCallbacks.empty() && AfterAnalysisCallbacks.empty() && + StartPipelineCallbacks.empty() && EndPipelineCallbacks.empty(); } template bool PassInstrumentation::runBeforePass(PassInstanceID PassID, @@ -71,6 +86,24 @@ template void PassInstrumentation::runAfterPass(PassInstanceID PassID, const LazyCallGraph::SCC &IR) const; +template void PassInstrumentation::runBeforeAnalysis(PassInstanceID PassID, + const Module &IR) const; +template void PassInstrumentation::runBeforeAnalysis(PassInstanceID PassID, + const Function &IR) const; +template void PassInstrumentation::runBeforeAnalysis(PassInstanceID PassID, + const Loop &IR) const; +template void +PassInstrumentation::runBeforeAnalysis(PassInstanceID PassID, + const LazyCallGraph::SCC &IR) const; +template void PassInstrumentation::runAfterAnalysis(PassInstanceID PassID, + const Module &IR) const; +template void PassInstrumentation::runAfterAnalysis(PassInstanceID PassID, + const Function &IR) const; +template void PassInstrumentation::runAfterAnalysis(PassInstanceID PassID, + const Loop &IR) const; +template void +PassInstrumentation::runAfterAnalysis(PassInstanceID PassID, + const LazyCallGraph::SCC &IR) const; AnalysisKey PassInstrumentationProxy::Key; Index: test/Other/new-pm-lto-defaults.ll =================================================================== --- test/Other/new-pm-lto-defaults.ll +++ test/Other/new-pm-lto-defaults.ll @@ -51,8 +51,10 @@ ; CHECK-O1-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Function ; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy +; CHECK-O-NEXT: Running analysis: PassInstrumentationProxy ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph{{.*}}> ; CHECK-O-NEXT: Running analysis: AAManager +; CHECK-O1-NEXT: Running analysis: PassInstrumentationProxy ; CHECK-O1-NEXT: Running analysis: TargetLibraryAnalysis ; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: CallGraphAnalysis Index: test/Other/new-pm-thinlto-defaults.ll =================================================================== --- test/Other/new-pm-thinlto-defaults.ll +++ test/Other/new-pm-thinlto-defaults.ll @@ -59,13 +59,14 @@ ; CHECK-POSTLINK-O-NEXT: Running analysis: ProfileSummaryAnalysis ; CHECK-POSTLINK-O-NEXT: Running analysis: InnerAnalysisManagerProxy ; CHECK-POSTLINK-O-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis +; CHECK-POSTLINK-O-NEXT: Running analysis: PassInstrumentationProxy ; CHECK-O-NEXT: Running pass: PassManager<{{.*}}Module{{.*}}> ; CHECK-O-NEXT: Starting llvm::Module pass manager run. ; CHECK-O-NEXT: Running pass: InferFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis ; CHECK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}> ; CHECK-PRELINK-O-NODIS-NEXT: Running analysis: InnerAnalysisManagerProxy -; CHECK-O-NEXT: Running analysis: PassInstrumentationProxy +; CHECK-PRELINK-O-NEXT: Running analysis: PassInstrumentationProxy ; CHECK-O-NEXT: Starting llvm::Function pass manager run. ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running analysis: TargetIRAnalysis Index: unittests/IR/PassBuilderCallbacksTest.cpp =================================================================== --- unittests/IR/PassBuilderCallbacksTest.cpp +++ unittests/IR/PassBuilderCallbacksTest.cpp @@ -272,11 +272,19 @@ // by default by PassBuilder - Verifier pass etc). EXPECT_CALL(*this, runBeforePass(_, _, Ge(0))).Times(AnyNumber()); EXPECT_CALL(*this, runAfterPass(_, _, Ge(1))).Times(AnyNumber()); + EXPECT_CALL(*this, runBeforeAnalysis(_, _, _)).Times(AnyNumber()); + EXPECT_CALL(*this, runAfterAnalysis(_, _, _)).Times(AnyNumber()); } MOCK_METHOD3(runBeforePass, - bool(PassInstanceID PassID, llvm::Any, PassExecutionCounter)); + bool(PassInstanceID PassID, llvm::Any, PassExecutionLocation)); MOCK_METHOD3(runAfterPass, - void(PassInstanceID PassID, llvm::Any, PassExecutionCounter)); + void(PassInstanceID PassID, llvm::Any, PassExecutionLocation)); + MOCK_METHOD3(runBeforeAnalysis, + void(PassInstanceID PassID, llvm::Any, PassExecutionLocation)); + MOCK_METHOD3(runAfterAnalysis, + void(PassInstanceID PassID, llvm::Any, PassExecutionLocation)); + MOCK_METHOD0(startPipeline, void()); + MOCK_METHOD0(endPipeline, void()); }; static std::unique_ptr parseIR(LLVMContext &C, const char *IR) { @@ -427,6 +435,27 @@ _PI.registerAfterPassCallback( std::bind(&MockPassInstrumentationCallbacks::runAfterPass, &PassInstrumentationCallbacks, _1, _2, _3)); + _PI.registerBeforeAnalysisCallback( + std::bind(&MockPassInstrumentationCallbacks::runBeforeAnalysis, + &PassInstrumentationCallbacks, _1, _2, _3)); + _PI.registerAfterAnalysisCallback( + std::bind(&MockPassInstrumentationCallbacks::runAfterAnalysis, + &PassInstrumentationCallbacks, _1, _2, _3)); + _PI.registerStartPassManagerCallback( + std::bind(&MockPassInstrumentationCallbacks::startPassManager, + &PassInstrumentationCallbacks, _1, _2, _3)); + _PI.registerFinishPassManagerCallback( + std::bind(&MockPassInstrumentationCallbacks::finishPassManager, + &PassInstrumentationCallbacks, _1, _2, _3)); + _PI.registerStartPipelineCallback( + std::bind(&MockPassInstrumentationCallbacks::startPipeline, + &PassInstrumentationCallbacks)); + _PI.registerEndPipelineCallback( + std::bind(&MockPassInstrumentationCallbacks::endPipeline, + &PassInstrumentationCallbacks)); + _PI.registerStartIterationCallback( + std::bind(&MockPassInstrumentationCallbacks::startIteration, + &PassInstrumentationCallbacks, _1, _2, _3)); }); /// Register builtin analyses and cross-register the analysis proxies PB.registerModuleAnalyses(AM); @@ -466,6 +495,10 @@ testing::InSequence InstrumentationExpectationsSequenced; EXPECT_CALL(PassInstrumentationCallbacks, runBeforePass(_, HasName(""), Eq(1))); + EXPECT_CALL(PassInstrumentationCallbacks, + runBeforeAnalysis(_, HasName(""), Eq(1))); + EXPECT_CALL(PassInstrumentationCallbacks, + runAfterAnalysis(_, HasName(""), Eq(1))); EXPECT_CALL(PassInstrumentationCallbacks, runAfterPass(_, HasName(""), Eq(1))); } @@ -498,6 +531,12 @@ EXPECT_CALL( PassInstrumentationCallbacks, runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo"), Ge(3))); + EXPECT_CALL(PassInstrumentationCallbacks, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), + HasName("foo"), Ge(3))); + EXPECT_CALL(PassInstrumentationCallbacks, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), + HasName("foo"), Ge(3))); EXPECT_CALL( PassInstrumentationCallbacks, runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo"), Ge(3))); @@ -529,6 +568,12 @@ EXPECT_CALL(PassInstrumentationCallbacks, runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop"), Ge(5))); + EXPECT_CALL(PassInstrumentationCallbacks, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), + HasName("loop"), Ge(5))); + EXPECT_CALL(PassInstrumentationCallbacks, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), + HasName("loop"), Ge(5))); EXPECT_CALL(PassInstrumentationCallbacks, runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), Ge(5))); @@ -561,6 +606,12 @@ EXPECT_CALL( PassInstrumentationCallbacks, runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)"), Ge(3))); + EXPECT_CALL(PassInstrumentationCallbacks, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), + HasName("(foo)"), Ge(3))); + EXPECT_CALL(PassInstrumentationCallbacks, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), + HasName("(foo)"), Ge(3))); EXPECT_CALL( PassInstrumentationCallbacks, runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), Ge(3)));