[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
This commit is contained in:
Fedor Sergeev 2018-09-21 22:10:17 +00:00
parent 5f6d527f09
commit 10febb0779
5 changed files with 125 additions and 6 deletions

View File

@ -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 <typename CallableT>
void registerBeforeAnalysisCallback(CallableT C) {
BeforeAnalysisCallbacks.emplace_back(std::move(C));
}
template <typename CallableT>
void registerAfterAnalysisCallback(CallableT C) {
AfterAnalysisCallbacks.emplace_back(std::move(C));
}
private:
friend class PassInstrumentation;
SmallVector<llvm::unique_function<BeforePassFunc>, 4> BeforePassCallbacks;
SmallVector<llvm::unique_function<AfterPassFunc>, 4> AfterPassCallbacks;
SmallVector<llvm::unique_function<BeforeAnalysisFunc>, 4>
BeforeAnalysisCallbacks;
SmallVector<llvm::unique_function<AfterAnalysisFunc>, 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 <typename IRUnitT, typename PassT>
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 <typename IRUnitT, typename PassT>
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.
///

View File

@ -943,9 +943,18 @@ private:
if (DebugLogging)
dbgs() << "Running analysis: " << P.name() << " on " << IR.getName()
<< "\n";
PassInstrumentation PI;
if (ID != PassInstrumentationAnalysis::ID()) {
PI = getResult<PassInstrumentationAnalysis>(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});

View File

@ -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

View File

@ -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

View File

@ -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("<string>")))
.InSequence(PISequence);
EXPECT_CALL(CallbacksHandle,
runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
HasName("<string>")))
.InSequence(PISequence);
EXPECT_CALL(
CallbacksHandle,
runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
.InSequence(PISequence);
EXPECT_CALL(CallbacksHandle,
runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
.InSequence(PISequence);
@ -492,9 +513,16 @@ TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).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))