1 //===- unittests/IR/PassBuilderCallbacksTest.cpp - PB Callback Tests --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Testing/Support/Error.h"
10 #include <functional>
11 #include <gmock/gmock.h>
12 #include <gtest/gtest.h>
13 #include <llvm/ADT/Any.h>
14 #include <llvm/Analysis/CGSCCPassManager.h>
15 #include <llvm/Analysis/LoopAnalysisManager.h>
16 #include <llvm/AsmParser/Parser.h>
17 #include <llvm/IR/LLVMContext.h>
18 #include <llvm/IR/PassInstrumentation.h>
19 #include <llvm/IR/PassManager.h>
20 #include <llvm/Passes/PassBuilder.h>
21 #include <llvm/Support/Regex.h>
22 #include <llvm/Support/SourceMgr.h>
23 #include <llvm/Transforms/Scalar/LoopPassManager.h>
24 
25 using namespace llvm;
26 
27 namespace {
28 using testing::AnyNumber;
29 using testing::AtLeast;
30 using testing::DoDefault;
31 using testing::Not;
32 using testing::Return;
33 using testing::Expectation;
34 using testing::Invoke;
35 using testing::WithArgs;
36 using testing::_;
37 
38 /// A CRTP base for analysis mock handles
39 ///
40 /// This class reconciles mocking with the value semantics implementation of the
41 /// AnalysisManager. Analysis mock handles should derive from this class and
42 /// call \c setDefault() in their constroctur for wiring up the defaults defined
43 /// by this base with their mock run() and invalidate() implementations.
44 template <typename DerivedT, typename IRUnitT,
45           typename AnalysisManagerT = AnalysisManager<IRUnitT>,
46           typename... ExtraArgTs>
47 class MockAnalysisHandleBase {
48 public:
49   class Analysis : public AnalysisInfoMixin<Analysis> {
50     friend AnalysisInfoMixin<Analysis>;
51     friend MockAnalysisHandleBase;
52     static AnalysisKey Key;
53 
54     DerivedT *Handle;
55 
56     Analysis(DerivedT &Handle) : Handle(&Handle) {
57       static_assert(std::is_base_of<MockAnalysisHandleBase, DerivedT>::value,
58                     "Must pass the derived type to this template!");
59     }
60 
61   public:
62     class Result {
63       friend MockAnalysisHandleBase;
64 
65       DerivedT *Handle;
66 
67       Result(DerivedT &Handle) : Handle(&Handle) {}
68 
69     public:
70       // Forward invalidation events to the mock handle.
71       bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
72                       typename AnalysisManagerT::Invalidator &Inv) {
73         return Handle->invalidate(IR, PA, Inv);
74       }
75     };
76 
77     Result run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) {
78       return Handle->run(IR, AM, ExtraArgs...);
79     }
80   };
81 
82   Analysis getAnalysis() { return Analysis(static_cast<DerivedT &>(*this)); }
83   typename Analysis::Result getResult() {
84     return typename Analysis::Result(static_cast<DerivedT &>(*this));
85   }
86   static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
87 
88 protected:
89   // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within
90   // the template, so we use a boring static function.
91   static bool invalidateCallback(IRUnitT &IR, const PreservedAnalyses &PA,
92                                  typename AnalysisManagerT::Invalidator &Inv) {
93     auto PAC = PA.template getChecker<Analysis>();
94     return !PAC.preserved() &&
95            !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
96   }
97 
98   /// Derived classes should call this in their constructor to set up default
99   /// mock actions. (We can't do this in our constructor because this has to
100   /// run after the DerivedT is constructed.)
101   void setDefaults() {
102     ON_CALL(static_cast<DerivedT &>(*this),
103             run(_, _, testing::Matcher<ExtraArgTs>(_)...))
104         .WillByDefault(Return(this->getResult()));
105     ON_CALL(static_cast<DerivedT &>(*this), invalidate(_, _, _))
106         .WillByDefault(Invoke(&invalidateCallback));
107   }
108 };
109 
110 /// A CRTP base for pass mock handles
111 ///
112 /// This class reconciles mocking with the value semantics implementation of the
113 /// PassManager. Pass mock handles should derive from this class and
114 /// call \c setDefault() in their constroctur for wiring up the defaults defined
115 /// by this base with their mock run() and invalidate() implementations.
116 template <typename DerivedT, typename IRUnitT, typename AnalysisManagerT,
117           typename... ExtraArgTs>
118 AnalysisKey MockAnalysisHandleBase<DerivedT, IRUnitT, AnalysisManagerT,
119                                    ExtraArgTs...>::Analysis::Key;
120 
121 template <typename DerivedT, typename IRUnitT,
122           typename AnalysisManagerT = AnalysisManager<IRUnitT>,
123           typename... ExtraArgTs>
124 class MockPassHandleBase {
125 public:
126   class Pass : public PassInfoMixin<Pass> {
127     friend MockPassHandleBase;
128 
129     DerivedT *Handle;
130 
131     Pass(DerivedT &Handle) : Handle(&Handle) {
132       static_assert(std::is_base_of<MockPassHandleBase, DerivedT>::value,
133                     "Must pass the derived type to this template!");
134     }
135 
136   public:
137     PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
138                           ExtraArgTs... ExtraArgs) {
139       return Handle->run(IR, AM, ExtraArgs...);
140     }
141   };
142 
143   static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
144 
145   Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); }
146 
147 protected:
148   /// Derived classes should call this in their constructor to set up default
149   /// mock actions. (We can't do this in our constructor because this has to
150   /// run after the DerivedT is constructed.)
151   void setDefaults() {
152     ON_CALL(static_cast<DerivedT &>(*this),
153             run(_, _, testing::Matcher<ExtraArgTs>(_)...))
154         .WillByDefault(Return(PreservedAnalyses::all()));
155   }
156 };
157 
158 /// Mock handles for passes for the IRUnits Module, CGSCC, Function, Loop.
159 /// These handles define the appropriate run() mock interface for the respective
160 /// IRUnit type.
161 template <typename IRUnitT> struct MockPassHandle;
162 template <>
163 struct MockPassHandle<Loop>
164     : MockPassHandleBase<MockPassHandle<Loop>, Loop, LoopAnalysisManager,
165                          LoopStandardAnalysisResults &, LPMUpdater &> {
166   MOCK_METHOD4(run,
167                PreservedAnalyses(Loop &, LoopAnalysisManager &,
168                                  LoopStandardAnalysisResults &, LPMUpdater &));
169   static void invalidateLoop(Loop &L, LoopAnalysisManager &,
170                              LoopStandardAnalysisResults &,
171                              LPMUpdater &Updater) {
172     Updater.markLoopAsDeleted(L, L.getName());
173   }
174   MockPassHandle() { setDefaults(); }
175 };
176 
177 template <>
178 struct MockPassHandle<Function>
179     : MockPassHandleBase<MockPassHandle<Function>, Function> {
180   MOCK_METHOD2(run, PreservedAnalyses(Function &, FunctionAnalysisManager &));
181 
182   MockPassHandle() { setDefaults(); }
183 };
184 
185 template <>
186 struct MockPassHandle<LazyCallGraph::SCC>
187     : MockPassHandleBase<MockPassHandle<LazyCallGraph::SCC>, LazyCallGraph::SCC,
188                          CGSCCAnalysisManager, LazyCallGraph &,
189                          CGSCCUpdateResult &> {
190   MOCK_METHOD4(run,
191                PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
192                                  LazyCallGraph &G, CGSCCUpdateResult &UR));
193 
194   static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
195                             LazyCallGraph &, CGSCCUpdateResult &UR) {
196     UR.InvalidatedSCCs.insert(&C);
197   }
198 
199   MockPassHandle() { setDefaults(); }
200 };
201 
202 template <>
203 struct MockPassHandle<Module>
204     : MockPassHandleBase<MockPassHandle<Module>, Module> {
205   MOCK_METHOD2(run, PreservedAnalyses(Module &, ModuleAnalysisManager &));
206 
207   MockPassHandle() { setDefaults(); }
208 };
209 
210 /// Mock handles for analyses for the IRUnits Module, CGSCC, Function, Loop.
211 /// These handles define the appropriate run() and invalidate() mock interfaces
212 /// for the respective IRUnit type.
213 template <typename IRUnitT> struct MockAnalysisHandle;
214 template <>
215 struct MockAnalysisHandle<Loop>
216     : MockAnalysisHandleBase<MockAnalysisHandle<Loop>, Loop,
217                              LoopAnalysisManager,
218                              LoopStandardAnalysisResults &> {
219 
220   MOCK_METHOD3_T(run, typename Analysis::Result(Loop &, LoopAnalysisManager &,
221                                                 LoopStandardAnalysisResults &));
222 
223   MOCK_METHOD3_T(invalidate, bool(Loop &, const PreservedAnalyses &,
224                                   LoopAnalysisManager::Invalidator &));
225 
226   MockAnalysisHandle<Loop>() { this->setDefaults(); }
227 };
228 
229 template <>
230 struct MockAnalysisHandle<Function>
231     : MockAnalysisHandleBase<MockAnalysisHandle<Function>, Function> {
232   MOCK_METHOD2(run, Analysis::Result(Function &, FunctionAnalysisManager &));
233 
234   MOCK_METHOD3(invalidate, bool(Function &, const PreservedAnalyses &,
235                                 FunctionAnalysisManager::Invalidator &));
236 
237   MockAnalysisHandle<Function>() { setDefaults(); }
238 };
239 
240 template <>
241 struct MockAnalysisHandle<LazyCallGraph::SCC>
242     : MockAnalysisHandleBase<MockAnalysisHandle<LazyCallGraph::SCC>,
243                              LazyCallGraph::SCC, CGSCCAnalysisManager,
244                              LazyCallGraph &> {
245   MOCK_METHOD3(run, Analysis::Result(LazyCallGraph::SCC &,
246                                      CGSCCAnalysisManager &, LazyCallGraph &));
247 
248   MOCK_METHOD3(invalidate, bool(LazyCallGraph::SCC &, const PreservedAnalyses &,
249                                 CGSCCAnalysisManager::Invalidator &));
250 
251   MockAnalysisHandle<LazyCallGraph::SCC>() { setDefaults(); }
252 };
253 
254 template <>
255 struct MockAnalysisHandle<Module>
256     : MockAnalysisHandleBase<MockAnalysisHandle<Module>, Module> {
257   MOCK_METHOD2(run, Analysis::Result(Module &, ModuleAnalysisManager &));
258 
259   MOCK_METHOD3(invalidate, bool(Module &, const PreservedAnalyses &,
260                                 ModuleAnalysisManager::Invalidator &));
261 
262   MockAnalysisHandle<Module>() { setDefaults(); }
263 };
264 
265 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
266   SMDiagnostic Err;
267   return parseAssemblyString(IR, Err, C);
268 }
269 
270 /// Helper for HasName matcher that returns getName both for IRUnit and
271 /// for IRUnit pointer wrapper into llvm::Any (wrapped by PassInstrumentation).
272 template <typename IRUnitT> std::string getName(const IRUnitT &IR) {
273   return std::string(IR.getName());
274 }
275 
276 template <> std::string getName(const StringRef &name) {
277   return std::string(name);
278 }
279 
280 template <> std::string getName(const llvm::Any &WrappedIR) {
281   if (any_isa<const Module *>(WrappedIR))
282     return any_cast<const Module *>(WrappedIR)->getName().str();
283   if (any_isa<const Function *>(WrappedIR))
284     return any_cast<const Function *>(WrappedIR)->getName().str();
285   if (any_isa<const Loop *>(WrappedIR))
286     return any_cast<const Loop *>(WrappedIR)->getName().str();
287   if (any_isa<const LazyCallGraph::SCC *>(WrappedIR))
288     return any_cast<const LazyCallGraph::SCC *>(WrappedIR)->getName();
289   return "<UNKNOWN>";
290 }
291 /// Define a custom matcher for objects which support a 'getName' method.
292 ///
293 /// LLVM often has IR objects or analysis objects which expose a name
294 /// and in tests it is convenient to match these by name for readability.
295 /// Usually, this name is either a StringRef or a plain std::string. This
296 /// matcher supports any type exposing a getName() method of this form whose
297 /// return value is compatible with an std::ostream. For StringRef, this uses
298 /// the shift operator defined above.
299 ///
300 /// It should be used as:
301 ///
302 ///   HasName("my_function")
303 ///
304 /// No namespace or other qualification is required.
305 MATCHER_P(HasName, Name, "") {
306   *result_listener << "has name '" << getName(arg) << "'";
307   return Name == getName(arg);
308 }
309 
310 MATCHER_P(HasNameRegex, Name, "") {
311   *result_listener << "has name '" << getName(arg) << "'";
312   llvm::Regex r(Name);
313   return r.match(getName(arg));
314 }
315 
316 struct MockPassInstrumentationCallbacks {
317   PassInstrumentationCallbacks Callbacks;
318 
319   MockPassInstrumentationCallbacks() {
320     ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true));
321   }
322   MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
323   MOCK_METHOD2(runBeforeSkippedPass, void(StringRef PassID, llvm::Any));
324   MOCK_METHOD2(runBeforeNonSkippedPass, void(StringRef PassID, llvm::Any));
325   MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any));
326   MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID));
327   MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
328   MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
329 
330   void registerPassInstrumentation() {
331     Callbacks.registerBeforePassCallback([this](StringRef P, llvm::Any IR) {
332       return this->runBeforePass(P, IR);
333     });
334     Callbacks.registerBeforeSkippedPassCallback(
335         [this](StringRef P, llvm::Any IR) {
336           this->runBeforeSkippedPass(P, IR);
337         });
338     Callbacks.registerBeforeNonSkippedPassCallback(
339         [this](StringRef P, llvm::Any IR) {
340           this->runBeforeNonSkippedPass(P, IR);
341         });
342     Callbacks.registerAfterPassCallback(
343         [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); });
344     Callbacks.registerAfterPassInvalidatedCallback(
345         [this](StringRef P) { this->runAfterPassInvalidated(P); });
346     Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
347       return this->runBeforeAnalysis(P, IR);
348     });
349     Callbacks.registerAfterAnalysisCallback(
350         [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); });
351   }
352 
353   void ignoreNonMockPassInstrumentation(StringRef IRName) {
354     // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
355     // parts of a pipeline that we do not care about (e.g. various passes added
356     // by default by PassBuilder - Verifier pass etc).
357     // Make sure to avoid ignoring Mock passes/analysis, we definitely want
358     // to check these explicitly.
359     EXPECT_CALL(*this,
360                 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
361         .Times(AnyNumber());
362     EXPECT_CALL(
363         *this, runBeforeSkippedPass(Not(HasNameRegex("Mock")), HasName(IRName)))
364         .Times(AnyNumber());
365     EXPECT_CALL(*this, runBeforeNonSkippedPass(Not(HasNameRegex("Mock")),
366                                                HasName(IRName)))
367         .Times(AnyNumber());
368     EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName)))
369         .Times(AnyNumber());
370     EXPECT_CALL(*this,
371                 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
372         .Times(AnyNumber());
373     EXPECT_CALL(*this,
374                 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
375         .Times(AnyNumber());
376   }
377 };
378 
379 template <typename PassManagerT> class PassBuilderCallbacksTest;
380 
381 /// This test fixture is shared between all the actual tests below and
382 /// takes care of setting up appropriate defaults.
383 ///
384 /// The template specialization serves to extract the IRUnit and AM types from
385 /// the given PassManagerT.
386 template <typename TestIRUnitT, typename... ExtraPassArgTs,
387           typename... ExtraAnalysisArgTs>
388 class PassBuilderCallbacksTest<PassManager<
389     TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>,
390     ExtraPassArgTs...>> : public testing::Test {
391 protected:
392   using IRUnitT = TestIRUnitT;
393   using AnalysisManagerT = AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>;
394   using PassManagerT =
395       PassManager<TestIRUnitT, AnalysisManagerT, ExtraPassArgTs...>;
396   using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis;
397 
398   LLVMContext Context;
399   std::unique_ptr<Module> M;
400 
401   MockPassInstrumentationCallbacks CallbacksHandle;
402 
403   PassBuilder PB;
404   ModulePassManager PM;
405   LoopAnalysisManager LAM;
406   FunctionAnalysisManager FAM;
407   CGSCCAnalysisManager CGAM;
408   ModuleAnalysisManager AM;
409 
410   MockPassHandle<IRUnitT> PassHandle;
411   MockAnalysisHandle<IRUnitT> AnalysisHandle;
412 
413   static PreservedAnalyses getAnalysisResult(IRUnitT &U, AnalysisManagerT &AM,
414                                              ExtraAnalysisArgTs &&... Args) {
415     (void)AM.template getResult<AnalysisT>(
416         U, std::forward<ExtraAnalysisArgTs>(Args)...);
417     return PreservedAnalyses::all();
418   }
419 
420   PassBuilderCallbacksTest()
421       : M(parseIR(Context,
422                   "declare void @bar()\n"
423                   "define void @foo(i32 %n) {\n"
424                   "entry:\n"
425                   "  br label %loop\n"
426                   "loop:\n"
427                   "  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
428                   "  %iv.next = add i32 %iv, 1\n"
429                   "  tail call void @bar()\n"
430                   "  %cmp = icmp eq i32 %iv, %n\n"
431                   "  br i1 %cmp, label %exit, label %loop\n"
432                   "exit:\n"
433                   "  ret void\n"
434                   "}\n")),
435         CallbacksHandle(),
436         PB(nullptr, PipelineTuningOptions(), None, &CallbacksHandle.Callbacks),
437         PM(true), LAM(true), FAM(true), CGAM(true), AM(true) {
438 
439     EXPECT_TRUE(&CallbacksHandle.Callbacks ==
440                 PB.getPassInstrumentationCallbacks());
441 
442     /// Register a callback for analysis registration.
443     ///
444     /// The callback is a function taking a reference to an AnalyisManager
445     /// object. When called, the callee gets to register its own analyses with
446     /// this PassBuilder instance.
447     PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) {
448       // Register our mock analysis
449       AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
450     });
451 
452     /// Register a callback for pipeline parsing.
453     ///
454     /// During parsing of a textual pipeline, the PassBuilder will call these
455     /// callbacks for each encountered pass name that it does not know. This
456     /// includes both simple pass names as well as names of sub-pipelines. In
457     /// the latter case, the InnerPipeline is not empty.
458     PB.registerPipelineParsingCallback(
459         [this](StringRef Name, PassManagerT &PM,
460                ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
461           /// Handle parsing of the names of analysis utilities such as
462           /// require<test-analysis> and invalidate<test-analysis> for our
463           /// analysis mock handle
464           if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", Name, PM))
465             return true;
466 
467           /// Parse the name of our pass mock handle
468           if (Name == "test-transform") {
469             PM.addPass(PassHandle.getPass());
470             return true;
471           }
472           return false;
473         });
474 
475     /// Register builtin analyses and cross-register the analysis proxies
476     PB.registerModuleAnalyses(AM);
477     PB.registerCGSCCAnalyses(CGAM);
478     PB.registerFunctionAnalyses(FAM);
479     PB.registerLoopAnalyses(LAM);
480     PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
481   }
482 };
483 
484 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
485 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
486 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
487 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
488 
489 /// Test parsing of the name of our mock pass for all IRUnits.
490 ///
491 /// The pass should by default run our mock analysis and then preserve it.
492 TEST_F(ModuleCallbacksTest, Passes) {
493   EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
494   EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
495       .WillOnce(Invoke(getAnalysisResult));
496 
497   StringRef PipelineText = "test-transform";
498   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
499       << "Pipeline was: " << PipelineText;
500 
501   PM.run(*M, AM);
502 }
503 
504 TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
505   EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
506   EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
507       .WillOnce(Invoke(getAnalysisResult));
508 
509   CallbacksHandle.registerPassInstrumentation();
510   // Non-mock instrumentation not specifically mentioned below can be ignored.
511   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
512 
513   // PassInstrumentation calls should happen in-sequence, in the same order
514   // as passes/analyses are scheduled.
515   ::testing::Sequence PISequence;
516   EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
517                                              HasName("<string>")))
518       .InSequence(PISequence);
519   EXPECT_CALL(CallbacksHandle,
520               runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"),
521                                       HasName("<string>")))
522       .InSequence(PISequence);
523   EXPECT_CALL(CallbacksHandle,
524               runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
525                                 HasName("<string>")))
526       .InSequence(PISequence);
527   EXPECT_CALL(
528       CallbacksHandle,
529       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
530       .InSequence(PISequence);
531   EXPECT_CALL(CallbacksHandle,
532               runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
533       .InSequence(PISequence);
534 
535   // No passes are skipped, so there should be no calls to
536   // runBeforeSkippedPass().
537   EXPECT_CALL(
538       CallbacksHandle,
539       runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
540       .Times(0);
541 
542   StringRef PipelineText = "test-transform";
543   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
544       << "Pipeline was: " << PipelineText;
545 
546   PM.run(*M, AM);
547 }
548 
549 TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
550   CallbacksHandle.registerPassInstrumentation();
551   // Non-mock instrumentation run here can safely be ignored.
552   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
553   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
554 
555   // Skip all passes by returning false. Pass managers and adaptor passes are
556   // also passes that observed by the callbacks.
557   EXPECT_CALL(CallbacksHandle, runBeforePass(_, _))
558       .WillRepeatedly(Return(false));
559 
560   EXPECT_CALL(CallbacksHandle,
561               runBeforeSkippedPass(HasNameRegex("MockPassHandle"), _))
562       .Times(3);
563 
564   EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
565   EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0);
566 
567   // As the pass is skipped there is no nonskippedpass/afterPass,
568   // beforeAnalysis/afterAnalysis as well.
569   EXPECT_CALL(CallbacksHandle,
570               runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
571       .Times(0);
572   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
573       .Times(0);
574   EXPECT_CALL(CallbacksHandle,
575               runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
576       .Times(0);
577   EXPECT_CALL(CallbacksHandle,
578               runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
579       .Times(0);
580 
581   // Order is important here. `Adaptor` expectations should be checked first
582   // because the its argument contains 'PassManager' (for example:
583   // ModuleToFunctionPassAdaptor{{.*}}PassManager{{.*}}). Check
584   // `runBeforeNonSkippedPass` and `runAfterPass` to show that they are not
585   // skipped.
586   //
587   // Pass managers are not ignored.
588   // 5 = (1) ModulePassManager + (2) FunctionPassMangers + (1) LoopPassManager +
589   //     (1) CGSCCPassManager
590   EXPECT_CALL(CallbacksHandle,
591               runBeforeNonSkippedPass(HasNameRegex("PassManager"), _))
592       .Times(5);
593   EXPECT_CALL(
594       CallbacksHandle,
595       runBeforeNonSkippedPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _))
596       .Times(1);
597   EXPECT_CALL(CallbacksHandle,
598               runBeforeNonSkippedPass(
599                   HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _))
600       .Times(1);
601   EXPECT_CALL(
602       CallbacksHandle,
603       runBeforeNonSkippedPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _))
604       .Times(1);
605   EXPECT_CALL(
606       CallbacksHandle,
607       runBeforeNonSkippedPass(HasNameRegex("FunctionToLoopPassAdaptor"), _))
608       .Times(1);
609 
610   // The `runAfterPass` checks are the same as these of
611   // `runBeforeNonSkippedPass`.
612   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("PassManager"), _))
613       .Times(5);
614   EXPECT_CALL(CallbacksHandle,
615               runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _))
616       .Times(1);
617   EXPECT_CALL(
618       CallbacksHandle,
619       runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _))
620       .Times(1);
621   EXPECT_CALL(CallbacksHandle,
622               runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _))
623       .Times(1);
624   EXPECT_CALL(CallbacksHandle,
625               runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _))
626       .Times(1);
627 
628   // Ignore analyses introduced by adaptor passes.
629   EXPECT_CALL(CallbacksHandle,
630               runBeforeAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _))
631       .Times(AnyNumber());
632   EXPECT_CALL(CallbacksHandle,
633               runAfterAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _))
634       .Times(AnyNumber());
635 
636   // Register Funtion and Loop version of "test-transform" for testing
637   PB.registerPipelineParsingCallback(
638       [](StringRef Name, FunctionPassManager &FPM,
639          ArrayRef<PassBuilder::PipelineElement>) {
640         if (Name == "test-transform") {
641           FPM.addPass(MockPassHandle<Function>().getPass());
642           return true;
643         }
644         return false;
645       });
646   PB.registerPipelineParsingCallback(
647       [](StringRef Name, LoopPassManager &LPM,
648          ArrayRef<PassBuilder::PipelineElement>) {
649         if (Name == "test-transform") {
650           LPM.addPass(MockPassHandle<Loop>().getPass());
651           return true;
652         }
653         return false;
654       });
655 
656   StringRef PipelineText = "test-transform,function(test-transform),cgscc("
657                            "function(loop(test-transform)))";
658   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
659       << "Pipeline was: " << PipelineText;
660 
661   PM.run(*M, AM);
662 }
663 
664 TEST_F(FunctionCallbacksTest, Passes) {
665   EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
666   EXPECT_CALL(PassHandle, run(HasName("foo"), _))
667       .WillOnce(Invoke(getAnalysisResult));
668 
669   StringRef PipelineText = "test-transform";
670   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
671       << "Pipeline was: " << PipelineText;
672   PM.run(*M, AM);
673 }
674 
675 TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
676   CallbacksHandle.registerPassInstrumentation();
677   // Non-mock instrumentation not specifically mentioned below can be ignored.
678   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
679   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
680 
681   EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
682   EXPECT_CALL(PassHandle, run(HasName("foo"), _))
683       .WillOnce(Invoke(getAnalysisResult));
684 
685   // PassInstrumentation calls should happen in-sequence, in the same order
686   // as passes/analyses are scheduled.
687   ::testing::Sequence PISequence;
688   EXPECT_CALL(CallbacksHandle,
689               runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
690       .InSequence(PISequence);
691   EXPECT_CALL(
692       CallbacksHandle,
693       runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
694       .InSequence(PISequence);
695   EXPECT_CALL(
696       CallbacksHandle,
697       runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
698       .InSequence(PISequence);
699   EXPECT_CALL(
700       CallbacksHandle,
701       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
702       .InSequence(PISequence);
703   EXPECT_CALL(CallbacksHandle,
704               runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo")))
705       .InSequence(PISequence);
706 
707   // No passes are skipped, so there should be no calls to
708   // runBeforeSkippedPass().
709   EXPECT_CALL(
710       CallbacksHandle,
711       runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
712       .Times(0);
713 
714   // Our mock pass does not invalidate IR.
715   EXPECT_CALL(CallbacksHandle,
716               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
717       .Times(0);
718 
719   StringRef PipelineText = "test-transform";
720   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
721       << "Pipeline was: " << PipelineText;
722   PM.run(*M, AM);
723 }
724 
725 TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
726   CallbacksHandle.registerPassInstrumentation();
727   // Non-mock instrumentation run here can safely be ignored.
728   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
729   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
730 
731   // Skip the pass by returning false.
732   EXPECT_CALL(CallbacksHandle,
733               runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
734       .WillOnce(Return(false));
735 
736   EXPECT_CALL(
737       CallbacksHandle,
738       runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
739       .Times(1);
740 
741   EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
742   EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0);
743 
744   // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
745   // as well.
746   EXPECT_CALL(CallbacksHandle,
747               runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
748       .Times(0);
749   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
750       .Times(0);
751   EXPECT_CALL(CallbacksHandle,
752               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
753       .Times(0);
754   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
755       .Times(0);
756   EXPECT_CALL(CallbacksHandle,
757               runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
758       .Times(0);
759   EXPECT_CALL(CallbacksHandle,
760               runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
761       .Times(0);
762 
763   StringRef PipelineText = "test-transform";
764   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
765       << "Pipeline was: " << PipelineText;
766   PM.run(*M, AM);
767 }
768 
769 TEST_F(LoopCallbacksTest, Passes) {
770   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
771   EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
772       .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
773 
774   StringRef PipelineText = "test-transform";
775   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
776       << "Pipeline was: " << PipelineText;
777   PM.run(*M, AM);
778 }
779 
780 TEST_F(LoopCallbacksTest, InstrumentedPasses) {
781   CallbacksHandle.registerPassInstrumentation();
782   // Non-mock instrumentation not specifically mentioned below can be ignored.
783   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
784   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
785   CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
786 
787   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
788   EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
789       .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
790 
791   // PassInstrumentation calls should happen in-sequence, in the same order
792   // as passes/analyses are scheduled.
793   ::testing::Sequence PISequence;
794   EXPECT_CALL(CallbacksHandle,
795               runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
796       .InSequence(PISequence);
797   EXPECT_CALL(
798       CallbacksHandle,
799       runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
800       .InSequence(PISequence);
801   EXPECT_CALL(
802       CallbacksHandle,
803       runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
804       .InSequence(PISequence);
805   EXPECT_CALL(
806       CallbacksHandle,
807       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
808       .InSequence(PISequence);
809   EXPECT_CALL(CallbacksHandle,
810               runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
811       .InSequence(PISequence);
812 
813   // Our mock pass does not invalidate IR.
814   EXPECT_CALL(CallbacksHandle,
815               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
816       .Times(0);
817 
818   // No passes are skipped, so there should be no calls to
819   // runBeforeSkippedPass().
820   EXPECT_CALL(
821       CallbacksHandle,
822       runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
823       .Times(0);
824 
825   StringRef PipelineText = "test-transform";
826   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
827       << "Pipeline was: " << PipelineText;
828   PM.run(*M, AM);
829 }
830 
831 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
832   CallbacksHandle.registerPassInstrumentation();
833   // Non-mock instrumentation not specifically mentioned below can be ignored.
834   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
835   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
836   CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
837 
838   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
839   EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
840       .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateLoop)),
841                       WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
842 
843   // PassInstrumentation calls should happen in-sequence, in the same order
844   // as passes/analyses are scheduled.
845   ::testing::Sequence PISequence;
846   EXPECT_CALL(CallbacksHandle,
847               runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
848       .InSequence(PISequence);
849   EXPECT_CALL(
850       CallbacksHandle,
851       runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
852       .InSequence(PISequence);
853   EXPECT_CALL(
854       CallbacksHandle,
855       runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
856       .InSequence(PISequence);
857   EXPECT_CALL(
858       CallbacksHandle,
859       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
860       .InSequence(PISequence);
861   EXPECT_CALL(CallbacksHandle,
862               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
863       .InSequence(PISequence);
864   EXPECT_CALL(CallbacksHandle,
865               runAfterPassInvalidated(HasNameRegex("^PassManager")))
866       .InSequence(PISequence);
867 
868   // Our mock pass invalidates IR, thus normal runAfterPass is never called.
869   EXPECT_CALL(CallbacksHandle,
870               runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
871       .Times(0);
872 
873   StringRef PipelineText = "test-transform";
874   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
875       << "Pipeline was: " << PipelineText;
876   PM.run(*M, AM);
877 }
878 
879 TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
880   CallbacksHandle.registerPassInstrumentation();
881   // Non-mock instrumentation run here can safely be ignored.
882   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
883   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
884   CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
885 
886   // Skip the pass by returning false.
887   EXPECT_CALL(CallbacksHandle,
888               runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
889       .WillOnce(Return(false));
890 
891   EXPECT_CALL(
892       CallbacksHandle,
893       runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
894       .Times(1);
895 
896   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
897   EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0);
898 
899   // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
900   // as well.
901   EXPECT_CALL(CallbacksHandle,
902               runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
903       .Times(0);
904   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
905       .Times(0);
906   EXPECT_CALL(CallbacksHandle,
907               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
908       .Times(0);
909   EXPECT_CALL(CallbacksHandle,
910               runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
911       .Times(0);
912   EXPECT_CALL(CallbacksHandle,
913               runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
914       .Times(0);
915 
916   StringRef PipelineText = "test-transform";
917   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
918       << "Pipeline was: " << PipelineText;
919   PM.run(*M, AM);
920 }
921 
922 TEST_F(CGSCCCallbacksTest, Passes) {
923   EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
924   EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
925       .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
926 
927   StringRef PipelineText = "test-transform";
928   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
929       << "Pipeline was: " << PipelineText;
930   PM.run(*M, AM);
931 }
932 
933 TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
934   CallbacksHandle.registerPassInstrumentation();
935   // Non-mock instrumentation not specifically mentioned below can be ignored.
936   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
937   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
938   CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
939 
940   EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
941   EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
942       .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
943 
944   // PassInstrumentation calls should happen in-sequence, in the same order
945   // as passes/analyses are scheduled.
946   ::testing::Sequence PISequence;
947   EXPECT_CALL(CallbacksHandle,
948               runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
949       .InSequence(PISequence);
950   EXPECT_CALL(
951       CallbacksHandle,
952       runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
953       .InSequence(PISequence);
954   EXPECT_CALL(
955       CallbacksHandle,
956       runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
957       .InSequence(PISequence);
958   EXPECT_CALL(
959       CallbacksHandle,
960       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
961       .InSequence(PISequence);
962   EXPECT_CALL(CallbacksHandle,
963               runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
964       .InSequence(PISequence);
965 
966   // Our mock pass does not invalidate IR.
967   EXPECT_CALL(CallbacksHandle,
968               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
969       .Times(0);
970 
971   // No passes are skipped, so there should be no calls to
972   // runBeforeSkippedPass().
973   EXPECT_CALL(
974       CallbacksHandle,
975       runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
976       .Times(0);
977 
978   StringRef PipelineText = "test-transform";
979   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
980       << "Pipeline was: " << PipelineText;
981   PM.run(*M, AM);
982 }
983 
984 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
985   CallbacksHandle.registerPassInstrumentation();
986   // Non-mock instrumentation not specifically mentioned below can be ignored.
987   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
988   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
989   CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
990 
991   EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
992   EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
993       .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateSCC)),
994                       WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
995 
996   // PassInstrumentation calls should happen in-sequence, in the same order
997   // as passes/analyses are scheduled.
998   ::testing::Sequence PISequence;
999   EXPECT_CALL(CallbacksHandle,
1000               runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1001       .InSequence(PISequence);
1002   EXPECT_CALL(
1003       CallbacksHandle,
1004       runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1005       .InSequence(PISequence);
1006   EXPECT_CALL(
1007       CallbacksHandle,
1008       runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1009       .InSequence(PISequence);
1010   EXPECT_CALL(
1011       CallbacksHandle,
1012       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1013       .InSequence(PISequence);
1014   EXPECT_CALL(CallbacksHandle,
1015               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
1016       .InSequence(PISequence);
1017   EXPECT_CALL(CallbacksHandle,
1018               runAfterPassInvalidated(HasNameRegex("^PassManager")))
1019       .InSequence(PISequence);
1020 
1021   // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
1022   EXPECT_CALL(CallbacksHandle,
1023               runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1024       .Times(0);
1025 
1026   StringRef PipelineText = "test-transform";
1027   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1028       << "Pipeline was: " << PipelineText;
1029   PM.run(*M, AM);
1030 }
1031 
1032 TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
1033   CallbacksHandle.registerPassInstrumentation();
1034   // Non-mock instrumentation run here can safely be ignored.
1035   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1036   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1037   CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
1038 
1039   // Skip the pass by returning false.
1040   EXPECT_CALL(CallbacksHandle,
1041               runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1042       .WillOnce(Return(false));
1043 
1044   EXPECT_CALL(
1045       CallbacksHandle,
1046       runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1047       .Times(1);
1048 
1049   // neither Analysis nor Pass are called.
1050   EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0);
1051   EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0);
1052 
1053   // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
1054   // as well.
1055   EXPECT_CALL(CallbacksHandle,
1056               runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
1057       .Times(0);
1058   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
1059       .Times(0);
1060   EXPECT_CALL(CallbacksHandle,
1061               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
1062       .Times(0);
1063   EXPECT_CALL(CallbacksHandle,
1064               runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1065       .Times(0);
1066   EXPECT_CALL(CallbacksHandle,
1067               runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1068       .Times(0);
1069 
1070   StringRef PipelineText = "test-transform";
1071   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1072       << "Pipeline was: " << PipelineText;
1073   PM.run(*M, AM);
1074 }
1075 
1076 /// Test parsing of the names of analysis utilities for our mock analysis
1077 /// for all IRUnits.
1078 ///
1079 /// We first require<>, then invalidate<> it, expecting the analysis to be run
1080 /// once and subsequently invalidated.
1081 TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
1082   EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
1083   EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
1084 
1085   StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1086   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1087       << "Pipeline was: " << PipelineText;
1088   PM.run(*M, AM);
1089 }
1090 
1091 TEST_F(CGSCCCallbacksTest, PassUtilities) {
1092   EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1093   EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
1094 
1095   StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1096   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1097       << "Pipeline was: " << PipelineText;
1098   PM.run(*M, AM);
1099 }
1100 
1101 TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
1102   EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
1103   EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
1104 
1105   StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1106   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1107       << "Pipeline was: " << PipelineText;
1108   PM.run(*M, AM);
1109 }
1110 
1111 TEST_F(LoopCallbacksTest, PassUtilities) {
1112   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
1113   EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
1114 
1115   StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1116 
1117   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1118       << "Pipeline was: " << PipelineText;
1119   PM.run(*M, AM);
1120 }
1121 
1122 /// Test parsing of the top-level pipeline.
1123 ///
1124 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
1125 /// from PassBuilder if it encounters an unknown pipeline entry at the top level
1126 /// (i.e., the first entry on the pipeline).
1127 /// This test parses a pipeline named 'another-pipeline', whose only elements
1128 /// may be the test-transform pass or the analysis utilities
1129 TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
1130   PB.registerParseTopLevelPipelineCallback([this](
1131       ModulePassManager &MPM, ArrayRef<PassBuilder::PipelineElement> Pipeline,
1132       bool VerifyEachPass, bool DebugLogging) {
1133     auto &FirstName = Pipeline.front().Name;
1134     auto &InnerPipeline = Pipeline.front().InnerPipeline;
1135     if (FirstName == "another-pipeline") {
1136       for (auto &E : InnerPipeline) {
1137         if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", E.Name, PM))
1138           continue;
1139 
1140         if (E.Name == "test-transform") {
1141           PM.addPass(PassHandle.getPass());
1142           continue;
1143         }
1144         return false;
1145       }
1146     }
1147     return true;
1148   });
1149 
1150   EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
1151   EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
1152       .WillOnce(Invoke(getAnalysisResult));
1153   EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
1154 
1155   StringRef PipelineText =
1156       "another-pipeline(test-transform,invalidate<test-analysis>)";
1157   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1158       << "Pipeline was: " << PipelineText;
1159   PM.run(*M, AM);
1160 
1161   /// Test the negative case
1162   PipelineText = "another-pipeline(instcombine)";
1163   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed())
1164       << "Pipeline was: " << PipelineText;
1165 }
1166 } // end anonymous namespace
1167