From d3259add2480bb9fe789813982ad3405c7dc59c2 Mon Sep 17 00:00:00 2001 From: Fedor Sergeev Date: Fri, 21 Sep 2018 22:10:17 +0000 Subject: [PATCH] [New PM][PassInstrumentation] Adding PassInstrumentation to the AnalysisManager runs As a prerequisite to time-passes implementation which needs to time both passes and analyses, adding instrumentation points to the Analysis Manager. The are two functional differences between Pass and Analysis instrumentation: - the latter does not increment pass execution counter - it does not provide ability to skip execution of the corresponding analysis Reviewers: chandlerc, philip.pfaffe Differential Revision: https://reviews.llvm.org/D51275 llvm-svn: 342778 --- include/llvm/IR/PassInstrumentation.h | 34 +++++++++- include/llvm/IR/PassManager.h | 9 +++ test/Other/new-pm-lto-defaults.ll | 2 + test/Other/new-pm-thinlto-defaults.ll | 3 +- unittests/IR/PassBuilderCallbacksTest.cpp | 83 +++++++++++++++++++++-- 5 files changed, 125 insertions(+), 6 deletions(-) diff --git a/include/llvm/IR/PassInstrumentation.h b/include/llvm/IR/PassInstrumentation.h index 3fdda6cb53e..3718b53c453 100644 --- a/include/llvm/IR/PassInstrumentation.h +++ b/include/llvm/IR/PassInstrumentation.h @@ -68,7 +68,7 @@ class PreservedAnalyses; /// PassInstrumentation to pass control to the registered callbacks. class PassInstrumentationCallbacks { 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(StringRef, Any); using AfterPassFunc = void(StringRef, Any); @@ -90,11 +90,25 @@ public: AfterPassCallbacks.emplace_back(std::move(C)); } + template + void registerBeforeAnalysisCallback(CallableT C) { + BeforeAnalysisCallbacks.emplace_back(std::move(C)); + } + + template + void registerAfterAnalysisCallback(CallableT C) { + AfterAnalysisCallbacks.emplace_back(std::move(C)); + } + private: friend class PassInstrumentation; SmallVector, 4> BeforePassCallbacks; SmallVector, 4> AfterPassCallbacks; + SmallVector, 4> + BeforeAnalysisCallbacks; + SmallVector, 4> + AfterAnalysisCallbacks; }; /// This class provides instrumentation entry points for the Pass Manager, @@ -133,6 +147,24 @@ public: C(Pass.name(), llvm::Any(&IR)); } + /// BeforeAnalysis instrumentation point - takes \p Analysis instance + /// to be executed and constant reference to IR it operates on. + template + void runBeforeAnalysis(const PassT &Analysis, const IRUnitT &IR) const { + if (Callbacks) + for (auto &C : Callbacks->BeforeAnalysisCallbacks) + C(Analysis.name(), llvm::Any(&IR)); + } + + /// AfterAnalysis instrumentation point - takes \p Analysis instance + /// that has just been executed and constant reference to IR it operated on. + template + void runAfterAnalysis(const PassT &Analysis, const IRUnitT &IR) const { + if (Callbacks) + for (auto &C : Callbacks->AfterAnalysisCallbacks) + C(Analysis.name(), llvm::Any(&IR)); + } + /// Handle invalidation from the pass manager when PassInstrumentation /// is used as the result of PassInstrumentationAnalysis. /// diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index f3182376c10..738a2242eea 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -943,9 +943,18 @@ private: if (DebugLogging) dbgs() << "Running analysis: " << P.name() << " on " << IR.getName() << "\n"; + + PassInstrumentation PI; + if (ID != PassInstrumentationAnalysis::ID()) { + PI = getResult(IR, ExtraArgs...); + PI.runBeforeAnalysis(P, IR); + } + AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...)); + PI.runAfterAnalysis(P, IR); + // P.run may have inserted elements into AnalysisResults and invalidated // RI. RI = AnalysisResults.find({ID, &IR}); diff --git a/test/Other/new-pm-lto-defaults.ll b/test/Other/new-pm-lto-defaults.ll index 92b41536612..03f4804a2ba 100644 --- a/test/Other/new-pm-lto-defaults.ll +++ b/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: PassInstrumentationAnalysis ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph{{.*}}> ; CHECK-O-NEXT: Running analysis: AAManager +; CHECK-O1-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-O1-NEXT: Running analysis: TargetLibraryAnalysis ; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: CallGraphAnalysis diff --git a/test/Other/new-pm-thinlto-defaults.ll b/test/Other/new-pm-thinlto-defaults.ll index ece33c81863..38c9fad3594 100644 --- a/test/Other/new-pm-thinlto-defaults.ll +++ b/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: PassInstrumentationAnalysis ; 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: PassInstrumentationAnalysis +; CHECK-PRELINK-O-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-O-NEXT: Starting llvm::Function pass manager run. ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running analysis: TargetIRAnalysis diff --git a/unittests/IR/PassBuilderCallbacksTest.cpp b/unittests/IR/PassBuilderCallbacksTest.cpp index f9a6721bb97..97bbb81a6b0 100644 --- a/unittests/IR/PassBuilderCallbacksTest.cpp +++ b/unittests/IR/PassBuilderCallbacksTest.cpp @@ -309,6 +309,8 @@ struct MockPassInstrumentationCallbacks { } MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any)); MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any)); + MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any)); + MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any)); void registerPassInstrumentation() { Callbacks.registerBeforePassCallback([this](StringRef P, llvm::Any IR) { @@ -316,6 +318,11 @@ struct MockPassInstrumentationCallbacks { }); Callbacks.registerAfterPassCallback( [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); }); + Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) { + return this->runBeforeAnalysis(P, IR); + }); + Callbacks.registerAfterAnalysisCallback( + [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); }); } void ignoreNonMockPassInstrumentation(StringRef IRName) { @@ -329,6 +336,12 @@ struct MockPassInstrumentationCallbacks { .Times(AnyNumber()); EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName))) .Times(AnyNumber()); + EXPECT_CALL(*this, + runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName))) + .Times(AnyNumber()); + EXPECT_CALL(*this, + runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName))) + .Times(AnyNumber()); } }; @@ -468,6 +481,14 @@ TEST_F(ModuleCallbacksTest, InstrumentedPasses) { EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), HasName(""))) .InSequence(PISequence); + EXPECT_CALL(CallbacksHandle, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), + HasName(""))) + .InSequence(PISequence); + EXPECT_CALL( + CallbacksHandle, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName(""))) + .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), HasName(""))) .InSequence(PISequence); @@ -492,9 +513,16 @@ TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) { EXPECT_CALL(AnalysisHandle, run(HasName(""), _)).Times(0); EXPECT_CALL(PassHandle, run(HasName(""), _)).Times(0); - // As the pass is skipped there is no afterPass as well. + // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis + // as well. EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) .Times(0); + EXPECT_CALL(CallbacksHandle, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) + .Times(0); + EXPECT_CALL(CallbacksHandle, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _)) + .Times(0); StringRef PipelineText = "test-transform"; ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) @@ -530,6 +558,14 @@ TEST_F(FunctionCallbacksTest, InstrumentedPasses) { EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo"))) .InSequence(PISequence); + EXPECT_CALL( + CallbacksHandle, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo"))) + .InSequence(PISequence); + EXPECT_CALL( + CallbacksHandle, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo"))) + .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo"))) .InSequence(PISequence); @@ -554,9 +590,18 @@ TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) { EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0); EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0); - // As the pass is skipped there is no afterPass as well. + // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis + // as well. EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) .Times(0); + EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + .Times(0); + EXPECT_CALL(CallbacksHandle, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) + .Times(0); + EXPECT_CALL(CallbacksHandle, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _)) + .Times(0); StringRef PipelineText = "test-transform"; ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) @@ -592,6 +637,14 @@ TEST_F(LoopCallbacksTest, InstrumentedPasses) { EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop"))) .InSequence(PISequence); + EXPECT_CALL( + CallbacksHandle, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop"))) + .InSequence(PISequence); + EXPECT_CALL( + CallbacksHandle, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop"))) + .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"))) .InSequence(PISequence); @@ -617,9 +670,16 @@ TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) { EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0); EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0); - // As the pass is skipped there is no afterPass as well. + // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis + // as well. EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) .Times(0); + EXPECT_CALL(CallbacksHandle, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) + .Times(0); + EXPECT_CALL(CallbacksHandle, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _)) + .Times(0); StringRef PipelineText = "test-transform"; ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) @@ -654,6 +714,14 @@ TEST_F(CGSCCCallbacksTest, InstrumentedPasses) { EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) .InSequence(PISequence); + EXPECT_CALL( + CallbacksHandle, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)"))) + .InSequence(PISequence); + EXPECT_CALL( + CallbacksHandle, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)"))) + .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) .InSequence(PISequence); @@ -679,9 +747,16 @@ TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) { EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0); EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0); - // As the pass is skipped there is no afterPass as well. + // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis + // as well. EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) .Times(0); + EXPECT_CALL(CallbacksHandle, + runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) + .Times(0); + EXPECT_CALL(CallbacksHandle, + runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _)) + .Times(0); StringRef PipelineText = "test-transform"; ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))