1 //===- unittests/IR/PassBuilderCallbacksTest.cpp - PB Callback Tests --===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/Testing/Support/Error.h"
12 #include <gmock/gmock.h>
13 #include <gtest/gtest.h>
14 #include <llvm/ADT/Any.h>
15 #include <llvm/Analysis/CGSCCPassManager.h>
16 #include <llvm/Analysis/LoopAnalysisManager.h>
17 #include <llvm/AsmParser/Parser.h>
18 #include <llvm/IR/LLVMContext.h>
19 #include <llvm/IR/PassInstrumentation.h>
20 #include <llvm/IR/PassManager.h>
21 #include <llvm/Passes/PassBuilder.h>
22 #include <llvm/Support/Regex.h>
23 #include <llvm/Support/SourceMgr.h>
24 #include <llvm/Transforms/Scalar/LoopPassManager.h>
29 using testing::AnyNumber;
30 using testing::AtLeast;
31 using testing::DoDefault;
33 using testing::Return;
34 using testing::Expectation;
35 using testing::Invoke;
36 using testing::WithArgs;
39 /// A CRTP base for analysis mock handles
41 /// This class reconciles mocking with the value semantics implementation of the
42 /// AnalysisManager. Analysis mock handles should derive from this class and
43 /// call \c setDefault() in their constroctur for wiring up the defaults defined
44 /// by this base with their mock run() and invalidate() implementations.
45 template <typename DerivedT, typename IRUnitT,
46 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
47 typename... ExtraArgTs>
48 class MockAnalysisHandleBase {
50 class Analysis : public AnalysisInfoMixin<Analysis> {
51 friend AnalysisInfoMixin<Analysis>;
52 friend MockAnalysisHandleBase;
53 static AnalysisKey Key;
57 Analysis(DerivedT &Handle) : Handle(&Handle) {
58 static_assert(std::is_base_of<MockAnalysisHandleBase, DerivedT>::value,
59 "Must pass the derived type to this template!");
64 friend MockAnalysisHandleBase;
68 Result(DerivedT &Handle) : Handle(&Handle) {}
71 // Forward invalidation events to the mock handle.
72 bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
73 typename AnalysisManagerT::Invalidator &Inv) {
74 return Handle->invalidate(IR, PA, Inv);
78 Result run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) {
79 return Handle->run(IR, AM, ExtraArgs...);
83 Analysis getAnalysis() { return Analysis(static_cast<DerivedT &>(*this)); }
84 typename Analysis::Result getResult() {
85 return typename Analysis::Result(static_cast<DerivedT &>(*this));
87 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
90 // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within
91 // the template, so we use a boring static function.
92 static bool invalidateCallback(IRUnitT &IR, const PreservedAnalyses &PA,
93 typename AnalysisManagerT::Invalidator &Inv) {
94 auto PAC = PA.template getChecker<Analysis>();
95 return !PAC.preserved() &&
96 !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
99 /// Derived classes should call this in their constructor to set up default
100 /// mock actions. (We can't do this in our constructor because this has to
101 /// run after the DerivedT is constructed.)
103 ON_CALL(static_cast<DerivedT &>(*this),
104 run(_, _, testing::Matcher<ExtraArgTs>(_)...))
105 .WillByDefault(Return(this->getResult()));
106 ON_CALL(static_cast<DerivedT &>(*this), invalidate(_, _, _))
107 .WillByDefault(Invoke(&invalidateCallback));
111 /// A CRTP base for pass mock handles
113 /// This class reconciles mocking with the value semantics implementation of the
114 /// PassManager. Pass mock handles should derive from this class and
115 /// call \c setDefault() in their constroctur for wiring up the defaults defined
116 /// by this base with their mock run() and invalidate() implementations.
117 template <typename DerivedT, typename IRUnitT, typename AnalysisManagerT,
118 typename... ExtraArgTs>
119 AnalysisKey MockAnalysisHandleBase<DerivedT, IRUnitT, AnalysisManagerT,
120 ExtraArgTs...>::Analysis::Key;
122 template <typename DerivedT, typename IRUnitT,
123 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
124 typename... ExtraArgTs>
125 class MockPassHandleBase {
127 class Pass : public PassInfoMixin<Pass> {
128 friend MockPassHandleBase;
132 Pass(DerivedT &Handle) : Handle(&Handle) {
133 static_assert(std::is_base_of<MockPassHandleBase, DerivedT>::value,
134 "Must pass the derived type to this template!");
138 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
139 ExtraArgTs... ExtraArgs) {
140 return Handle->run(IR, AM, ExtraArgs...);
144 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
146 Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); }
149 /// Derived classes should call this in their constructor to set up default
150 /// mock actions. (We can't do this in our constructor because this has to
151 /// run after the DerivedT is constructed.)
153 ON_CALL(static_cast<DerivedT &>(*this),
154 run(_, _, testing::Matcher<ExtraArgTs>(_)...))
155 .WillByDefault(Return(PreservedAnalyses::all()));
159 /// Mock handles for passes for the IRUnits Module, CGSCC, Function, Loop.
160 /// These handles define the appropriate run() mock interface for the respective
162 template <typename IRUnitT> struct MockPassHandle;
164 struct MockPassHandle<Loop>
165 : MockPassHandleBase<MockPassHandle<Loop>, Loop, LoopAnalysisManager,
166 LoopStandardAnalysisResults &, LPMUpdater &> {
168 PreservedAnalyses(Loop &, LoopAnalysisManager &,
169 LoopStandardAnalysisResults &, LPMUpdater &));
170 static void invalidateLoop(Loop &L, LoopAnalysisManager &,
171 LoopStandardAnalysisResults &,
172 LPMUpdater &Updater) {
173 Updater.markLoopAsDeleted(L, L.getName());
175 MockPassHandle() { setDefaults(); }
179 struct MockPassHandle<Function>
180 : MockPassHandleBase<MockPassHandle<Function>, Function> {
181 MOCK_METHOD2(run, PreservedAnalyses(Function &, FunctionAnalysisManager &));
183 MockPassHandle() { setDefaults(); }
187 struct MockPassHandle<LazyCallGraph::SCC>
188 : MockPassHandleBase<MockPassHandle<LazyCallGraph::SCC>, LazyCallGraph::SCC,
189 CGSCCAnalysisManager, LazyCallGraph &,
190 CGSCCUpdateResult &> {
192 PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
193 LazyCallGraph &G, CGSCCUpdateResult &UR));
195 static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
196 LazyCallGraph &, CGSCCUpdateResult &UR) {
197 UR.InvalidatedSCCs.insert(&C);
200 MockPassHandle() { setDefaults(); }
204 struct MockPassHandle<Module>
205 : MockPassHandleBase<MockPassHandle<Module>, Module> {
206 MOCK_METHOD2(run, PreservedAnalyses(Module &, ModuleAnalysisManager &));
208 MockPassHandle() { setDefaults(); }
211 /// Mock handles for analyses for the IRUnits Module, CGSCC, Function, Loop.
212 /// These handles define the appropriate run() and invalidate() mock interfaces
213 /// for the respective IRUnit type.
214 template <typename IRUnitT> struct MockAnalysisHandle;
216 struct MockAnalysisHandle<Loop>
217 : MockAnalysisHandleBase<MockAnalysisHandle<Loop>, Loop,
219 LoopStandardAnalysisResults &> {
221 MOCK_METHOD3_T(run, typename Analysis::Result(Loop &, LoopAnalysisManager &,
222 LoopStandardAnalysisResults &));
224 MOCK_METHOD3_T(invalidate, bool(Loop &, const PreservedAnalyses &,
225 LoopAnalysisManager::Invalidator &));
227 MockAnalysisHandle<Loop>() { this->setDefaults(); }
231 struct MockAnalysisHandle<Function>
232 : MockAnalysisHandleBase<MockAnalysisHandle<Function>, Function> {
233 MOCK_METHOD2(run, Analysis::Result(Function &, FunctionAnalysisManager &));
235 MOCK_METHOD3(invalidate, bool(Function &, const PreservedAnalyses &,
236 FunctionAnalysisManager::Invalidator &));
238 MockAnalysisHandle<Function>() { setDefaults(); }
242 struct MockAnalysisHandle<LazyCallGraph::SCC>
243 : MockAnalysisHandleBase<MockAnalysisHandle<LazyCallGraph::SCC>,
244 LazyCallGraph::SCC, CGSCCAnalysisManager,
246 MOCK_METHOD3(run, Analysis::Result(LazyCallGraph::SCC &,
247 CGSCCAnalysisManager &, LazyCallGraph &));
249 MOCK_METHOD3(invalidate, bool(LazyCallGraph::SCC &, const PreservedAnalyses &,
250 CGSCCAnalysisManager::Invalidator &));
252 MockAnalysisHandle<LazyCallGraph::SCC>() { setDefaults(); }
256 struct MockAnalysisHandle<Module>
257 : MockAnalysisHandleBase<MockAnalysisHandle<Module>, Module> {
258 MOCK_METHOD2(run, Analysis::Result(Module &, ModuleAnalysisManager &));
260 MOCK_METHOD3(invalidate, bool(Module &, const PreservedAnalyses &,
261 ModuleAnalysisManager::Invalidator &));
263 MockAnalysisHandle<Module>() { setDefaults(); }
266 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
268 return parseAssemblyString(IR, Err, C);
271 /// Helper for HasName matcher that returns getName both for IRUnit and
272 /// for IRUnit pointer wrapper into llvm::Any (wrapped by PassInstrumentation).
273 template <typename IRUnitT> std::string getName(const IRUnitT &IR) {
277 template <> std::string getName(const StringRef &name) { return name; }
279 template <> std::string getName(const llvm::Any &WrappedIR) {
280 if (any_isa<const Module *>(WrappedIR))
281 return any_cast<const Module *>(WrappedIR)->getName().str();
282 if (any_isa<const Function *>(WrappedIR))
283 return any_cast<const Function *>(WrappedIR)->getName().str();
284 if (any_isa<const Loop *>(WrappedIR))
285 return any_cast<const Loop *>(WrappedIR)->getName().str();
286 if (any_isa<const LazyCallGraph::SCC *>(WrappedIR))
287 return any_cast<const LazyCallGraph::SCC *>(WrappedIR)->getName();
290 /// Define a custom matcher for objects which support a 'getName' method.
292 /// LLVM often has IR objects or analysis objects which expose a name
293 /// and in tests it is convenient to match these by name for readability.
294 /// Usually, this name is either a StringRef or a plain std::string. This
295 /// matcher supports any type exposing a getName() method of this form whose
296 /// return value is compatible with an std::ostream. For StringRef, this uses
297 /// the shift operator defined above.
299 /// It should be used as:
301 /// HasName("my_function")
303 /// No namespace or other qualification is required.
304 MATCHER_P(HasName, Name, "") {
305 *result_listener << "has name '" << getName(arg) << "'";
306 return Name == getName(arg);
309 MATCHER_P(HasNameRegex, Name, "") {
310 *result_listener << "has name '" << getName(arg) << "'";
312 return r.match(getName(arg));
315 struct MockPassInstrumentationCallbacks {
316 PassInstrumentationCallbacks Callbacks;
318 MockPassInstrumentationCallbacks() {
319 ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true));
321 MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
322 MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any));
323 MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID));
324 MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
325 MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
327 void registerPassInstrumentation() {
328 Callbacks.registerBeforePassCallback([this](StringRef P, llvm::Any IR) {
329 return this->runBeforePass(P, IR);
331 Callbacks.registerAfterPassCallback(
332 [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); });
333 Callbacks.registerAfterPassInvalidatedCallback(
334 [this](StringRef P) { this->runAfterPassInvalidated(P); });
335 Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
336 return this->runBeforeAnalysis(P, IR);
338 Callbacks.registerAfterAnalysisCallback(
339 [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); });
342 void ignoreNonMockPassInstrumentation(StringRef IRName) {
343 // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
344 // parts of a pipeline that we do not care about (e.g. various passes added
345 // by default by PassBuilder - Verifier pass etc).
346 // Make sure to avoid ignoring Mock passes/analysis, we definitely want
347 // to check these explicitly.
349 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
351 EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName)))
354 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
357 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
362 template <typename PassManagerT> class PassBuilderCallbacksTest;
364 /// This test fixture is shared between all the actual tests below and
365 /// takes care of setting up appropriate defaults.
367 /// The template specialization serves to extract the IRUnit and AM types from
368 /// the given PassManagerT.
369 template <typename TestIRUnitT, typename... ExtraPassArgTs,
370 typename... ExtraAnalysisArgTs>
371 class PassBuilderCallbacksTest<PassManager<
372 TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>,
373 ExtraPassArgTs...>> : public testing::Test {
375 using IRUnitT = TestIRUnitT;
376 using AnalysisManagerT = AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>;
378 PassManager<TestIRUnitT, AnalysisManagerT, ExtraPassArgTs...>;
379 using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis;
382 std::unique_ptr<Module> M;
384 MockPassInstrumentationCallbacks CallbacksHandle;
387 ModulePassManager PM;
388 LoopAnalysisManager LAM;
389 FunctionAnalysisManager FAM;
390 CGSCCAnalysisManager CGAM;
391 ModuleAnalysisManager AM;
393 MockPassHandle<IRUnitT> PassHandle;
394 MockAnalysisHandle<IRUnitT> AnalysisHandle;
396 static PreservedAnalyses getAnalysisResult(IRUnitT &U, AnalysisManagerT &AM,
397 ExtraAnalysisArgTs &&... Args) {
398 (void)AM.template getResult<AnalysisT>(
399 U, std::forward<ExtraAnalysisArgTs>(Args)...);
400 return PreservedAnalyses::all();
403 PassBuilderCallbacksTest()
405 "declare void @bar()\n"
406 "define void @foo(i32 %n) {\n"
410 " %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
411 " %iv.next = add i32 %iv, 1\n"
412 " tail call void @bar()\n"
413 " %cmp = icmp eq i32 %iv, %n\n"
414 " br i1 %cmp, label %exit, label %loop\n"
418 CallbacksHandle(), PB(nullptr, None, &CallbacksHandle.Callbacks),
419 PM(true), LAM(true), FAM(true), CGAM(true), AM(true) {
421 /// Register a callback for analysis registration.
423 /// The callback is a function taking a reference to an AnalyisManager
424 /// object. When called, the callee gets to register its own analyses with
425 /// this PassBuilder instance.
426 PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) {
427 // Register our mock analysis
428 AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
431 /// Register a callback for pipeline parsing.
433 /// During parsing of a textual pipeline, the PassBuilder will call these
434 /// callbacks for each encountered pass name that it does not know. This
435 /// includes both simple pass names as well as names of sub-pipelines. In
436 /// the latter case, the InnerPipeline is not empty.
437 PB.registerPipelineParsingCallback(
438 [this](StringRef Name, PassManagerT &PM,
439 ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
440 /// Handle parsing of the names of analysis utilities such as
441 /// require<test-analysis> and invalidate<test-analysis> for our
442 /// analysis mock handle
443 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", Name, PM))
446 /// Parse the name of our pass mock handle
447 if (Name == "test-transform") {
448 PM.addPass(PassHandle.getPass());
454 /// Register builtin analyses and cross-register the analysis proxies
455 PB.registerModuleAnalyses(AM);
456 PB.registerCGSCCAnalyses(CGAM);
457 PB.registerFunctionAnalyses(FAM);
458 PB.registerLoopAnalyses(LAM);
459 PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
463 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
464 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
465 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
466 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
468 /// Test parsing of the name of our mock pass for all IRUnits.
470 /// The pass should by default run our mock analysis and then preserve it.
471 TEST_F(ModuleCallbacksTest, Passes) {
472 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
473 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
474 .WillOnce(Invoke(getAnalysisResult));
476 StringRef PipelineText = "test-transform";
477 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
478 << "Pipeline was: " << PipelineText;
483 TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
484 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
485 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
486 .WillOnce(Invoke(getAnalysisResult));
488 CallbacksHandle.registerPassInstrumentation();
489 // Non-mock instrumentation not specifically mentioned below can be ignored.
490 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
492 // PassInstrumentation calls should happen in-sequence, in the same order
493 // as passes/analyses are scheduled.
494 ::testing::Sequence PISequence;
495 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
496 HasName("<string>")))
497 .InSequence(PISequence);
498 EXPECT_CALL(CallbacksHandle,
499 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
500 HasName("<string>")))
501 .InSequence(PISequence);
504 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
505 .InSequence(PISequence);
506 EXPECT_CALL(CallbacksHandle,
507 runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
508 .InSequence(PISequence);
510 StringRef PipelineText = "test-transform";
511 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
512 << "Pipeline was: " << PipelineText;
517 TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
518 CallbacksHandle.registerPassInstrumentation();
519 // Non-mock instrumentation run here can safely be ignored.
520 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
522 // Skip the pass by returning false.
523 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
524 HasName("<string>")))
525 .WillOnce(Return(false));
527 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
528 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0);
530 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
532 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
534 EXPECT_CALL(CallbacksHandle,
535 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
537 EXPECT_CALL(CallbacksHandle,
538 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
541 StringRef PipelineText = "test-transform";
542 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
543 << "Pipeline was: " << PipelineText;
548 TEST_F(FunctionCallbacksTest, Passes) {
549 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
550 EXPECT_CALL(PassHandle, run(HasName("foo"), _))
551 .WillOnce(Invoke(getAnalysisResult));
553 StringRef PipelineText = "test-transform";
554 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
555 << "Pipeline was: " << PipelineText;
559 TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
560 CallbacksHandle.registerPassInstrumentation();
561 // Non-mock instrumentation not specifically mentioned below can be ignored.
562 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
563 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
565 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
566 EXPECT_CALL(PassHandle, run(HasName("foo"), _))
567 .WillOnce(Invoke(getAnalysisResult));
569 // PassInstrumentation calls should happen in-sequence, in the same order
570 // as passes/analyses are scheduled.
571 ::testing::Sequence PISequence;
572 EXPECT_CALL(CallbacksHandle,
573 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
574 .InSequence(PISequence);
577 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
578 .InSequence(PISequence);
581 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
582 .InSequence(PISequence);
583 EXPECT_CALL(CallbacksHandle,
584 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo")))
585 .InSequence(PISequence);
587 // Our mock pass does not invalidate IR.
588 EXPECT_CALL(CallbacksHandle,
589 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
592 StringRef PipelineText = "test-transform";
593 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
594 << "Pipeline was: " << PipelineText;
598 TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
599 CallbacksHandle.registerPassInstrumentation();
600 // Non-mock instrumentation run here can safely be ignored.
601 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
602 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
604 // Skip the pass by returning false.
605 EXPECT_CALL(CallbacksHandle,
606 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
607 .WillOnce(Return(false));
609 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
610 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0);
612 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
614 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
616 EXPECT_CALL(CallbacksHandle,
617 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
619 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
621 EXPECT_CALL(CallbacksHandle,
622 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
624 EXPECT_CALL(CallbacksHandle,
625 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
628 StringRef PipelineText = "test-transform";
629 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
630 << "Pipeline was: " << PipelineText;
634 TEST_F(LoopCallbacksTest, Passes) {
635 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
636 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
637 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
639 StringRef PipelineText = "test-transform";
640 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
641 << "Pipeline was: " << PipelineText;
645 TEST_F(LoopCallbacksTest, InstrumentedPasses) {
646 CallbacksHandle.registerPassInstrumentation();
647 // Non-mock instrumentation not specifically mentioned below can be ignored.
648 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
649 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
650 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
652 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
653 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
654 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
656 // PassInstrumentation calls should happen in-sequence, in the same order
657 // as passes/analyses are scheduled.
658 ::testing::Sequence PISequence;
659 EXPECT_CALL(CallbacksHandle,
660 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
661 .InSequence(PISequence);
664 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
665 .InSequence(PISequence);
668 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
669 .InSequence(PISequence);
670 EXPECT_CALL(CallbacksHandle,
671 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
672 .InSequence(PISequence);
674 // Our mock pass does not invalidate IR.
675 EXPECT_CALL(CallbacksHandle,
676 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
679 StringRef PipelineText = "test-transform";
680 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
681 << "Pipeline was: " << PipelineText;
685 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
686 CallbacksHandle.registerPassInstrumentation();
687 // Non-mock instrumentation not specifically mentioned below can be ignored.
688 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
689 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
690 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
692 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
693 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
694 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateLoop)),
695 WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
697 // PassInstrumentation calls should happen in-sequence, in the same order
698 // as passes/analyses are scheduled.
699 ::testing::Sequence PISequence;
700 EXPECT_CALL(CallbacksHandle,
701 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
702 .InSequence(PISequence);
705 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
706 .InSequence(PISequence);
709 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
710 .InSequence(PISequence);
711 EXPECT_CALL(CallbacksHandle,
712 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
713 .InSequence(PISequence);
714 EXPECT_CALL(CallbacksHandle,
715 runAfterPassInvalidated(HasNameRegex("^PassManager")))
716 .InSequence(PISequence);
718 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
719 EXPECT_CALL(CallbacksHandle,
720 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
723 StringRef PipelineText = "test-transform";
724 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
725 << "Pipeline was: " << PipelineText;
729 TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
730 CallbacksHandle.registerPassInstrumentation();
731 // Non-mock instrumentation run here can safely be ignored.
732 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
733 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
734 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
736 // Skip the pass by returning false.
737 EXPECT_CALL(CallbacksHandle,
738 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
739 .WillOnce(Return(false));
741 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
742 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0);
744 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
746 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
748 EXPECT_CALL(CallbacksHandle,
749 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
751 EXPECT_CALL(CallbacksHandle,
752 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
754 EXPECT_CALL(CallbacksHandle,
755 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
758 StringRef PipelineText = "test-transform";
759 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
760 << "Pipeline was: " << PipelineText;
764 TEST_F(CGSCCCallbacksTest, Passes) {
765 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
766 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
767 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
769 StringRef PipelineText = "test-transform";
770 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
771 << "Pipeline was: " << PipelineText;
775 TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
776 CallbacksHandle.registerPassInstrumentation();
777 // Non-mock instrumentation not specifically mentioned below can be ignored.
778 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
779 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
781 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
782 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
783 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
785 // PassInstrumentation calls should happen in-sequence, in the same order
786 // as passes/analyses are scheduled.
787 ::testing::Sequence PISequence;
788 EXPECT_CALL(CallbacksHandle,
789 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
790 .InSequence(PISequence);
793 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
794 .InSequence(PISequence);
797 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
798 .InSequence(PISequence);
799 EXPECT_CALL(CallbacksHandle,
800 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
801 .InSequence(PISequence);
803 // Our mock pass does not invalidate IR.
804 EXPECT_CALL(CallbacksHandle,
805 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
808 StringRef PipelineText = "test-transform";
809 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
810 << "Pipeline was: " << PipelineText;
814 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
815 CallbacksHandle.registerPassInstrumentation();
816 // Non-mock instrumentation not specifically mentioned below can be ignored.
817 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
818 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
820 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
821 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
822 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateSCC)),
823 WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
825 // PassInstrumentation calls should happen in-sequence, in the same order
826 // as passes/analyses are scheduled.
827 ::testing::Sequence PISequence;
828 EXPECT_CALL(CallbacksHandle,
829 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
830 .InSequence(PISequence);
833 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
834 .InSequence(PISequence);
837 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
838 .InSequence(PISequence);
839 EXPECT_CALL(CallbacksHandle,
840 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
841 .InSequence(PISequence);
842 EXPECT_CALL(CallbacksHandle,
843 runAfterPassInvalidated(HasNameRegex("^PassManager")))
844 .InSequence(PISequence);
846 // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
847 EXPECT_CALL(CallbacksHandle,
848 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
851 StringRef PipelineText = "test-transform";
852 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
853 << "Pipeline was: " << PipelineText;
857 TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
858 CallbacksHandle.registerPassInstrumentation();
859 // Non-mock instrumentation run here can safely be ignored.
860 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
861 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
863 // Skip the pass by returning false.
864 EXPECT_CALL(CallbacksHandle,
865 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
866 .WillOnce(Return(false));
868 // neither Analysis nor Pass are called.
869 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0);
870 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0);
872 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
874 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
876 EXPECT_CALL(CallbacksHandle,
877 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
879 EXPECT_CALL(CallbacksHandle,
880 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
882 EXPECT_CALL(CallbacksHandle,
883 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
886 StringRef PipelineText = "test-transform";
887 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
888 << "Pipeline was: " << PipelineText;
892 /// Test parsing of the names of analysis utilities for our mock analysis
895 /// We first require<>, then invalidate<> it, expecting the analysis to be run
896 /// once and subsequently invalidated.
897 TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
898 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
899 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
901 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
902 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
903 << "Pipeline was: " << PipelineText;
907 TEST_F(CGSCCCallbacksTest, PassUtilities) {
908 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
909 EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
911 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
912 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
913 << "Pipeline was: " << PipelineText;
917 TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
918 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
919 EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
921 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
922 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
923 << "Pipeline was: " << PipelineText;
927 TEST_F(LoopCallbacksTest, PassUtilities) {
928 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
929 EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
931 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
933 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
934 << "Pipeline was: " << PipelineText;
938 /// Test parsing of the top-level pipeline.
940 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
941 /// from PassBuilder if it encounters an unknown pipeline entry at the top level
942 /// (i.e., the first entry on the pipeline).
943 /// This test parses a pipeline named 'another-pipeline', whose only elements
944 /// may be the test-transform pass or the analysis utilities
945 TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
946 PB.registerParseTopLevelPipelineCallback([this](
947 ModulePassManager &MPM, ArrayRef<PassBuilder::PipelineElement> Pipeline,
948 bool VerifyEachPass, bool DebugLogging) {
949 auto &FirstName = Pipeline.front().Name;
950 auto &InnerPipeline = Pipeline.front().InnerPipeline;
951 if (FirstName == "another-pipeline") {
952 for (auto &E : InnerPipeline) {
953 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", E.Name, PM))
956 if (E.Name == "test-transform") {
957 PM.addPass(PassHandle.getPass());
966 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
967 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
968 .WillOnce(Invoke(getAnalysisResult));
969 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
971 StringRef PipelineText =
972 "another-pipeline(test-transform,invalidate<test-analysis>)";
973 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
974 << "Pipeline was: " << PipelineText;
977 /// Test the negative case
978 PipelineText = "another-pipeline(instcombine)";
979 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed())
980 << "Pipeline was: " << PipelineText;
982 } // end anonymous namespace