[llvm] r348887 - [NewPM] fixing asserts on deleted loop in -print-after-all
Fedor Sergeev via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 11 11:05:35 PST 2018
Author: fedor.sergeev
Date: Tue Dec 11 11:05:35 2018
New Revision: 348887
URL: http://llvm.org/viewvc/llvm-project?rev=348887&view=rev
Log:
[NewPM] fixing asserts on deleted loop in -print-after-all
IR-printing AfterPass instrumentation might be called on a loop
that has just been invalidated. We should skip printing it to
avoid spurious asserts.
Reviewed By: chandlerc, philip.pfaffe
Differential Revision: https://reviews.llvm.org/D54740
Added:
llvm/trunk/test/Other/loop-deletion-printer.ll
llvm/trunk/test/Other/scc-deleted-printer.ll
Modified:
llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h
llvm/trunk/include/llvm/IR/PassInstrumentation.h
llvm/trunk/include/llvm/IR/PassTimingInfo.h
llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h
llvm/trunk/lib/Analysis/CGSCCPassManager.cpp
llvm/trunk/lib/IR/PassTimingInfo.cpp
llvm/trunk/lib/Passes/StandardInstrumentations.cpp
llvm/trunk/lib/Transforms/Scalar/LoopPassManager.cpp
llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp
Modified: llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h?rev=348887&r1=348886&r2=348887&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h (original)
+++ llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h Tue Dec 11 11:05:35 2018
@@ -441,7 +441,10 @@ public:
PreservedAnalyses PassPA = Pass.run(*C, CGAM, CG, UR);
- PI.runAfterPass<LazyCallGraph::SCC>(Pass, *C);
+ if (UR.InvalidatedSCCs.count(C))
+ PI.runAfterPassInvalidated<LazyCallGraph::SCC>(Pass);
+ else
+ PI.runAfterPass<LazyCallGraph::SCC>(Pass, *C);
// Update the SCC and RefSCC if necessary.
C = UR.UpdatedC ? UR.UpdatedC : C;
@@ -762,7 +765,10 @@ public:
PreservedAnalyses PassPA = Pass.run(*C, AM, CG, UR);
- PI.runAfterPass<LazyCallGraph::SCC>(Pass, *C);
+ if (UR.InvalidatedSCCs.count(C))
+ PI.runAfterPassInvalidated<LazyCallGraph::SCC>(Pass);
+ else
+ PI.runAfterPass<LazyCallGraph::SCC>(Pass, *C);
// If the SCC structure has changed, bail immediately and let the outer
// CGSCC layer handle any iteration to reflect the refined structure.
Modified: llvm/trunk/include/llvm/IR/PassInstrumentation.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassInstrumentation.h?rev=348887&r1=348886&r2=348887&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PassInstrumentation.h (original)
+++ llvm/trunk/include/llvm/IR/PassInstrumentation.h Tue Dec 11 11:05:35 2018
@@ -68,10 +68,17 @@ class PreservedAnalyses;
/// PassInstrumentation to pass control to the registered callbacks.
class PassInstrumentationCallbacks {
public:
- // Before/After callbacks accept IRUnits, so they need to take them
- // as pointers, wrapped with llvm::Any
+ // Before/After callbacks accept IRUnits whenever appropriate, so they need
+ // to take them as constant pointers, wrapped with llvm::Any.
+ // For the case when IRUnit has been invalidated there is a different
+ // callback to use - AfterPassInvalidated.
+ // TODO: currently AfterPassInvalidated does not accept IRUnit, since passing
+ // already invalidated IRUnit is unsafe. There are ways to handle invalidated IRUnits
+ // in a safe way, and we might pursue that as soon as there is a useful instrumentation
+ // that needs it.
using BeforePassFunc = bool(StringRef, Any);
using AfterPassFunc = void(StringRef, Any);
+ using AfterPassInvalidatedFunc = void(StringRef);
using BeforeAnalysisFunc = void(StringRef, Any);
using AfterAnalysisFunc = void(StringRef, Any);
@@ -91,6 +98,11 @@ public:
}
template <typename CallableT>
+ void registerAfterPassInvalidatedCallback(CallableT C) {
+ AfterPassInvalidatedCallbacks.emplace_back(std::move(C));
+ }
+
+ template <typename CallableT>
void registerBeforeAnalysisCallback(CallableT C) {
BeforeAnalysisCallbacks.emplace_back(std::move(C));
}
@@ -105,6 +117,8 @@ private:
SmallVector<llvm::unique_function<BeforePassFunc>, 4> BeforePassCallbacks;
SmallVector<llvm::unique_function<AfterPassFunc>, 4> AfterPassCallbacks;
+ SmallVector<llvm::unique_function<AfterPassInvalidatedFunc>, 4>
+ AfterPassInvalidatedCallbacks;
SmallVector<llvm::unique_function<BeforeAnalysisFunc>, 4>
BeforeAnalysisCallbacks;
SmallVector<llvm::unique_function<AfterAnalysisFunc>, 4>
@@ -139,7 +153,8 @@ public:
}
/// AfterPass instrumentation point - takes \p Pass instance that has
- /// just been executed and constant reference to IR it operates on.
+ /// just been executed and constant reference to \p IR it operates on.
+ /// \p IR is guaranteed to be valid at this point.
template <typename IRUnitT, typename PassT>
void runAfterPass(const PassT &Pass, const IRUnitT &IR) const {
if (Callbacks)
@@ -147,6 +162,16 @@ public:
C(Pass.name(), llvm::Any(&IR));
}
+ /// AfterPassInvalidated instrumentation point - takes \p Pass instance
+ /// that has just been executed. For use when IR has been invalidated
+ /// by \p Pass execution.
+ template <typename IRUnitT, typename PassT>
+ void runAfterPassInvalidated(const PassT &Pass) const {
+ if (Callbacks)
+ for (auto &C : Callbacks->AfterPassInvalidatedCallbacks)
+ C(Pass.name());
+ }
+
/// BeforeAnalysis instrumentation point - takes \p Analysis instance
/// to be executed and constant reference to IR it operates on.
template <typename IRUnitT, typename PassT>
Modified: llvm/trunk/include/llvm/IR/PassTimingInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassTimingInfo.h?rev=348887&r1=348886&r2=348887&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PassTimingInfo.h (original)
+++ llvm/trunk/include/llvm/IR/PassTimingInfo.h Tue Dec 11 11:05:35 2018
@@ -99,8 +99,8 @@ private:
void stopTimer(StringRef PassID);
// Implementation of pass instrumentation callbacks.
- bool runBeforePass(StringRef PassID, Any IR);
- void runAfterPass(StringRef PassID, Any IR);
+ bool runBeforePass(StringRef PassID);
+ void runAfterPass(StringRef PassID);
};
} // namespace llvm
Modified: llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h?rev=348887&r1=348886&r2=348887&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h (original)
+++ llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h Tue Dec 11 11:05:35 2018
@@ -352,7 +352,11 @@ public:
continue;
PreservedAnalyses PassPA = Pass.run(*L, LAM, LAR, Updater);
- PI.runAfterPass<Loop>(Pass, *L);
+ // Do not pass deleted Loop into the instrumentation.
+ if (Updater.skipCurrentLoop())
+ PI.runAfterPassInvalidated<Loop>(Pass);
+ else
+ PI.runAfterPass<Loop>(Pass, *L);
// FIXME: We should verify the set of analyses relevant to Loop passes
// are preserved.
Modified: llvm/trunk/lib/Analysis/CGSCCPassManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CGSCCPassManager.cpp?rev=348887&r1=348886&r2=348887&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CGSCCPassManager.cpp (original)
+++ llvm/trunk/lib/Analysis/CGSCCPassManager.cpp Tue Dec 11 11:05:35 2018
@@ -79,7 +79,10 @@ PassManager<LazyCallGraph::SCC, CGSCCAna
PreservedAnalyses PassPA = Pass->run(*C, AM, G, UR);
- PI.runAfterPass(*Pass, *C);
+ if (UR.InvalidatedSCCs.count(C))
+ PI.runAfterPassInvalidated<LazyCallGraph::SCC>(*Pass);
+ else
+ PI.runAfterPass<LazyCallGraph::SCC>(*Pass, *C);
// Update the SCC if necessary.
C = UR.UpdatedC ? UR.UpdatedC : C;
Modified: llvm/trunk/lib/IR/PassTimingInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/PassTimingInfo.cpp?rev=348887&r1=348886&r2=348887&view=diff
==============================================================================
--- llvm/trunk/lib/IR/PassTimingInfo.cpp (original)
+++ llvm/trunk/lib/IR/PassTimingInfo.cpp Tue Dec 11 11:05:35 2018
@@ -226,7 +226,7 @@ static bool matchPassManager(StringRef P
Prefix.endswith("AnalysisManagerProxy");
}
-bool TimePassesHandler::runBeforePass(StringRef PassID, Any IR) {
+bool TimePassesHandler::runBeforePass(StringRef PassID) {
if (matchPassManager(PassID))
return true;
@@ -239,7 +239,7 @@ bool TimePassesHandler::runBeforePass(St
return true;
}
-void TimePassesHandler::runAfterPass(StringRef PassID, Any IR) {
+void TimePassesHandler::runAfterPass(StringRef PassID) {
if (matchPassManager(PassID))
return;
@@ -254,13 +254,15 @@ void TimePassesHandler::registerCallback
return;
PIC.registerBeforePassCallback(
- [this](StringRef P, Any IR) { return this->runBeforePass(P, IR); });
+ [this](StringRef P, Any) { return this->runBeforePass(P); });
PIC.registerAfterPassCallback(
- [this](StringRef P, Any IR) { this->runAfterPass(P, IR); });
+ [this](StringRef P, Any) { this->runAfterPass(P); });
+ PIC.registerAfterPassInvalidatedCallback(
+ [this](StringRef P) { this->runAfterPass(P); });
PIC.registerBeforeAnalysisCallback(
- [this](StringRef P, Any IR) { this->runBeforePass(P, IR); });
+ [this](StringRef P, Any) { this->runBeforePass(P); });
PIC.registerAfterAnalysisCallback(
- [this](StringRef P, Any IR) { this->runAfterPass(P, IR); });
+ [this](StringRef P, Any) { this->runAfterPass(P); });
}
} // namespace llvm
Modified: llvm/trunk/lib/Passes/StandardInstrumentations.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/StandardInstrumentations.cpp?rev=348887&r1=348886&r2=348887&view=diff
==============================================================================
--- llvm/trunk/lib/Passes/StandardInstrumentations.cpp (original)
+++ llvm/trunk/lib/Passes/StandardInstrumentations.cpp Tue Dec 11 11:05:35 2018
@@ -53,7 +53,6 @@ void unwrapAndPrint(StringRef Banner, An
Extra = formatv(" (function: {0})\n", F->getName());
} else if (any_isa<const LazyCallGraph::SCC *>(IR)) {
const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
- assert(C);
if (!llvm::forcePrintModuleIR()) {
Extra = formatv(" (scc: {0})\n", C->getName());
bool BannerPrinted = false;
Modified: llvm/trunk/lib/Transforms/Scalar/LoopPassManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopPassManager.cpp?rev=348887&r1=348886&r2=348887&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopPassManager.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopPassManager.cpp Tue Dec 11 11:05:35 2018
@@ -44,7 +44,11 @@ PassManager<Loop, LoopAnalysisManager, L
PreservedAnalyses PassPA = Pass->run(L, AM, AR, U);
- PI.runAfterPass<Loop>(*Pass, L);
+ // do not pass deleted Loop into the instrumentation
+ if (U.skipCurrentLoop())
+ PI.runAfterPassInvalidated<Loop>(*Pass);
+ else
+ PI.runAfterPass<Loop>(*Pass, L);
// If the loop was deleted, abort the run and return to the outer walk.
if (U.skipCurrentLoop()) {
Added: llvm/trunk/test/Other/loop-deletion-printer.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/loop-deletion-printer.ll?rev=348887&view=auto
==============================================================================
--- llvm/trunk/test/Other/loop-deletion-printer.ll (added)
+++ llvm/trunk/test/Other/loop-deletion-printer.ll Tue Dec 11 11:05:35 2018
@@ -0,0 +1,24 @@
+; Make sure that Loop which was invalidated by loop-deletion
+; does not lead to problems for -print-after-all and is just skipped.
+;
+; RUN: opt < %s -disable-output \
+; RUN: -passes=loop-instsimplify -print-after-all 2>&1 | FileCheck %s -check-prefix=SIMPLIFY
+; RUN: opt < %s -disable-output \
+; RUN: -passes=loop-deletion,loop-instsimplify -print-after-all 2>&1 | FileCheck %s -check-prefix=DELETED
+;
+; SIMPLIFY: IR Dump {{.*}} LoopInstSimplifyPass
+; DELETED-NOT: IR Dump {{.*}}LoopInstSimplifyPass
+; DELETED-NOT: IR Dump {{.*}}LoopDeletionPass
+
+define void @deleteme() {
+entry:
+ br label %loop
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
+ %iv.next = add i32 %iv, 1
+ %check = icmp ult i32 %iv.next, 3
+ br i1 %check, label %loop, label %exit
+exit:
+ ret void
+}
+
Added: llvm/trunk/test/Other/scc-deleted-printer.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/scc-deleted-printer.ll?rev=348887&view=auto
==============================================================================
--- llvm/trunk/test/Other/scc-deleted-printer.ll (added)
+++ llvm/trunk/test/Other/scc-deleted-printer.ll Tue Dec 11 11:05:35 2018
@@ -0,0 +1,25 @@
+; RUN: opt < %s 2>&1 -disable-output \
+; RUN: -passes=inline -print-before-all -print-after-all | FileCheck %s -check-prefix=INL
+; RUN: opt < %s 2>&1 -disable-output \
+; RUN: -passes=inline -print-before-all -print-after-all -print-module-scope | FileCheck %s -check-prefix=INL-MOD
+
+; INL: IR Dump Before {{InlinerPass .*scc: .tester, foo}}
+; INL-NOT: IR Dump After {{InlinerPass}}
+; INL: IR Dump Before {{InlinerPass .*scc: .tester}}
+; INL: IR Dump After {{InlinerPass .*scc: .tester}}
+
+; INL-MOD: IR Dump Before {{InlinerPass .*scc: .tester, foo}}
+; INL-MOD-NOT: IR Dump After {{InlinerPass}}
+; INL-MOD: IR Dump Before {{InlinerPass .*scc: .tester}}
+; INL-MOD: IR Dump After {{InlinerPass .*scc: .tester}}
+
+
+define void @tester() noinline {
+ call void @foo()
+ ret void
+}
+
+define internal void @foo() alwaysinline {
+ call void @tester()
+ ret void
+}
Modified: llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp?rev=348887&r1=348886&r2=348887&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp (original)
+++ llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp Tue Dec 11 11:05:35 2018
@@ -167,6 +167,11 @@ struct MockPassHandle<Loop>
MOCK_METHOD4(run,
PreservedAnalyses(Loop &, LoopAnalysisManager &,
LoopStandardAnalysisResults &, LPMUpdater &));
+ static void invalidateLoop(Loop &L, LoopAnalysisManager &,
+ LoopStandardAnalysisResults &,
+ LPMUpdater &Updater) {
+ Updater.markLoopAsDeleted(L, L.getName());
+ }
MockPassHandle() { setDefaults(); }
};
@@ -187,6 +192,11 @@ struct MockPassHandle<LazyCallGraph::SCC
PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
LazyCallGraph &G, CGSCCUpdateResult &UR));
+ static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
+ LazyCallGraph &, CGSCCUpdateResult &UR) {
+ UR.InvalidatedSCCs.insert(&C);
+ }
+
MockPassHandle() { setDefaults(); }
};
@@ -310,6 +320,7 @@ struct MockPassInstrumentationCallbacks
}
MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any));
+ MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID));
MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
@@ -319,6 +330,8 @@ struct MockPassInstrumentationCallbacks
});
Callbacks.registerAfterPassCallback(
[this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); });
+ Callbacks.registerAfterPassInvalidatedCallback(
+ [this](StringRef P) { this->runAfterPassInvalidated(P); });
Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
return this->runBeforeAnalysis(P, IR);
});
@@ -571,6 +584,11 @@ TEST_F(FunctionCallbacksTest, Instrument
runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo")))
.InSequence(PISequence);
+ // Our mock pass does not invalidate IR.
+ EXPECT_CALL(CallbacksHandle,
+ runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
+ .Times(0);
+
StringRef PipelineText = "test-transform";
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
@@ -595,6 +613,9 @@ TEST_F(FunctionCallbacksTest, Instrument
// as well.
EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
.Times(0);
+ EXPECT_CALL(CallbacksHandle,
+ runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
+ .Times(0);
EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
.Times(0);
EXPECT_CALL(CallbacksHandle,
@@ -650,6 +671,55 @@ TEST_F(LoopCallbacksTest, InstrumentedPa
runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
.InSequence(PISequence);
+ // Our mock pass does not invalidate IR.
+ EXPECT_CALL(CallbacksHandle,
+ runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
+ .Times(0);
+
+ StringRef PipelineText = "test-transform";
+ ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
+ << "Pipeline was: " << PipelineText;
+ PM.run(*M, AM);
+}
+
+TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
+ CallbacksHandle.registerPassInstrumentation();
+ // Non-mock instrumentation not specifically mentioned below can be ignored.
+ CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
+ CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
+ CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
+
+ EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
+ EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
+ .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateLoop)),
+ WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
+
+ // PassInstrumentation calls should happen in-sequence, in the same order
+ // as passes/analyses are scheduled.
+ ::testing::Sequence PISequence;
+ 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,
+ runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
+ .InSequence(PISequence);
+ EXPECT_CALL(CallbacksHandle,
+ runAfterPassInvalidated(HasNameRegex("^PassManager")))
+ .InSequence(PISequence);
+
+ // Our mock pass invalidates IR, thus normal runAfterPass is never called.
+ EXPECT_CALL(CallbacksHandle,
+ runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
+ .Times(0);
+
StringRef PipelineText = "test-transform";
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
@@ -676,6 +746,9 @@ TEST_F(LoopCallbacksTest, InstrumentedSk
EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
.Times(0);
EXPECT_CALL(CallbacksHandle,
+ runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
+ .Times(0);
+ EXPECT_CALL(CallbacksHandle,
runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
.Times(0);
EXPECT_CALL(CallbacksHandle,
@@ -727,6 +800,54 @@ TEST_F(CGSCCCallbacksTest, InstrumentedP
runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
.InSequence(PISequence);
+ // Our mock pass does not invalidate IR.
+ EXPECT_CALL(CallbacksHandle,
+ runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
+ .Times(0);
+
+ StringRef PipelineText = "test-transform";
+ ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
+ << "Pipeline was: " << PipelineText;
+ PM.run(*M, AM);
+}
+
+TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
+ CallbacksHandle.registerPassInstrumentation();
+ // Non-mock instrumentation not specifically mentioned below can be ignored.
+ CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
+ CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
+
+ EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
+ EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
+ .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateSCC)),
+ WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
+
+ // PassInstrumentation calls should happen in-sequence, in the same order
+ // as passes/analyses are scheduled.
+ ::testing::Sequence PISequence;
+ 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,
+ runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
+ .InSequence(PISequence);
+ EXPECT_CALL(CallbacksHandle,
+ runAfterPassInvalidated(HasNameRegex("^PassManager")))
+ .InSequence(PISequence);
+
+ // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
+ EXPECT_CALL(CallbacksHandle,
+ runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
+ .Times(0);
+
StringRef PipelineText = "test-transform";
ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
<< "Pipeline was: " << PipelineText;
@@ -753,6 +874,9 @@ TEST_F(CGSCCCallbacksTest, InstrumentedS
EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
.Times(0);
EXPECT_CALL(CallbacksHandle,
+ runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
+ .Times(0);
+ EXPECT_CALL(CallbacksHandle,
runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
.Times(0);
EXPECT_CALL(CallbacksHandle,
More information about the llvm-commits
mailing list