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