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