Skip to content

Commit

Permalink
[New PM][PassInstrumentation] Adding PassInstrumentation to the Analy…
Browse files Browse the repository at this point in the history
…sisManager 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
  • Loading branch information
Fedor Sergeev committed Sep 21, 2018
1 parent 5f6d527 commit 10febb0
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 6 deletions.
34 changes: 33 additions & 1 deletion llvm/include/llvm/IR/PassInstrumentation.h
Expand Up @@ -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);
Expand All @@ -90,11 +90,25 @@ class PassInstrumentationCallbacks {
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,
Expand Down Expand Up @@ -133,6 +147,24 @@ class PassInstrumentation {
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.
///
Expand Down
9 changes: 9 additions & 0 deletions llvm/include/llvm/IR/PassManager.h
Expand Up @@ -943,9 +943,18 @@ template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager {
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});
Expand Down
2 changes: 2 additions & 0 deletions llvm/test/Other/new-pm-lto-defaults.ll
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion llvm/test/Other/new-pm-thinlto-defaults.ll
Expand Up @@ -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
Expand Down
83 changes: 79 additions & 4 deletions llvm/unittests/IR/PassBuilderCallbacksTest.cpp
Expand Up @@ -309,13 +309,20 @@ 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) {
return this->runBeforePass(P, IR);
});
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) {
Expand All @@ -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());
}
};

Expand Down Expand Up @@ -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);
Expand All @@ -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))
Expand Down Expand Up @@ -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);
Expand All @@ -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))
Expand Down Expand Up @@ -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);
Expand All @@ -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))
Expand Down Expand Up @@ -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);
Expand All @@ -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))
Expand Down

0 comments on commit 10febb0

Please sign in to comment.