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(runBeforeNonSkippedPass, void(StringRef PassID, llvm::Any));
324   MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any));
325   MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID));
326   MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
327   MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
328 
329   void registerPassInstrumentation() {
330     Callbacks.registerBeforePassCallback([this](StringRef P, llvm::Any IR) {
331       return this->runBeforePass(P, IR);
332     });
333     Callbacks.registerBeforeNonSkippedPassCallback(
334         [this](StringRef P, llvm::Any IR) {
335           this->runBeforeNonSkippedPass(P, IR);
336         });
337     Callbacks.registerAfterPassCallback(
338         [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); });
339     Callbacks.registerAfterPassInvalidatedCallback(
340         [this](StringRef P) { this->runAfterPassInvalidated(P); });
341     Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
342       return this->runBeforeAnalysis(P, IR);
343     });
344     Callbacks.registerAfterAnalysisCallback(
345         [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); });
346   }
347 
348   void ignoreNonMockPassInstrumentation(StringRef IRName) {
349     // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
350     // parts of a pipeline that we do not care about (e.g. various passes added
351     // by default by PassBuilder - Verifier pass etc).
352     // Make sure to avoid ignoring Mock passes/analysis, we definitely want
353     // to check these explicitly.
354     EXPECT_CALL(*this,
355                 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
356         .Times(AnyNumber());
357     EXPECT_CALL(*this, runBeforeNonSkippedPass(Not(HasNameRegex("Mock")),
358                                                HasName(IRName)))
359         .Times(AnyNumber());
360     EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName)))
361         .Times(AnyNumber());
362     EXPECT_CALL(*this,
363                 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
364         .Times(AnyNumber());
365     EXPECT_CALL(*this,
366                 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
367         .Times(AnyNumber());
368   }
369 };
370 
371 template <typename PassManagerT> class PassBuilderCallbacksTest;
372 
373 /// This test fixture is shared between all the actual tests below and
374 /// takes care of setting up appropriate defaults.
375 ///
376 /// The template specialization serves to extract the IRUnit and AM types from
377 /// the given PassManagerT.
378 template <typename TestIRUnitT, typename... ExtraPassArgTs,
379           typename... ExtraAnalysisArgTs>
380 class PassBuilderCallbacksTest<PassManager<
381     TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>,
382     ExtraPassArgTs...>> : public testing::Test {
383 protected:
384   using IRUnitT = TestIRUnitT;
385   using AnalysisManagerT = AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>;
386   using PassManagerT =
387       PassManager<TestIRUnitT, AnalysisManagerT, ExtraPassArgTs...>;
388   using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis;
389 
390   LLVMContext Context;
391   std::unique_ptr<Module> M;
392 
393   MockPassInstrumentationCallbacks CallbacksHandle;
394 
395   PassBuilder PB;
396   ModulePassManager PM;
397   LoopAnalysisManager LAM;
398   FunctionAnalysisManager FAM;
399   CGSCCAnalysisManager CGAM;
400   ModuleAnalysisManager AM;
401 
402   MockPassHandle<IRUnitT> PassHandle;
403   MockAnalysisHandle<IRUnitT> AnalysisHandle;
404 
405   static PreservedAnalyses getAnalysisResult(IRUnitT &U, AnalysisManagerT &AM,
406                                              ExtraAnalysisArgTs &&... Args) {
407     (void)AM.template getResult<AnalysisT>(
408         U, std::forward<ExtraAnalysisArgTs>(Args)...);
409     return PreservedAnalyses::all();
410   }
411 
412   PassBuilderCallbacksTest()
413       : M(parseIR(Context,
414                   "declare void @bar()\n"
415                   "define void @foo(i32 %n) {\n"
416                   "entry:\n"
417                   "  br label %loop\n"
418                   "loop:\n"
419                   "  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
420                   "  %iv.next = add i32 %iv, 1\n"
421                   "  tail call void @bar()\n"
422                   "  %cmp = icmp eq i32 %iv, %n\n"
423                   "  br i1 %cmp, label %exit, label %loop\n"
424                   "exit:\n"
425                   "  ret void\n"
426                   "}\n")),
427         CallbacksHandle(),
428         PB(nullptr, PipelineTuningOptions(), None, &CallbacksHandle.Callbacks),
429         PM(true), LAM(true), FAM(true), CGAM(true), AM(true) {
430 
431     EXPECT_TRUE(&CallbacksHandle.Callbacks ==
432                 PB.getPassInstrumentationCallbacks());
433 
434     /// Register a callback for analysis registration.
435     ///
436     /// The callback is a function taking a reference to an AnalyisManager
437     /// object. When called, the callee gets to register its own analyses with
438     /// this PassBuilder instance.
439     PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) {
440       // Register our mock analysis
441       AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
442     });
443 
444     /// Register a callback for pipeline parsing.
445     ///
446     /// During parsing of a textual pipeline, the PassBuilder will call these
447     /// callbacks for each encountered pass name that it does not know. This
448     /// includes both simple pass names as well as names of sub-pipelines. In
449     /// the latter case, the InnerPipeline is not empty.
450     PB.registerPipelineParsingCallback(
451         [this](StringRef Name, PassManagerT &PM,
452                ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
453           /// Handle parsing of the names of analysis utilities such as
454           /// require<test-analysis> and invalidate<test-analysis> for our
455           /// analysis mock handle
456           if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", Name, PM))
457             return true;
458 
459           /// Parse the name of our pass mock handle
460           if (Name == "test-transform") {
461             PM.addPass(PassHandle.getPass());
462             return true;
463           }
464           return false;
465         });
466 
467     /// Register builtin analyses and cross-register the analysis proxies
468     PB.registerModuleAnalyses(AM);
469     PB.registerCGSCCAnalyses(CGAM);
470     PB.registerFunctionAnalyses(FAM);
471     PB.registerLoopAnalyses(LAM);
472     PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
473   }
474 };
475 
476 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
477 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
478 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
479 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
480 
481 /// Test parsing of the name of our mock pass for all IRUnits.
482 ///
483 /// The pass should by default run our mock analysis and then preserve it.
484 TEST_F(ModuleCallbacksTest, Passes) {
485   EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
486   EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
487       .WillOnce(Invoke(getAnalysisResult));
488 
489   StringRef PipelineText = "test-transform";
490   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
491       << "Pipeline was: " << PipelineText;
492 
493   PM.run(*M, AM);
494 }
495 
496 TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
497   EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
498   EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
499       .WillOnce(Invoke(getAnalysisResult));
500 
501   CallbacksHandle.registerPassInstrumentation();
502   // Non-mock instrumentation not specifically mentioned below can be ignored.
503   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
504 
505   // PassInstrumentation calls should happen in-sequence, in the same order
506   // as passes/analyses are scheduled.
507   ::testing::Sequence PISequence;
508   EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
509                                              HasName("<string>")))
510       .InSequence(PISequence);
511   EXPECT_CALL(CallbacksHandle,
512               runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"),
513                                       HasName("<string>")))
514       .InSequence(PISequence);
515   EXPECT_CALL(CallbacksHandle,
516               runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
517                                 HasName("<string>")))
518       .InSequence(PISequence);
519   EXPECT_CALL(
520       CallbacksHandle,
521       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
522       .InSequence(PISequence);
523   EXPECT_CALL(CallbacksHandle,
524               runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
525       .InSequence(PISequence);
526 
527   StringRef PipelineText = "test-transform";
528   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
529       << "Pipeline was: " << PipelineText;
530 
531   PM.run(*M, AM);
532 }
533 
534 TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
535   CallbacksHandle.registerPassInstrumentation();
536   // Non-mock instrumentation run here can safely be ignored.
537   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
538 
539   // Skip all passes by returning false. Pass managers and adaptor passes are
540   // also passes that observed by the callbacks.
541   EXPECT_CALL(CallbacksHandle, runBeforePass(_, _))
542       .WillRepeatedly(Return(false));
543 
544   EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
545   EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0);
546 
547   // As the pass is skipped there is no nonskippedpass/afterPass,
548   // beforeAnalysis/afterAnalysis as well.
549   EXPECT_CALL(CallbacksHandle,
550               runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
551       .Times(0);
552   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
553       .Times(0);
554   EXPECT_CALL(CallbacksHandle,
555               runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
556       .Times(0);
557   EXPECT_CALL(CallbacksHandle,
558               runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
559       .Times(0);
560 
561   // Order is important here. `Adaptor` expectations should be checked first
562   // because the its argument contains 'PassManager' (for example:
563   // ModuleToFunctionPassAdaptor{{.*}}PassManager{{.*}}). Check
564   // `runBeforeNonSkippedPass` and `runAfterPass` to show that they are not
565   // skipped.
566   //
567   // Pass managers are not ignored.
568   // 5 = (1) ModulePassManager + (2) FunctionPassMangers + (1) LoopPassManager +
569   //     (1) CGSCCPassManager
570   EXPECT_CALL(CallbacksHandle,
571               runBeforeNonSkippedPass(HasNameRegex("PassManager"), _))
572       .Times(5);
573   EXPECT_CALL(
574       CallbacksHandle,
575       runBeforeNonSkippedPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _))
576       .Times(1);
577   EXPECT_CALL(CallbacksHandle,
578               runBeforeNonSkippedPass(
579                   HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _))
580       .Times(1);
581   EXPECT_CALL(
582       CallbacksHandle,
583       runBeforeNonSkippedPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _))
584       .Times(1);
585   EXPECT_CALL(
586       CallbacksHandle,
587       runBeforeNonSkippedPass(HasNameRegex("FunctionToLoopPassAdaptor"), _))
588       .Times(1);
589 
590   // The `runAfterPass` checks are the same as these of
591   // `runBeforeNonSkippedPass`.
592   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("PassManager"), _))
593       .Times(5);
594   EXPECT_CALL(CallbacksHandle,
595               runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _))
596       .Times(1);
597   EXPECT_CALL(
598       CallbacksHandle,
599       runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _))
600       .Times(1);
601   EXPECT_CALL(CallbacksHandle,
602               runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _))
603       .Times(1);
604   EXPECT_CALL(CallbacksHandle,
605               runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _))
606       .Times(1);
607 
608   // Ignore analyses introduced by adaptor passes.
609   EXPECT_CALL(CallbacksHandle,
610               runBeforeAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _))
611       .Times(AnyNumber());
612   EXPECT_CALL(CallbacksHandle,
613               runAfterAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _))
614       .Times(AnyNumber());
615 
616   // Register Funtion and Loop version of "test-transform" for testing
617   PB.registerPipelineParsingCallback(
618       [](StringRef Name, FunctionPassManager &FPM,
619          ArrayRef<PassBuilder::PipelineElement>) {
620         if (Name == "test-transform") {
621           FPM.addPass(MockPassHandle<Function>().getPass());
622           return true;
623         }
624         return false;
625       });
626   PB.registerPipelineParsingCallback(
627       [](StringRef Name, LoopPassManager &LPM,
628          ArrayRef<PassBuilder::PipelineElement>) {
629         if (Name == "test-transform") {
630           LPM.addPass(MockPassHandle<Loop>().getPass());
631           return true;
632         }
633         return false;
634       });
635 
636   StringRef PipelineText = "test-transform,function(test-transform),cgscc("
637                            "function(loop(test-transform)))";
638   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
639       << "Pipeline was: " << PipelineText;
640 
641   PM.run(*M, AM);
642 }
643 
644 TEST_F(FunctionCallbacksTest, Passes) {
645   EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
646   EXPECT_CALL(PassHandle, run(HasName("foo"), _))
647       .WillOnce(Invoke(getAnalysisResult));
648 
649   StringRef PipelineText = "test-transform";
650   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
651       << "Pipeline was: " << PipelineText;
652   PM.run(*M, AM);
653 }
654 
655 TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
656   CallbacksHandle.registerPassInstrumentation();
657   // Non-mock instrumentation not specifically mentioned below can be ignored.
658   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
659   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
660 
661   EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
662   EXPECT_CALL(PassHandle, run(HasName("foo"), _))
663       .WillOnce(Invoke(getAnalysisResult));
664 
665   // PassInstrumentation calls should happen in-sequence, in the same order
666   // as passes/analyses are scheduled.
667   ::testing::Sequence PISequence;
668   EXPECT_CALL(CallbacksHandle,
669               runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
670       .InSequence(PISequence);
671   EXPECT_CALL(
672       CallbacksHandle,
673       runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
674       .InSequence(PISequence);
675   EXPECT_CALL(
676       CallbacksHandle,
677       runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
678       .InSequence(PISequence);
679   EXPECT_CALL(
680       CallbacksHandle,
681       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
682       .InSequence(PISequence);
683   EXPECT_CALL(CallbacksHandle,
684               runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo")))
685       .InSequence(PISequence);
686 
687   // Our mock pass does not invalidate IR.
688   EXPECT_CALL(CallbacksHandle,
689               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
690       .Times(0);
691 
692   StringRef PipelineText = "test-transform";
693   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
694       << "Pipeline was: " << PipelineText;
695   PM.run(*M, AM);
696 }
697 
698 TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
699   CallbacksHandle.registerPassInstrumentation();
700   // Non-mock instrumentation run here can safely be ignored.
701   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
702   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
703 
704   // Skip the pass by returning false.
705   EXPECT_CALL(CallbacksHandle,
706               runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
707       .WillOnce(Return(false));
708 
709   EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
710   EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0);
711 
712   // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
713   // as well.
714   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
715       .Times(0);
716   EXPECT_CALL(CallbacksHandle,
717               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
718       .Times(0);
719   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
720       .Times(0);
721   EXPECT_CALL(CallbacksHandle,
722               runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
723       .Times(0);
724   EXPECT_CALL(CallbacksHandle,
725               runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
726       .Times(0);
727 
728   StringRef PipelineText = "test-transform";
729   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
730       << "Pipeline was: " << PipelineText;
731   PM.run(*M, AM);
732 }
733 
734 TEST_F(LoopCallbacksTest, Passes) {
735   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
736   EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
737       .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
738 
739   StringRef PipelineText = "test-transform";
740   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
741       << "Pipeline was: " << PipelineText;
742   PM.run(*M, AM);
743 }
744 
745 TEST_F(LoopCallbacksTest, InstrumentedPasses) {
746   CallbacksHandle.registerPassInstrumentation();
747   // Non-mock instrumentation not specifically mentioned below can be ignored.
748   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
749   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
750   CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
751 
752   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
753   EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
754       .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
755 
756   // PassInstrumentation calls should happen in-sequence, in the same order
757   // as passes/analyses are scheduled.
758   ::testing::Sequence PISequence;
759   EXPECT_CALL(CallbacksHandle,
760               runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
761       .InSequence(PISequence);
762   EXPECT_CALL(
763       CallbacksHandle,
764       runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
765       .InSequence(PISequence);
766   EXPECT_CALL(
767       CallbacksHandle,
768       runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
769       .InSequence(PISequence);
770   EXPECT_CALL(
771       CallbacksHandle,
772       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
773       .InSequence(PISequence);
774   EXPECT_CALL(CallbacksHandle,
775               runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
776       .InSequence(PISequence);
777 
778   // Our mock pass does not invalidate IR.
779   EXPECT_CALL(CallbacksHandle,
780               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
781       .Times(0);
782 
783   StringRef PipelineText = "test-transform";
784   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
785       << "Pipeline was: " << PipelineText;
786   PM.run(*M, AM);
787 }
788 
789 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
790   CallbacksHandle.registerPassInstrumentation();
791   // Non-mock instrumentation not specifically mentioned below can be ignored.
792   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
793   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
794   CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
795 
796   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
797   EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
798       .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateLoop)),
799                       WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
800 
801   // PassInstrumentation calls should happen in-sequence, in the same order
802   // as passes/analyses are scheduled.
803   ::testing::Sequence PISequence;
804   EXPECT_CALL(CallbacksHandle,
805               runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
806       .InSequence(PISequence);
807   EXPECT_CALL(
808       CallbacksHandle,
809       runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
810       .InSequence(PISequence);
811   EXPECT_CALL(
812       CallbacksHandle,
813       runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
814       .InSequence(PISequence);
815   EXPECT_CALL(
816       CallbacksHandle,
817       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
818       .InSequence(PISequence);
819   EXPECT_CALL(CallbacksHandle,
820               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
821       .InSequence(PISequence);
822   EXPECT_CALL(CallbacksHandle,
823               runAfterPassInvalidated(HasNameRegex("^PassManager")))
824       .InSequence(PISequence);
825 
826   // Our mock pass invalidates IR, thus normal runAfterPass is never called.
827   EXPECT_CALL(CallbacksHandle,
828               runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
829       .Times(0);
830 
831   StringRef PipelineText = "test-transform";
832   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
833       << "Pipeline was: " << PipelineText;
834   PM.run(*M, AM);
835 }
836 
837 TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
838   CallbacksHandle.registerPassInstrumentation();
839   // Non-mock instrumentation run here can safely be ignored.
840   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
841   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
842   CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
843 
844   // Skip the pass by returning false.
845   EXPECT_CALL(CallbacksHandle,
846               runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
847       .WillOnce(Return(false));
848 
849   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
850   EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0);
851 
852   // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
853   // as well.
854   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
855       .Times(0);
856   EXPECT_CALL(CallbacksHandle,
857               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
858       .Times(0);
859   EXPECT_CALL(CallbacksHandle,
860               runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
861       .Times(0);
862   EXPECT_CALL(CallbacksHandle,
863               runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
864       .Times(0);
865 
866   StringRef PipelineText = "test-transform";
867   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
868       << "Pipeline was: " << PipelineText;
869   PM.run(*M, AM);
870 }
871 
872 TEST_F(CGSCCCallbacksTest, Passes) {
873   EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
874   EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
875       .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
876 
877   StringRef PipelineText = "test-transform";
878   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
879       << "Pipeline was: " << PipelineText;
880   PM.run(*M, AM);
881 }
882 
883 TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
884   CallbacksHandle.registerPassInstrumentation();
885   // Non-mock instrumentation not specifically mentioned below can be ignored.
886   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
887   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
888   CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
889 
890   EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
891   EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
892       .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
893 
894   // PassInstrumentation calls should happen in-sequence, in the same order
895   // as passes/analyses are scheduled.
896   ::testing::Sequence PISequence;
897   EXPECT_CALL(CallbacksHandle,
898               runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
899       .InSequence(PISequence);
900   EXPECT_CALL(
901       CallbacksHandle,
902       runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
903       .InSequence(PISequence);
904   EXPECT_CALL(
905       CallbacksHandle,
906       runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
907       .InSequence(PISequence);
908   EXPECT_CALL(
909       CallbacksHandle,
910       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
911       .InSequence(PISequence);
912   EXPECT_CALL(CallbacksHandle,
913               runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
914       .InSequence(PISequence);
915 
916   // Our mock pass does not invalidate IR.
917   EXPECT_CALL(CallbacksHandle,
918               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
919       .Times(0);
920 
921   StringRef PipelineText = "test-transform";
922   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
923       << "Pipeline was: " << PipelineText;
924   PM.run(*M, AM);
925 }
926 
927 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
928   CallbacksHandle.registerPassInstrumentation();
929   // Non-mock instrumentation not specifically mentioned below can be ignored.
930   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
931   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
932   CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
933 
934   EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
935   EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
936       .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateSCC)),
937                       WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
938 
939   // PassInstrumentation calls should happen in-sequence, in the same order
940   // as passes/analyses are scheduled.
941   ::testing::Sequence PISequence;
942   EXPECT_CALL(CallbacksHandle,
943               runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
944       .InSequence(PISequence);
945   EXPECT_CALL(
946       CallbacksHandle,
947       runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
948       .InSequence(PISequence);
949   EXPECT_CALL(
950       CallbacksHandle,
951       runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
952       .InSequence(PISequence);
953   EXPECT_CALL(
954       CallbacksHandle,
955       runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
956       .InSequence(PISequence);
957   EXPECT_CALL(CallbacksHandle,
958               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
959       .InSequence(PISequence);
960   EXPECT_CALL(CallbacksHandle,
961               runAfterPassInvalidated(HasNameRegex("^PassManager")))
962       .InSequence(PISequence);
963 
964   // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
965   EXPECT_CALL(CallbacksHandle,
966               runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
967       .Times(0);
968 
969   StringRef PipelineText = "test-transform";
970   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
971       << "Pipeline was: " << PipelineText;
972   PM.run(*M, AM);
973 }
974 
975 TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
976   CallbacksHandle.registerPassInstrumentation();
977   // Non-mock instrumentation run here can safely be ignored.
978   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
979   CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
980   CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
981 
982   // Skip the pass by returning false.
983   EXPECT_CALL(CallbacksHandle,
984               runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
985       .WillOnce(Return(false));
986 
987   // neither Analysis nor Pass are called.
988   EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0);
989   EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0);
990 
991   // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
992   // as well.
993   EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
994       .Times(0);
995   EXPECT_CALL(CallbacksHandle,
996               runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
997       .Times(0);
998   EXPECT_CALL(CallbacksHandle,
999               runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1000       .Times(0);
1001   EXPECT_CALL(CallbacksHandle,
1002               runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1003       .Times(0);
1004 
1005   StringRef PipelineText = "test-transform";
1006   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1007       << "Pipeline was: " << PipelineText;
1008   PM.run(*M, AM);
1009 }
1010 
1011 /// Test parsing of the names of analysis utilities for our mock analysis
1012 /// for all IRUnits.
1013 ///
1014 /// We first require<>, then invalidate<> it, expecting the analysis to be run
1015 /// once and subsequently invalidated.
1016 TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
1017   EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
1018   EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
1019 
1020   StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1021   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1022       << "Pipeline was: " << PipelineText;
1023   PM.run(*M, AM);
1024 }
1025 
1026 TEST_F(CGSCCCallbacksTest, PassUtilities) {
1027   EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1028   EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
1029 
1030   StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1031   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1032       << "Pipeline was: " << PipelineText;
1033   PM.run(*M, AM);
1034 }
1035 
1036 TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
1037   EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
1038   EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
1039 
1040   StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1041   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1042       << "Pipeline was: " << PipelineText;
1043   PM.run(*M, AM);
1044 }
1045 
1046 TEST_F(LoopCallbacksTest, PassUtilities) {
1047   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
1048   EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
1049 
1050   StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1051 
1052   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1053       << "Pipeline was: " << PipelineText;
1054   PM.run(*M, AM);
1055 }
1056 
1057 /// Test parsing of the top-level pipeline.
1058 ///
1059 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
1060 /// from PassBuilder if it encounters an unknown pipeline entry at the top level
1061 /// (i.e., the first entry on the pipeline).
1062 /// This test parses a pipeline named 'another-pipeline', whose only elements
1063 /// may be the test-transform pass or the analysis utilities
1064 TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
1065   PB.registerParseTopLevelPipelineCallback([this](
1066       ModulePassManager &MPM, ArrayRef<PassBuilder::PipelineElement> Pipeline,
1067       bool VerifyEachPass, bool DebugLogging) {
1068     auto &FirstName = Pipeline.front().Name;
1069     auto &InnerPipeline = Pipeline.front().InnerPipeline;
1070     if (FirstName == "another-pipeline") {
1071       for (auto &E : InnerPipeline) {
1072         if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", E.Name, PM))
1073           continue;
1074 
1075         if (E.Name == "test-transform") {
1076           PM.addPass(PassHandle.getPass());
1077           continue;
1078         }
1079         return false;
1080       }
1081     }
1082     return true;
1083   });
1084 
1085   EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
1086   EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
1087       .WillOnce(Invoke(getAnalysisResult));
1088   EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
1089 
1090   StringRef PipelineText =
1091       "another-pipeline(test-transform,invalidate<test-analysis>)";
1092   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
1093       << "Pipeline was: " << PipelineText;
1094   PM.run(*M, AM);
1095 
1096   /// Test the negative case
1097   PipelineText = "another-pipeline(instcombine)";
1098   ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed())
1099       << "Pipeline was: " << PipelineText;
1100 }
1101 } // end anonymous namespace
1102