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