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