blob: 63fdc67b11524f53d97a3068e4102478a40ad1ed [file] [log] [blame]
Philip Pfaffe19045612017-07-10 10:57:55 +00001//===- 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
Fedor Sergeevff886492018-10-17 10:36:23 +000010#include "llvm/Testing/Support/Error.h"
Fedor Sergeeve6959a62018-09-20 17:08:45 +000011#include <functional>
Philip Pfaffe19045612017-07-10 10:57:55 +000012#include <gmock/gmock.h>
13#include <gtest/gtest.h>
Fedor Sergeeve6959a62018-09-20 17:08:45 +000014#include <llvm/ADT/Any.h>
Philip Pfaffe19045612017-07-10 10:57:55 +000015#include <llvm/Analysis/CGSCCPassManager.h>
16#include <llvm/Analysis/LoopAnalysisManager.h>
17#include <llvm/AsmParser/Parser.h>
18#include <llvm/IR/LLVMContext.h>
Fedor Sergeeve6959a62018-09-20 17:08:45 +000019#include <llvm/IR/PassInstrumentation.h>
Philip Pfaffe19045612017-07-10 10:57:55 +000020#include <llvm/IR/PassManager.h>
21#include <llvm/Passes/PassBuilder.h>
Fedor Sergeeve6959a62018-09-20 17:08:45 +000022#include <llvm/Support/Regex.h>
Philip Pfaffe19045612017-07-10 10:57:55 +000023#include <llvm/Support/SourceMgr.h>
24#include <llvm/Transforms/Scalar/LoopPassManager.h>
25
26using namespace llvm;
27
Philip Pfaffe19045612017-07-10 10:57:55 +000028namespace {
Fedor Sergeeve6959a62018-09-20 17:08:45 +000029using testing::AnyNumber;
30using testing::AtLeast;
Philip Pfaffe19045612017-07-10 10:57:55 +000031using testing::DoDefault;
Fedor Sergeeve6959a62018-09-20 17:08:45 +000032using testing::Not;
Philip Pfaffe19045612017-07-10 10:57:55 +000033using testing::Return;
34using testing::Expectation;
35using testing::Invoke;
36using testing::WithArgs;
37using testing::_;
38
Adrian Prantl26b584c2018-05-01 15:54:18 +000039/// A CRTP base for analysis mock handles
Philip Pfaffe19045612017-07-10 10:57:55 +000040///
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.
45template <typename DerivedT, typename IRUnitT,
46 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
47 typename... ExtraArgTs>
48class MockAnalysisHandleBase {
49public:
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 }
Fedor Sergeeve6959a62018-09-20 17:08:45 +000087 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
Philip Pfaffe19045612017-07-10 10:57:55 +000088
89protected:
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
Adrian Prantl26b584c2018-05-01 15:54:18 +0000111/// A CRTP base for pass mock handles
Philip Pfaffe19045612017-07-10 10:57:55 +0000112///
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.
117template <typename DerivedT, typename IRUnitT, typename AnalysisManagerT,
118 typename... ExtraArgTs>
119AnalysisKey MockAnalysisHandleBase<DerivedT, IRUnitT, AnalysisManagerT,
120 ExtraArgTs...>::Analysis::Key;
121
122template <typename DerivedT, typename IRUnitT,
123 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
124 typename... ExtraArgTs>
125class MockPassHandleBase {
126public:
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
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000144 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
145
Philip Pfaffe19045612017-07-10 10:57:55 +0000146 Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); }
147
148protected:
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.
162template <typename IRUnitT> struct MockPassHandle;
163template <>
164struct MockPassHandle<Loop>
165 : MockPassHandleBase<MockPassHandle<Loop>, Loop, LoopAnalysisManager,
166 LoopStandardAnalysisResults &, LPMUpdater &> {
167 MOCK_METHOD4(run,
168 PreservedAnalyses(Loop &, LoopAnalysisManager &,
169 LoopStandardAnalysisResults &, LPMUpdater &));
Fedor Sergeev601226c2018-12-11 19:05:35 +0000170 static void invalidateLoop(Loop &L, LoopAnalysisManager &,
171 LoopStandardAnalysisResults &,
172 LPMUpdater &Updater) {
173 Updater.markLoopAsDeleted(L, L.getName());
174 }
Philip Pfaffe19045612017-07-10 10:57:55 +0000175 MockPassHandle() { setDefaults(); }
176};
177
178template <>
179struct MockPassHandle<Function>
180 : MockPassHandleBase<MockPassHandle<Function>, Function> {
181 MOCK_METHOD2(run, PreservedAnalyses(Function &, FunctionAnalysisManager &));
182
183 MockPassHandle() { setDefaults(); }
184};
185
186template <>
187struct 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
Fedor Sergeev601226c2018-12-11 19:05:35 +0000195 static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
196 LazyCallGraph &, CGSCCUpdateResult &UR) {
197 UR.InvalidatedSCCs.insert(&C);
198 }
199
Philip Pfaffe19045612017-07-10 10:57:55 +0000200 MockPassHandle() { setDefaults(); }
201};
202
203template <>
204struct 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.
214template <typename IRUnitT> struct MockAnalysisHandle;
215template <>
216struct 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
230template <>
231struct 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
241template <>
242struct 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
255template <>
256struct 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
266static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
267 SMDiagnostic Err;
268 return parseAssemblyString(IR, Err, C);
269}
270
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000271/// Helper for HasName matcher that returns getName both for IRUnit and
272/// for IRUnit pointer wrapper into llvm::Any (wrapped by PassInstrumentation).
273template <typename IRUnitT> std::string getName(const IRUnitT &IR) {
274 return IR.getName();
275}
276
277template <> std::string getName(const StringRef &name) { return name; }
278
279template <> 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.
304MATCHER_P(HasName, Name, "") {
305 *result_listener << "has name '" << getName(arg) << "'";
306 return Name == getName(arg);
307}
308
309MATCHER_P(HasNameRegex, Name, "") {
310 *result_listener << "has name '" << getName(arg) << "'";
311 llvm::Regex r(Name);
312 return r.match(getName(arg));
313}
314
315struct 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));
Fedor Sergeev601226c2018-12-11 19:05:35 +0000323 MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID));
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000324 MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
325 MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000326
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); });
Fedor Sergeev601226c2018-12-11 19:05:35 +0000333 Callbacks.registerAfterPassInvalidatedCallback(
334 [this](StringRef P) { this->runAfterPassInvalidated(P); });
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000335 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); });
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000340 }
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());
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000353 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());
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000359 }
360};
361
Philip Pfaffe19045612017-07-10 10:57:55 +0000362template <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.
369template <typename TestIRUnitT, typename... ExtraPassArgTs,
370 typename... ExtraAnalysisArgTs>
371class PassBuilderCallbacksTest<PassManager<
372 TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>,
373 ExtraPassArgTs...>> : public testing::Test {
374protected:
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
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000384 MockPassInstrumentationCallbacks CallbacksHandle;
385
Philip Pfaffe19045612017-07-10 10:57:55 +0000386 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")),
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000418 CallbacksHandle(), PB(nullptr, None, &CallbacksHandle.Callbacks),
Philip Pfaffe19045612017-07-10 10:57:55 +0000419 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
Philip Pfaffe19045612017-07-10 10:57:55 +0000463using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
464using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
465using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
466using 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.
471TEST_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";
Fedor Sergeevff886492018-10-17 10:36:23 +0000477 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Philip Pfaffe19045612017-07-10 10:57:55 +0000478 << "Pipeline was: " << PipelineText;
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000479
480 PM.run(*M, AM);
481}
482
483TEST_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,
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000499 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,
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000507 runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
508 .InSequence(PISequence);
509
510 StringRef PipelineText = "test-transform";
Fedor Sergeevff886492018-10-17 10:36:23 +0000511 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000512 << "Pipeline was: " << PipelineText;
513
514 PM.run(*M, AM);
515}
516
517TEST_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
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000530 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
531 // as well.
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000532 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
533 .Times(0);
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000534 EXPECT_CALL(CallbacksHandle,
535 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
536 .Times(0);
537 EXPECT_CALL(CallbacksHandle,
538 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
539 .Times(0);
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000540
541 StringRef PipelineText = "test-transform";
Fedor Sergeevff886492018-10-17 10:36:23 +0000542 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000543 << "Pipeline was: " << PipelineText;
544
Philip Pfaffe19045612017-07-10 10:57:55 +0000545 PM.run(*M, AM);
546}
547
548TEST_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";
Fedor Sergeevff886492018-10-17 10:36:23 +0000554 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Philip Pfaffe19045612017-07-10 10:57:55 +0000555 << "Pipeline was: " << PipelineText;
556 PM.run(*M, AM);
557}
558
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000559TEST_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);
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000575 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);
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000583 EXPECT_CALL(CallbacksHandle,
584 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo")))
585 .InSequence(PISequence);
586
Fedor Sergeev601226c2018-12-11 19:05:35 +0000587 // Our mock pass does not invalidate IR.
588 EXPECT_CALL(CallbacksHandle,
589 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
590 .Times(0);
591
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000592 StringRef PipelineText = "test-transform";
Fedor Sergeevff886492018-10-17 10:36:23 +0000593 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000594 << "Pipeline was: " << PipelineText;
595 PM.run(*M, AM);
596}
597
598TEST_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
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000612 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
613 // as well.
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000614 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
615 .Times(0);
Fedor Sergeev601226c2018-12-11 19:05:35 +0000616 EXPECT_CALL(CallbacksHandle,
617 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
618 .Times(0);
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000619 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);
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000627
628 StringRef PipelineText = "test-transform";
Fedor Sergeevff886492018-10-17 10:36:23 +0000629 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000630 << "Pipeline was: " << PipelineText;
631 PM.run(*M, AM);
632}
633
Philip Pfaffe19045612017-07-10 10:57:55 +0000634TEST_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";
Fedor Sergeevff886492018-10-17 10:36:23 +0000640 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Philip Pfaffe19045612017-07-10 10:57:55 +0000641 << "Pipeline was: " << PipelineText;
642 PM.run(*M, AM);
643}
644
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000645TEST_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);
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000662 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);
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000670 EXPECT_CALL(CallbacksHandle,
671 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
672 .InSequence(PISequence);
673
Fedor Sergeev601226c2018-12-11 19:05:35 +0000674 // 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
685TEST_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
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000723 StringRef PipelineText = "test-transform";
Fedor Sergeevff886492018-10-17 10:36:23 +0000724 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000725 << "Pipeline was: " << PipelineText;
726 PM.run(*M, AM);
727}
728
729TEST_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
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000744 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
745 // as well.
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000746 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
747 .Times(0);
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000748 EXPECT_CALL(CallbacksHandle,
Fedor Sergeev601226c2018-12-11 19:05:35 +0000749 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
750 .Times(0);
751 EXPECT_CALL(CallbacksHandle,
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000752 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
753 .Times(0);
754 EXPECT_CALL(CallbacksHandle,
755 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
756 .Times(0);
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000757
758 StringRef PipelineText = "test-transform";
Fedor Sergeevff886492018-10-17 10:36:23 +0000759 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000760 << "Pipeline was: " << PipelineText;
761 PM.run(*M, AM);
762}
763
Philip Pfaffe19045612017-07-10 10:57:55 +0000764TEST_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";
Fedor Sergeevff886492018-10-17 10:36:23 +0000770 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Philip Pfaffe19045612017-07-10 10:57:55 +0000771 << "Pipeline was: " << PipelineText;
772 PM.run(*M, AM);
773}
774
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000775TEST_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);
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000791 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);
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000799 EXPECT_CALL(CallbacksHandle,
800 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
801 .InSequence(PISequence);
802
Fedor Sergeev601226c2018-12-11 19:05:35 +0000803 // 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
814TEST_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
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000851 StringRef PipelineText = "test-transform";
Fedor Sergeevff886492018-10-17 10:36:23 +0000852 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000853 << "Pipeline was: " << PipelineText;
854 PM.run(*M, AM);
855}
856
857TEST_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
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000872 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
873 // as well.
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000874 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
875 .Times(0);
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000876 EXPECT_CALL(CallbacksHandle,
Fedor Sergeev601226c2018-12-11 19:05:35 +0000877 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
878 .Times(0);
879 EXPECT_CALL(CallbacksHandle,
Fedor Sergeev8e283f92018-09-21 22:10:17 +0000880 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
881 .Times(0);
882 EXPECT_CALL(CallbacksHandle,
883 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
884 .Times(0);
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000885
886 StringRef PipelineText = "test-transform";
Fedor Sergeevff886492018-10-17 10:36:23 +0000887 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Fedor Sergeeve6959a62018-09-20 17:08:45 +0000888 << "Pipeline was: " << PipelineText;
889 PM.run(*M, AM);
890}
891
Philip Pfaffe19045612017-07-10 10:57:55 +0000892/// 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.
897TEST_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>";
Fedor Sergeevff886492018-10-17 10:36:23 +0000902 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Philip Pfaffe19045612017-07-10 10:57:55 +0000903 << "Pipeline was: " << PipelineText;
904 PM.run(*M, AM);
905}
906
907TEST_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>";
Fedor Sergeevff886492018-10-17 10:36:23 +0000912 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Philip Pfaffe19045612017-07-10 10:57:55 +0000913 << "Pipeline was: " << PipelineText;
914 PM.run(*M, AM);
915}
916
917TEST_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>";
Fedor Sergeevff886492018-10-17 10:36:23 +0000922 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Philip Pfaffe19045612017-07-10 10:57:55 +0000923 << "Pipeline was: " << PipelineText;
924 PM.run(*M, AM);
925}
926
927TEST_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
Fedor Sergeevff886492018-10-17 10:36:23 +0000933 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Philip Pfaffe19045612017-07-10 10:57:55 +0000934 << "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
945TEST_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>)";
Fedor Sergeevff886492018-10-17 10:36:23 +0000973 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
Philip Pfaffe19045612017-07-10 10:57:55 +0000974 << "Pipeline was: " << PipelineText;
975 PM.run(*M, AM);
976
977 /// Test the negative case
978 PipelineText = "another-pipeline(instcombine)";
Fedor Sergeevff886492018-10-17 10:36:23 +0000979 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed())
Philip Pfaffe19045612017-07-10 10:57:55 +0000980 << "Pipeline was: " << PipelineText;
981}
982} // end anonymous namespace