[docs] Fix build-docs.sh
[llvm-project.git] / llvm / unittests / IR / PassBuilderCallbacksTest.cpp
blob7785c975645370ace9fa3c775ccb6035562dda46
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 //===----------------------------------------------------------------------===//
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>
25 using namespace llvm;
27 namespace {
28 using testing::AnyNumber;
29 using testing::DoAll;
30 using testing::Not;
31 using testing::Return;
32 using testing::WithArgs;
33 using testing::_;
35 /// A CRTP base for analysis mock handles
36 ///
37 /// This class reconciles mocking with the value semantics implementation of the
38 /// AnalysisManager. Analysis mock handles should derive from this class and
39 /// call \c setDefault() in their constroctur for wiring up the defaults defined
40 /// by this base with their mock run() and invalidate() implementations.
41 template <typename DerivedT, typename IRUnitT,
42 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
43 typename... ExtraArgTs>
44 class MockAnalysisHandleBase {
45 public:
46 class Analysis : public AnalysisInfoMixin<Analysis> {
47 friend AnalysisInfoMixin<Analysis>;
48 friend MockAnalysisHandleBase;
49 static AnalysisKey Key;
51 DerivedT *Handle;
53 Analysis(DerivedT &Handle) : Handle(&Handle) {
54 static_assert(std::is_base_of<MockAnalysisHandleBase, DerivedT>::value,
55 "Must pass the derived type to this template!");
58 public:
59 class Result {
60 friend MockAnalysisHandleBase;
62 DerivedT *Handle;
64 Result(DerivedT &Handle) : Handle(&Handle) {}
66 public:
67 // Forward invalidation events to the mock handle.
68 bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
69 typename AnalysisManagerT::Invalidator &Inv) {
70 return Handle->invalidate(IR, PA, Inv);
74 Result run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) {
75 return Handle->run(IR, AM, ExtraArgs...);
79 Analysis getAnalysis() { return Analysis(static_cast<DerivedT &>(*this)); }
80 typename Analysis::Result getResult() {
81 return typename Analysis::Result(static_cast<DerivedT &>(*this));
83 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
85 protected:
86 // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within
87 // the template, so we use a boring static function.
88 static bool invalidateCallback(IRUnitT &IR, const PreservedAnalyses &PA,
89 typename AnalysisManagerT::Invalidator &Inv) {
90 auto PAC = PA.template getChecker<Analysis>();
91 return !PAC.preserved() &&
92 !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
95 /// Derived classes should call this in their constructor to set up default
96 /// mock actions. (We can't do this in our constructor because this has to
97 /// run after the DerivedT is constructed.)
98 void setDefaults() {
99 ON_CALL(static_cast<DerivedT &>(*this),
100 run(_, _, testing::Matcher<ExtraArgTs>(_)...))
101 .WillByDefault(Return(this->getResult()));
102 ON_CALL(static_cast<DerivedT &>(*this), invalidate(_, _, _))
103 .WillByDefault(&invalidateCallback);
107 /// A CRTP base for pass mock handles
109 /// This class reconciles mocking with the value semantics implementation of the
110 /// PassManager. Pass mock handles should derive from this class and
111 /// call \c setDefault() in their constroctur for wiring up the defaults defined
112 /// by this base with their mock run() and invalidate() implementations.
113 template <typename DerivedT, typename IRUnitT, typename AnalysisManagerT,
114 typename... ExtraArgTs>
115 AnalysisKey MockAnalysisHandleBase<DerivedT, IRUnitT, AnalysisManagerT,
116 ExtraArgTs...>::Analysis::Key;
118 template <typename DerivedT, typename IRUnitT,
119 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
120 typename... ExtraArgTs>
121 class MockPassHandleBase {
122 public:
123 class Pass : public PassInfoMixin<Pass> {
124 friend MockPassHandleBase;
126 DerivedT *Handle;
128 Pass(DerivedT &Handle) : Handle(&Handle) {
129 static_assert(std::is_base_of<MockPassHandleBase, DerivedT>::value,
130 "Must pass the derived type to this template!");
133 public:
134 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
135 ExtraArgTs... ExtraArgs) {
136 return Handle->run(IR, AM, ExtraArgs...);
140 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
142 Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); }
144 protected:
145 /// Derived classes should call this in their constructor to set up default
146 /// mock actions. (We can't do this in our constructor because this has to
147 /// run after the DerivedT is constructed.)
148 void setDefaults() {
149 ON_CALL(static_cast<DerivedT &>(*this),
150 run(_, _, testing::Matcher<ExtraArgTs>(_)...))
151 .WillByDefault(Return(PreservedAnalyses::all()));
155 /// Mock handles for passes for the IRUnits Module, CGSCC, Function, Loop.
156 /// These handles define the appropriate run() mock interface for the respective
157 /// IRUnit type.
158 template <typename IRUnitT> struct MockPassHandle;
159 template <>
160 struct MockPassHandle<Loop>
161 : MockPassHandleBase<MockPassHandle<Loop>, Loop, LoopAnalysisManager,
162 LoopStandardAnalysisResults &, LPMUpdater &> {
163 MOCK_METHOD4(run,
164 PreservedAnalyses(Loop &, LoopAnalysisManager &,
165 LoopStandardAnalysisResults &, LPMUpdater &));
166 static void invalidateLoop(Loop &L, LoopAnalysisManager &,
167 LoopStandardAnalysisResults &,
168 LPMUpdater &Updater) {
169 Updater.markLoopAsDeleted(L, L.getName());
171 MockPassHandle() { setDefaults(); }
174 template <>
175 struct MockPassHandle<LoopNest>
176 : MockPassHandleBase<MockPassHandle<LoopNest>, LoopNest,
177 LoopAnalysisManager, LoopStandardAnalysisResults &,
178 LPMUpdater &> {
179 MOCK_METHOD4(run,
180 PreservedAnalyses(LoopNest &, LoopAnalysisManager &,
181 LoopStandardAnalysisResults &, LPMUpdater &));
182 static void invalidateLoopNest(LoopNest &L, LoopAnalysisManager &,
183 LoopStandardAnalysisResults &,
184 LPMUpdater &Updater) {
185 Updater.markLoopAsDeleted(L.getOutermostLoop(), L.getName());
187 MockPassHandle() { setDefaults(); }
190 template <>
191 struct MockPassHandle<Function>
192 : MockPassHandleBase<MockPassHandle<Function>, Function> {
193 MOCK_METHOD2(run, PreservedAnalyses(Function &, FunctionAnalysisManager &));
195 MockPassHandle() { setDefaults(); }
198 template <>
199 struct MockPassHandle<LazyCallGraph::SCC>
200 : MockPassHandleBase<MockPassHandle<LazyCallGraph::SCC>, LazyCallGraph::SCC,
201 CGSCCAnalysisManager, LazyCallGraph &,
202 CGSCCUpdateResult &> {
203 MOCK_METHOD4(run,
204 PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
205 LazyCallGraph &G, CGSCCUpdateResult &UR));
207 static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
208 LazyCallGraph &, CGSCCUpdateResult &UR) {
209 UR.InvalidatedSCCs.insert(&C);
212 MockPassHandle() { setDefaults(); }
215 template <>
216 struct MockPassHandle<Module>
217 : MockPassHandleBase<MockPassHandle<Module>, Module> {
218 MOCK_METHOD2(run, PreservedAnalyses(Module &, ModuleAnalysisManager &));
220 MockPassHandle() { setDefaults(); }
223 /// Mock handles for analyses for the IRUnits Module, CGSCC, Function, Loop.
224 /// These handles define the appropriate run() and invalidate() mock interfaces
225 /// for the respective IRUnit type.
226 template <typename IRUnitT> struct MockAnalysisHandle;
227 template <>
228 struct MockAnalysisHandle<Loop>
229 : MockAnalysisHandleBase<MockAnalysisHandle<Loop>, Loop,
230 LoopAnalysisManager,
231 LoopStandardAnalysisResults &> {
233 MOCK_METHOD3_T(run, typename Analysis::Result(Loop &, LoopAnalysisManager &,
234 LoopStandardAnalysisResults &));
236 MOCK_METHOD3_T(invalidate, bool(Loop &, const PreservedAnalyses &,
237 LoopAnalysisManager::Invalidator &));
239 MockAnalysisHandle<Loop>() { this->setDefaults(); }
242 template <>
243 struct MockAnalysisHandle<Function>
244 : MockAnalysisHandleBase<MockAnalysisHandle<Function>, Function> {
245 MOCK_METHOD2(run, Analysis::Result(Function &, FunctionAnalysisManager &));
247 MOCK_METHOD3(invalidate, bool(Function &, const PreservedAnalyses &,
248 FunctionAnalysisManager::Invalidator &));
250 MockAnalysisHandle<Function>() { setDefaults(); }
253 template <>
254 struct MockAnalysisHandle<LazyCallGraph::SCC>
255 : MockAnalysisHandleBase<MockAnalysisHandle<LazyCallGraph::SCC>,
256 LazyCallGraph::SCC, CGSCCAnalysisManager,
257 LazyCallGraph &> {
258 MOCK_METHOD3(run, Analysis::Result(LazyCallGraph::SCC &,
259 CGSCCAnalysisManager &, LazyCallGraph &));
261 MOCK_METHOD3(invalidate, bool(LazyCallGraph::SCC &, const PreservedAnalyses &,
262 CGSCCAnalysisManager::Invalidator &));
264 MockAnalysisHandle<LazyCallGraph::SCC>() { setDefaults(); }
267 template <>
268 struct MockAnalysisHandle<Module>
269 : MockAnalysisHandleBase<MockAnalysisHandle<Module>, Module> {
270 MOCK_METHOD2(run, Analysis::Result(Module &, ModuleAnalysisManager &));
272 MOCK_METHOD3(invalidate, bool(Module &, const PreservedAnalyses &,
273 ModuleAnalysisManager::Invalidator &));
275 MockAnalysisHandle<Module>() { setDefaults(); }
278 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
279 SMDiagnostic Err;
280 return parseAssemblyString(IR, Err, C);
283 /// Helper for HasName matcher that returns getName both for IRUnit and
284 /// for IRUnit pointer wrapper into llvm::Any (wrapped by PassInstrumentation).
285 template <typename IRUnitT> std::string getName(const IRUnitT &IR) {
286 return std::string(IR.getName());
289 template <> std::string getName(const StringRef &name) {
290 return std::string(name);
293 template <> std::string getName(const llvm::Any &WrappedIR) {
294 if (any_isa<const Module *>(WrappedIR))
295 return any_cast<const Module *>(WrappedIR)->getName().str();
296 if (any_isa<const Function *>(WrappedIR))
297 return any_cast<const Function *>(WrappedIR)->getName().str();
298 if (any_isa<const Loop *>(WrappedIR))
299 return any_cast<const Loop *>(WrappedIR)->getName().str();
300 if (any_isa<const LoopNest *>(WrappedIR))
301 return any_cast<const LoopNest *>(WrappedIR)->getName().str();
302 if (any_isa<const LazyCallGraph::SCC *>(WrappedIR))
303 return any_cast<const LazyCallGraph::SCC *>(WrappedIR)->getName();
304 return "<UNKNOWN>";
306 /// Define a custom matcher for objects which support a 'getName' method.
308 /// LLVM often has IR objects or analysis objects which expose a name
309 /// and in tests it is convenient to match these by name for readability.
310 /// Usually, this name is either a StringRef or a plain std::string. This
311 /// matcher supports any type exposing a getName() method of this form whose
312 /// return value is compatible with an std::ostream. For StringRef, this uses
313 /// the shift operator defined above.
315 /// It should be used as:
317 /// HasName("my_function")
319 /// No namespace or other qualification is required.
320 MATCHER_P(HasName, Name, "") {
321 *result_listener << "has name '" << getName(arg) << "'";
322 return Name == getName(arg);
325 MATCHER_P(HasNameRegex, Name, "") {
326 *result_listener << "has name '" << getName(arg) << "'";
327 llvm::Regex r(Name);
328 return r.match(getName(arg));
331 struct MockPassInstrumentationCallbacks {
332 PassInstrumentationCallbacks Callbacks;
334 MockPassInstrumentationCallbacks() {
335 ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true));
337 MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
338 MOCK_METHOD2(runBeforeSkippedPass, void(StringRef PassID, llvm::Any));
339 MOCK_METHOD2(runBeforeNonSkippedPass, void(StringRef PassID, llvm::Any));
340 MOCK_METHOD3(runAfterPass,
341 void(StringRef PassID, llvm::Any, const PreservedAnalyses &PA));
342 MOCK_METHOD2(runAfterPassInvalidated,
343 void(StringRef PassID, const PreservedAnalyses &PA));
344 MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
345 MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
347 void registerPassInstrumentation() {
348 Callbacks.registerShouldRunOptionalPassCallback(
349 [this](StringRef P, llvm::Any IR) {
350 return this->runBeforePass(P, IR);
352 Callbacks.registerBeforeSkippedPassCallback(
353 [this](StringRef P, llvm::Any IR) {
354 this->runBeforeSkippedPass(P, IR);
356 Callbacks.registerBeforeNonSkippedPassCallback(
357 [this](StringRef P, llvm::Any IR) {
358 this->runBeforeNonSkippedPass(P, IR);
360 Callbacks.registerAfterPassCallback(
361 [this](StringRef P, llvm::Any IR, const PreservedAnalyses &PA) {
362 this->runAfterPass(P, IR, PA);
364 Callbacks.registerAfterPassInvalidatedCallback(
365 [this](StringRef P, const PreservedAnalyses &PA) {
366 this->runAfterPassInvalidated(P, PA);
368 Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
369 return this->runBeforeAnalysis(P, IR);
371 Callbacks.registerAfterAnalysisCallback(
372 [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); });
375 void ignoreNonMockPassInstrumentation(StringRef IRName) {
376 // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
377 // parts of a pipeline that we do not care about (e.g. various passes added
378 // by default by PassBuilder - Verifier pass etc).
379 // Make sure to avoid ignoring Mock passes/analysis, we definitely want
380 // to check these explicitly.
381 EXPECT_CALL(*this,
382 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
383 .Times(AnyNumber());
384 EXPECT_CALL(
385 *this, runBeforeSkippedPass(Not(HasNameRegex("Mock")), HasName(IRName)))
386 .Times(AnyNumber());
387 EXPECT_CALL(*this, runBeforeNonSkippedPass(Not(HasNameRegex("Mock")),
388 HasName(IRName)))
389 .Times(AnyNumber());
390 EXPECT_CALL(*this,
391 runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName), _))
392 .Times(AnyNumber());
393 EXPECT_CALL(*this,
394 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
395 .Times(AnyNumber());
396 EXPECT_CALL(*this,
397 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
398 .Times(AnyNumber());
402 template <typename IRUnitT>
403 using ExtraMockPassHandle =
404 std::conditional_t<std::is_same<IRUnitT, Loop>::value,
405 MockPassHandle<LoopNest>, MockPassHandle<IRUnitT>>;
407 template <typename PassManagerT> class PassBuilderCallbacksTest;
409 /// This test fixture is shared between all the actual tests below and
410 /// takes care of setting up appropriate defaults.
412 /// The template specialization serves to extract the IRUnit and AM types from
413 /// the given PassManagerT.
414 template <typename TestIRUnitT, typename... ExtraPassArgTs,
415 typename... ExtraAnalysisArgTs>
416 class PassBuilderCallbacksTest<PassManager<
417 TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>,
418 ExtraPassArgTs...>> : public testing::Test {
419 protected:
420 using IRUnitT = TestIRUnitT;
421 using AnalysisManagerT = AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>;
422 using PassManagerT =
423 PassManager<TestIRUnitT, AnalysisManagerT, ExtraPassArgTs...>;
424 using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis;
426 LLVMContext Context;
427 std::unique_ptr<Module> M;
429 MockPassInstrumentationCallbacks CallbacksHandle;
431 PassBuilder PB;
432 ModulePassManager PM;
433 LoopAnalysisManager LAM;
434 FunctionAnalysisManager FAM;
435 CGSCCAnalysisManager CGAM;
436 ModuleAnalysisManager AM;
438 MockPassHandle<IRUnitT> PassHandle;
439 ExtraMockPassHandle<IRUnitT> ExtraPassHandle;
441 MockAnalysisHandle<IRUnitT> AnalysisHandle;
443 static PreservedAnalyses getAnalysisResult(IRUnitT &U, AnalysisManagerT &AM,
444 ExtraAnalysisArgTs &&... Args) {
445 (void)AM.template getResult<AnalysisT>(
446 U, std::forward<ExtraAnalysisArgTs>(Args)...);
447 return PreservedAnalyses::all();
450 PassBuilderCallbacksTest()
451 : M(parseIR(Context,
452 "declare void @bar()\n"
453 "define void @foo(i32 %n) {\n"
454 "entry:\n"
455 " br label %loop\n"
456 "loop:\n"
457 " %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
458 " %iv.next = add i32 %iv, 1\n"
459 " tail call void @bar()\n"
460 " %cmp = icmp eq i32 %iv, %n\n"
461 " br i1 %cmp, label %exit, label %loop\n"
462 "exit:\n"
463 " ret void\n"
464 "}\n")),
465 CallbacksHandle(),
466 PB(nullptr, PipelineTuningOptions(), None, &CallbacksHandle.Callbacks),
467 PM(), LAM(), FAM(), CGAM(), AM() {
469 EXPECT_TRUE(&CallbacksHandle.Callbacks ==
470 PB.getPassInstrumentationCallbacks());
472 /// Register a callback for analysis registration.
474 /// The callback is a function taking a reference to an AnalyisManager
475 /// object. When called, the callee gets to register its own analyses with
476 /// this PassBuilder instance.
477 PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) {
478 // Register our mock analysis
479 AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
482 /// Register a callback for pipeline parsing.
484 /// During parsing of a textual pipeline, the PassBuilder will call these
485 /// callbacks for each encountered pass name that it does not know. This
486 /// includes both simple pass names as well as names of sub-pipelines. In
487 /// the latter case, the InnerPipeline is not empty.
488 PB.registerPipelineParsingCallback(
489 [this](StringRef Name, PassManagerT &PM,
490 ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
491 /// Handle parsing of the names of analysis utilities such as
492 /// require<test-analysis> and invalidate<test-analysis> for our
493 /// analysis mock handle
494 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", Name, PM))
495 return true;
497 /// Parse the name of our pass mock handle
498 if (Name == "test-transform") {
499 PM.addPass(PassHandle.getPass());
500 if (std::is_same<IRUnitT, Loop>::value)
501 PM.addPass(ExtraPassHandle.getPass());
502 return true;
504 return false;
507 /// Register builtin analyses and cross-register the analysis proxies
508 PB.registerModuleAnalyses(AM);
509 PB.registerCGSCCAnalyses(CGAM);
510 PB.registerFunctionAnalyses(FAM);
511 PB.registerLoopAnalyses(LAM);
512 PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
516 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
517 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
518 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
519 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
521 /// Test parsing of the name of our mock pass for all IRUnits.
523 /// The pass should by default run our mock analysis and then preserve it.
524 TEST_F(ModuleCallbacksTest, Passes) {
525 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
526 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
527 .WillOnce(&getAnalysisResult);
529 StringRef PipelineText = "test-transform";
530 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
531 << "Pipeline was: " << PipelineText;
533 PM.run(*M, AM);
536 TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
537 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
538 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
539 .WillOnce(&getAnalysisResult);
541 CallbacksHandle.registerPassInstrumentation();
542 // Non-mock instrumentation not specifically mentioned below can be ignored.
543 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
545 // PassInstrumentation calls should happen in-sequence, in the same order
546 // as passes/analyses are scheduled.
547 ::testing::Sequence PISequence;
548 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
549 HasName("<string>")))
550 .InSequence(PISequence);
551 EXPECT_CALL(CallbacksHandle,
552 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"),
553 HasName("<string>")))
554 .InSequence(PISequence);
555 EXPECT_CALL(CallbacksHandle,
556 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
557 HasName("<string>")))
558 .InSequence(PISequence);
559 EXPECT_CALL(
560 CallbacksHandle,
561 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
562 .InSequence(PISequence);
563 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"),
564 HasName("<string>"), _))
565 .InSequence(PISequence);
567 // No passes are skipped, so there should be no calls to
568 // runBeforeSkippedPass().
569 EXPECT_CALL(
570 CallbacksHandle,
571 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
572 .Times(0);
574 StringRef PipelineText = "test-transform";
575 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
576 << "Pipeline was: " << PipelineText;
578 PM.run(*M, AM);
581 TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
582 CallbacksHandle.registerPassInstrumentation();
583 // Non-mock instrumentation run here can safely be ignored.
584 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
585 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
587 // Skip all passes by returning false. Pass managers and adaptor passes are
588 // also passes that observed by the callbacks.
589 EXPECT_CALL(CallbacksHandle, runBeforePass(_, _))
590 .WillRepeatedly(Return(false));
592 EXPECT_CALL(CallbacksHandle,
593 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), _))
594 .Times(3);
596 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
597 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0);
599 // As the pass is skipped there is no nonskippedpass/afterPass,
600 // beforeAnalysis/afterAnalysis as well.
601 EXPECT_CALL(CallbacksHandle,
602 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
603 .Times(0);
604 EXPECT_CALL(CallbacksHandle,
605 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
606 .Times(0);
607 EXPECT_CALL(CallbacksHandle,
608 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
609 .Times(0);
610 EXPECT_CALL(CallbacksHandle,
611 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
612 .Times(0);
614 // Order is important here. `Adaptor` expectations should be checked first
615 // because the its argument contains 'PassManager' (for example:
616 // ModuleToFunctionPassAdaptor{{.*}}PassManager{{.*}}). Check
617 // `runBeforeNonSkippedPass` and `runAfterPass` to show that they are not
618 // skipped.
620 // Pass managers are not ignored.
621 // 5 = (1) ModulePassManager + (2) FunctionPassMangers + (1) LoopPassManager +
622 // (1) CGSCCPassManager
623 EXPECT_CALL(CallbacksHandle,
624 runBeforeNonSkippedPass(HasNameRegex("PassManager"), _))
625 .Times(5);
626 EXPECT_CALL(
627 CallbacksHandle,
628 runBeforeNonSkippedPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _))
629 .Times(1);
630 EXPECT_CALL(CallbacksHandle,
631 runBeforeNonSkippedPass(
632 HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _))
633 .Times(1);
634 EXPECT_CALL(
635 CallbacksHandle,
636 runBeforeNonSkippedPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _))
637 .Times(1);
638 EXPECT_CALL(
639 CallbacksHandle,
640 runBeforeNonSkippedPass(HasNameRegex("FunctionToLoopPassAdaptor"), _))
641 .Times(1);
643 // The `runAfterPass` checks are the same as these of
644 // `runBeforeNonSkippedPass`.
645 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("PassManager"), _, _))
646 .Times(5);
647 EXPECT_CALL(CallbacksHandle,
648 runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _, _))
649 .Times(1);
650 EXPECT_CALL(
651 CallbacksHandle,
652 runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _, _))
653 .Times(1);
654 EXPECT_CALL(CallbacksHandle,
655 runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _, _))
656 .Times(1);
657 EXPECT_CALL(CallbacksHandle,
658 runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _, _))
659 .Times(1);
661 // Ignore analyses introduced by adaptor passes.
662 EXPECT_CALL(CallbacksHandle,
663 runBeforeAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _))
664 .Times(AnyNumber());
665 EXPECT_CALL(CallbacksHandle,
666 runAfterAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _))
667 .Times(AnyNumber());
669 // Register Funtion and Loop version of "test-transform" for testing
670 PB.registerPipelineParsingCallback(
671 [](StringRef Name, FunctionPassManager &FPM,
672 ArrayRef<PassBuilder::PipelineElement>) {
673 if (Name == "test-transform") {
674 FPM.addPass(MockPassHandle<Function>().getPass());
675 return true;
677 return false;
679 PB.registerPipelineParsingCallback(
680 [](StringRef Name, LoopPassManager &LPM,
681 ArrayRef<PassBuilder::PipelineElement>) {
682 if (Name == "test-transform") {
683 LPM.addPass(MockPassHandle<Loop>().getPass());
684 return true;
686 return false;
689 StringRef PipelineText = "test-transform,function(test-transform),cgscc("
690 "function(loop(test-transform)))";
691 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
692 << "Pipeline was: " << PipelineText;
694 PM.run(*M, AM);
697 TEST_F(FunctionCallbacksTest, Passes) {
698 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
699 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).WillOnce(&getAnalysisResult);
701 StringRef PipelineText = "test-transform";
702 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
703 << "Pipeline was: " << PipelineText;
704 PM.run(*M, AM);
707 TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
708 CallbacksHandle.registerPassInstrumentation();
709 // Non-mock instrumentation not specifically mentioned below can be ignored.
710 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
711 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
713 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
714 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).WillOnce(&getAnalysisResult);
716 // PassInstrumentation calls should happen in-sequence, in the same order
717 // as passes/analyses are scheduled.
718 ::testing::Sequence PISequence;
719 EXPECT_CALL(CallbacksHandle,
720 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
721 .InSequence(PISequence);
722 EXPECT_CALL(
723 CallbacksHandle,
724 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
725 .InSequence(PISequence);
726 EXPECT_CALL(
727 CallbacksHandle,
728 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
729 .InSequence(PISequence);
730 EXPECT_CALL(
731 CallbacksHandle,
732 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
733 .InSequence(PISequence);
734 EXPECT_CALL(CallbacksHandle,
735 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo"), _))
736 .InSequence(PISequence);
738 // No passes are skipped, so there should be no calls to
739 // runBeforeSkippedPass().
740 EXPECT_CALL(
741 CallbacksHandle,
742 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
743 .Times(0);
745 // Our mock pass does not invalidate IR.
746 EXPECT_CALL(CallbacksHandle,
747 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
748 .Times(0);
750 StringRef PipelineText = "test-transform";
751 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
752 << "Pipeline was: " << PipelineText;
753 PM.run(*M, AM);
756 TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
757 CallbacksHandle.registerPassInstrumentation();
758 // Non-mock instrumentation run here can safely be ignored.
759 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
760 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
762 // Skip the pass by returning false.
763 EXPECT_CALL(CallbacksHandle,
764 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
765 .WillOnce(Return(false));
767 EXPECT_CALL(
768 CallbacksHandle,
769 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
770 .Times(1);
772 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
773 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0);
775 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
776 // as well.
777 EXPECT_CALL(CallbacksHandle,
778 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
779 .Times(0);
780 EXPECT_CALL(CallbacksHandle,
781 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
782 .Times(0);
783 EXPECT_CALL(CallbacksHandle,
784 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
785 .Times(0);
786 EXPECT_CALL(CallbacksHandle,
787 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
788 .Times(0);
789 EXPECT_CALL(CallbacksHandle,
790 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
791 .Times(0);
792 EXPECT_CALL(CallbacksHandle,
793 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
794 .Times(0);
796 StringRef PipelineText = "test-transform";
797 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
798 << "Pipeline was: " << PipelineText;
799 PM.run(*M, AM);
802 TEST_F(LoopCallbacksTest, Passes) {
803 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
804 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
805 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
806 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _));
808 StringRef PipelineText = "test-transform";
809 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
810 << "Pipeline was: " << PipelineText;
811 PM.run(*M, AM);
814 TEST_F(LoopCallbacksTest, InstrumentedPasses) {
815 CallbacksHandle.registerPassInstrumentation();
816 // Non-mock instrumentation not specifically mentioned below can be ignored.
817 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
818 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
819 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
821 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
822 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
823 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
824 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _));
826 // PassInstrumentation calls should happen in-sequence, in the same order
827 // as passes/analyses are scheduled.
828 ::testing::Sequence PISequence;
829 EXPECT_CALL(CallbacksHandle,
830 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
831 .InSequence(PISequence);
832 EXPECT_CALL(
833 CallbacksHandle,
834 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
835 .InSequence(PISequence);
836 EXPECT_CALL(
837 CallbacksHandle,
838 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
839 .InSequence(PISequence);
840 EXPECT_CALL(
841 CallbacksHandle,
842 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
843 .InSequence(PISequence);
844 EXPECT_CALL(CallbacksHandle,
845 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _))
846 .InSequence(PISequence);
848 EXPECT_CALL(CallbacksHandle,
849 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
850 HasName("loop")))
851 .InSequence(PISequence);
852 EXPECT_CALL(CallbacksHandle,
853 runBeforeNonSkippedPass(
854 HasNameRegex("MockPassHandle<.*LoopNest>"), HasName("loop")))
855 .InSequence(PISequence);
856 EXPECT_CALL(CallbacksHandle,
857 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
858 HasName("loop"), _))
859 .InSequence(PISequence);
861 // Our mock pass does not invalidate IR.
862 EXPECT_CALL(CallbacksHandle,
863 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
864 .Times(0);
866 // No passes are skipped, so there should be no calls to
867 // runBeforeSkippedPass().
868 EXPECT_CALL(
869 CallbacksHandle,
870 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
871 .Times(0);
873 StringRef PipelineText = "test-transform";
874 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
875 << "Pipeline was: " << PipelineText;
876 PM.run(*M, AM);
879 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
880 CallbacksHandle.registerPassInstrumentation();
881 // Non-mock instrumentation not specifically mentioned below can be ignored.
882 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
883 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
884 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
886 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
887 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
888 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(&PassHandle.invalidateLoop),
889 WithArgs<0, 1, 2>(&getAnalysisResult)));
891 // PassInstrumentation calls should happen in-sequence, in the same order
892 // as passes/analyses are scheduled.
893 ::testing::Sequence PISequence;
894 EXPECT_CALL(CallbacksHandle,
895 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
896 .InSequence(PISequence);
897 EXPECT_CALL(
898 CallbacksHandle,
899 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
900 .InSequence(PISequence);
901 EXPECT_CALL(
902 CallbacksHandle,
903 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
904 .InSequence(PISequence);
905 EXPECT_CALL(
906 CallbacksHandle,
907 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
908 .InSequence(PISequence);
909 EXPECT_CALL(CallbacksHandle,
910 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
911 .InSequence(PISequence);
912 EXPECT_CALL(CallbacksHandle,
913 runAfterPassInvalidated(HasNameRegex("^PassManager"), _))
914 .InSequence(PISequence);
916 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
917 EXPECT_CALL(CallbacksHandle,
918 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _))
919 .Times(0);
921 StringRef PipelineText = "test-transform";
922 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
923 << "Pipeline was: " << PipelineText;
924 PM.run(*M, AM);
927 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingLoopNestPasses) {
928 CallbacksHandle.registerPassInstrumentation();
929 // Non-mock instrumentation not specifically mentioned below can be ignored.
930 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
931 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
932 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
934 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
935 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
936 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
937 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _))
938 .WillOnce(DoAll(&ExtraPassHandle.invalidateLoopNest,
939 [&](LoopNest &, LoopAnalysisManager &,
940 LoopStandardAnalysisResults &,
941 LPMUpdater &) { return PreservedAnalyses::all(); }));
943 // PassInstrumentation calls should happen in-sequence, in the same order
944 // as passes/analyses are scheduled.
945 ::testing::Sequence PISequence;
946 EXPECT_CALL(CallbacksHandle,
947 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
948 .InSequence(PISequence);
949 EXPECT_CALL(
950 CallbacksHandle,
951 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
952 .InSequence(PISequence);
953 EXPECT_CALL(
954 CallbacksHandle,
955 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
956 .InSequence(PISequence);
957 EXPECT_CALL(
958 CallbacksHandle,
959 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
960 .InSequence(PISequence);
961 EXPECT_CALL(CallbacksHandle,
962 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _))
963 .InSequence(PISequence);
965 EXPECT_CALL(CallbacksHandle,
966 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
967 HasName("loop")))
968 .InSequence(PISequence);
969 EXPECT_CALL(CallbacksHandle,
970 runBeforeNonSkippedPass(
971 HasNameRegex("MockPassHandle<.*LoopNest>"), HasName("loop")))
972 .InSequence(PISequence);
973 EXPECT_CALL(
974 CallbacksHandle,
975 runAfterPassInvalidated(HasNameRegex("MockPassHandle<.*LoopNest>"), _))
976 .InSequence(PISequence);
978 EXPECT_CALL(CallbacksHandle,
979 runAfterPassInvalidated(HasNameRegex("^PassManager"), _))
980 .InSequence(PISequence);
982 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
983 EXPECT_CALL(CallbacksHandle, runAfterPassInvalidated(
984 HasNameRegex("MockPassHandle<.*Loop>"), _))
985 .Times(0);
986 EXPECT_CALL(CallbacksHandle,
987 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
988 HasName("loop"), _))
989 .Times(0);
991 StringRef PipelineText = "test-transform";
992 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
993 << "Pipeline was: " << PipelineText;
994 PM.run(*M, AM);
997 TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
998 CallbacksHandle.registerPassInstrumentation();
999 // Non-mock instrumentation run here can safely be ignored.
1000 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1001 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1002 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
1004 // Skip the pass by returning false.
1005 EXPECT_CALL(
1006 CallbacksHandle,
1007 runBeforePass(HasNameRegex("MockPassHandle<.*Loop>"), HasName("loop")))
1008 .WillOnce(Return(false));
1010 EXPECT_CALL(CallbacksHandle,
1011 runBeforeSkippedPass(HasNameRegex("MockPassHandle<.*Loop>"),
1012 HasName("loop")))
1013 .Times(1);
1015 EXPECT_CALL(CallbacksHandle,
1016 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
1017 HasName("loop")))
1018 .WillOnce(Return(false));
1020 EXPECT_CALL(CallbacksHandle,
1021 runBeforeSkippedPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
1022 HasName("loop")))
1023 .Times(1);
1025 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
1026 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0);
1027 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _)).Times(0);
1029 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
1030 // as well.
1031 EXPECT_CALL(CallbacksHandle, runBeforeNonSkippedPass(
1032 HasNameRegex("MockPassHandle<.*Loop>"), _))
1033 .Times(0);
1034 EXPECT_CALL(CallbacksHandle,
1035 runAfterPass(HasNameRegex("MockPassHandle<.*Loop>"), _, _))
1036 .Times(0);
1037 EXPECT_CALL(CallbacksHandle, runAfterPassInvalidated(
1038 HasNameRegex("MockPassHandle<.*Loop>"), _))
1039 .Times(0);
1040 EXPECT_CALL(
1041 CallbacksHandle,
1042 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle<.*LoopNest>"), _))
1043 .Times(0);
1044 EXPECT_CALL(CallbacksHandle,
1045 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"), _, _))
1046 .Times(0);
1047 EXPECT_CALL(
1048 CallbacksHandle,
1049 runAfterPassInvalidated(HasNameRegex("MockPassHandle<.*LoopNest>"), _))
1050 .Times(0);
1051 EXPECT_CALL(CallbacksHandle,
1052 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1053 .Times(0);
1054 EXPECT_CALL(CallbacksHandle,
1055 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1056 .Times(0);
1058 StringRef PipelineText = "test-transform";
1059 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1060 << "Pipeline was: " << PipelineText;
1061 PM.run(*M, AM);
1064 TEST_F(CGSCCCallbacksTest, Passes) {
1065 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1066 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
1067 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
1069 StringRef PipelineText = "test-transform";
1070 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1071 << "Pipeline was: " << PipelineText;
1072 PM.run(*M, AM);
1075 TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
1076 CallbacksHandle.registerPassInstrumentation();
1077 // Non-mock instrumentation not specifically mentioned below can be ignored.
1078 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1079 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1080 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
1082 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1083 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
1084 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
1086 // PassInstrumentation calls should happen in-sequence, in the same order
1087 // as passes/analyses are scheduled.
1088 ::testing::Sequence PISequence;
1089 EXPECT_CALL(CallbacksHandle,
1090 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1091 .InSequence(PISequence);
1092 EXPECT_CALL(
1093 CallbacksHandle,
1094 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1095 .InSequence(PISequence);
1096 EXPECT_CALL(
1097 CallbacksHandle,
1098 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1099 .InSequence(PISequence);
1100 EXPECT_CALL(
1101 CallbacksHandle,
1102 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1103 .InSequence(PISequence);
1104 EXPECT_CALL(CallbacksHandle,
1105 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), _))
1106 .InSequence(PISequence);
1108 // Our mock pass does not invalidate IR.
1109 EXPECT_CALL(CallbacksHandle,
1110 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
1111 .Times(0);
1113 // No passes are skipped, so there should be no calls to
1114 // runBeforeSkippedPass().
1115 EXPECT_CALL(
1116 CallbacksHandle,
1117 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1118 .Times(0);
1120 StringRef PipelineText = "test-transform";
1121 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1122 << "Pipeline was: " << PipelineText;
1123 PM.run(*M, AM);
1126 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
1127 CallbacksHandle.registerPassInstrumentation();
1128 // Non-mock instrumentation not specifically mentioned below can be ignored.
1129 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1130 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1131 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
1133 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1134 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
1135 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(&PassHandle.invalidateSCC),
1136 WithArgs<0, 1, 2>(&getAnalysisResult)));
1138 // PassInstrumentation calls should happen in-sequence, in the same order
1139 // as passes/analyses are scheduled.
1140 ::testing::Sequence PISequence;
1141 EXPECT_CALL(CallbacksHandle,
1142 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1143 .InSequence(PISequence);
1144 EXPECT_CALL(
1145 CallbacksHandle,
1146 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1147 .InSequence(PISequence);
1148 EXPECT_CALL(
1149 CallbacksHandle,
1150 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1151 .InSequence(PISequence);
1152 EXPECT_CALL(
1153 CallbacksHandle,
1154 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1155 .InSequence(PISequence);
1156 EXPECT_CALL(CallbacksHandle,
1157 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
1158 .InSequence(PISequence);
1159 EXPECT_CALL(CallbacksHandle,
1160 runAfterPassInvalidated(HasNameRegex("^PassManager"), _))
1161 .InSequence(PISequence);
1163 // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
1164 EXPECT_CALL(CallbacksHandle,
1165 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), _))
1166 .Times(0);
1168 StringRef PipelineText = "test-transform";
1169 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1170 << "Pipeline was: " << PipelineText;
1171 PM.run(*M, AM);
1174 TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
1175 CallbacksHandle.registerPassInstrumentation();
1176 // Non-mock instrumentation run here can safely be ignored.
1177 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1178 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1179 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
1181 // Skip the pass by returning false.
1182 EXPECT_CALL(CallbacksHandle,
1183 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1184 .WillOnce(Return(false));
1186 EXPECT_CALL(
1187 CallbacksHandle,
1188 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1189 .Times(1);
1191 // neither Analysis nor Pass are called.
1192 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0);
1193 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0);
1195 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
1196 // as well.
1197 EXPECT_CALL(CallbacksHandle,
1198 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
1199 .Times(0);
1200 EXPECT_CALL(CallbacksHandle,
1201 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
1202 .Times(0);
1203 EXPECT_CALL(CallbacksHandle,
1204 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
1205 .Times(0);
1206 EXPECT_CALL(CallbacksHandle,
1207 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1208 .Times(0);
1209 EXPECT_CALL(CallbacksHandle,
1210 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1211 .Times(0);
1213 StringRef PipelineText = "test-transform";
1214 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1215 << "Pipeline was: " << PipelineText;
1216 PM.run(*M, AM);
1219 /// Test parsing of the names of analysis utilities for our mock analysis
1220 /// for all IRUnits.
1222 /// We first require<>, then invalidate<> it, expecting the analysis to be run
1223 /// once and subsequently invalidated.
1224 TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
1225 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
1226 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
1228 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1229 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1230 << "Pipeline was: " << PipelineText;
1231 PM.run(*M, AM);
1234 TEST_F(CGSCCCallbacksTest, PassUtilities) {
1235 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1236 EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
1238 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1239 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1240 << "Pipeline was: " << PipelineText;
1241 PM.run(*M, AM);
1244 TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
1245 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
1246 EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
1248 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1249 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1250 << "Pipeline was: " << PipelineText;
1251 PM.run(*M, AM);
1254 TEST_F(LoopCallbacksTest, PassUtilities) {
1255 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
1256 EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
1258 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1260 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1261 << "Pipeline was: " << PipelineText;
1262 PM.run(*M, AM);
1265 /// Test parsing of the top-level pipeline.
1267 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
1268 /// from PassBuilder if it encounters an unknown pipeline entry at the top level
1269 /// (i.e., the first entry on the pipeline).
1270 /// This test parses a pipeline named 'another-pipeline', whose only elements
1271 /// may be the test-transform pass or the analysis utilities
1272 TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
1273 PB.registerParseTopLevelPipelineCallback(
1274 [this](ModulePassManager &MPM,
1275 ArrayRef<PassBuilder::PipelineElement> Pipeline) {
1276 auto &FirstName = Pipeline.front().Name;
1277 auto &InnerPipeline = Pipeline.front().InnerPipeline;
1278 if (FirstName == "another-pipeline") {
1279 for (auto &E : InnerPipeline) {
1280 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", E.Name,
1281 PM))
1282 continue;
1284 if (E.Name == "test-transform") {
1285 PM.addPass(PassHandle.getPass());
1286 continue;
1288 return false;
1291 return true;
1294 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
1295 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
1296 .WillOnce(&getAnalysisResult);
1297 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
1299 StringRef PipelineText =
1300 "another-pipeline(test-transform,invalidate<test-analysis>)";
1301 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1302 << "Pipeline was: " << PipelineText;
1303 PM.run(*M, AM);
1305 /// Test the negative case
1306 PipelineText = "another-pipeline(instcombine)";
1307 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Failed())
1308 << "Pipeline was: " << PipelineText;
1310 } // end anonymous namespace