OSDN Git Service

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