Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / unittests / IR / PassBuilderCallbacksTest.cpp
blob6230aed7b7119be6a91980bc0a9d1eae391c0891
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/Module.h>
19 #include <llvm/IR/PassInstrumentation.h>
20 #include <llvm/IR/PassManager.h>
21 #include <llvm/Passes/PassBuilder.h>
22 #include <llvm/Support/Regex.h>
23 #include <llvm/Support/SourceMgr.h>
24 #include <llvm/Transforms/Scalar/LoopPassManager.h>
26 using namespace llvm;
28 namespace {
29 using testing::AnyNumber;
30 using testing::DoAll;
31 using testing::Not;
32 using testing::Return;
33 using testing::WithArgs;
34 using testing::_;
36 /// A CRTP base for analysis mock handles
37 ///
38 /// This class reconciles mocking with the value semantics implementation of the
39 /// AnalysisManager. Analysis mock handles should derive from this class and
40 /// call \c setDefault() in their constroctur for wiring up the defaults defined
41 /// by this base with their mock run() and invalidate() implementations.
42 template <typename DerivedT, typename IRUnitT,
43 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
44 typename... ExtraArgTs>
45 class MockAnalysisHandleBase {
46 public:
47 class Analysis : public AnalysisInfoMixin<Analysis> {
48 friend AnalysisInfoMixin<Analysis>;
49 friend MockAnalysisHandleBase;
50 static AnalysisKey Key;
52 DerivedT *Handle;
54 Analysis(DerivedT &Handle) : Handle(&Handle) {
55 static_assert(std::is_base_of<MockAnalysisHandleBase, DerivedT>::value,
56 "Must pass the derived type to this template!");
59 public:
60 class Result {
61 friend MockAnalysisHandleBase;
63 DerivedT *Handle;
65 Result(DerivedT &Handle) : Handle(&Handle) {}
67 public:
68 // Forward invalidation events to the mock handle.
69 bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
70 typename AnalysisManagerT::Invalidator &Inv) {
71 return Handle->invalidate(IR, PA, Inv);
75 Result run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) {
76 return Handle->run(IR, AM, ExtraArgs...);
80 Analysis getAnalysis() { return Analysis(static_cast<DerivedT &>(*this)); }
81 typename Analysis::Result getResult() {
82 return typename Analysis::Result(static_cast<DerivedT &>(*this));
84 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
86 protected:
87 // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within
88 // the template, so we use a boring static function.
89 static bool invalidateCallback(IRUnitT &IR, const PreservedAnalyses &PA,
90 typename AnalysisManagerT::Invalidator &Inv) {
91 auto PAC = PA.template getChecker<Analysis>();
92 return !PAC.preserved() &&
93 !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
96 /// Derived classes should call this in their constructor to set up default
97 /// mock actions. (We can't do this in our constructor because this has to
98 /// run after the DerivedT is constructed.)
99 void setDefaults() {
100 ON_CALL(static_cast<DerivedT &>(*this),
101 run(_, _, testing::Matcher<ExtraArgTs>(_)...))
102 .WillByDefault(Return(this->getResult()));
103 ON_CALL(static_cast<DerivedT &>(*this), invalidate(_, _, _))
104 .WillByDefault(&invalidateCallback);
108 /// A CRTP base for pass mock handles
110 /// This class reconciles mocking with the value semantics implementation of the
111 /// PassManager. Pass mock handles should derive from this class and
112 /// call \c setDefault() in their constroctur for wiring up the defaults defined
113 /// by this base with their mock run() and invalidate() implementations.
114 template <typename DerivedT, typename IRUnitT, typename AnalysisManagerT,
115 typename... ExtraArgTs>
116 AnalysisKey MockAnalysisHandleBase<DerivedT, IRUnitT, AnalysisManagerT,
117 ExtraArgTs...>::Analysis::Key;
119 template <typename DerivedT, typename IRUnitT,
120 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
121 typename... ExtraArgTs>
122 class MockPassHandleBase {
123 public:
124 class Pass : public PassInfoMixin<Pass> {
125 friend MockPassHandleBase;
127 DerivedT *Handle;
129 Pass(DerivedT &Handle) : Handle(&Handle) {
130 static_assert(std::is_base_of<MockPassHandleBase, DerivedT>::value,
131 "Must pass the derived type to this template!");
134 public:
135 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
136 ExtraArgTs... ExtraArgs) {
137 return Handle->run(IR, AM, ExtraArgs...);
141 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
143 Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); }
145 protected:
146 /// Derived classes should call this in their constructor to set up default
147 /// mock actions. (We can't do this in our constructor because this has to
148 /// run after the DerivedT is constructed.)
149 void setDefaults() {
150 ON_CALL(static_cast<DerivedT &>(*this),
151 run(_, _, testing::Matcher<ExtraArgTs>(_)...))
152 .WillByDefault(Return(PreservedAnalyses::all()));
156 /// Mock handles for passes for the IRUnits Module, CGSCC, Function, Loop.
157 /// These handles define the appropriate run() mock interface for the respective
158 /// IRUnit type.
159 template <typename IRUnitT> struct MockPassHandle;
160 template <>
161 struct MockPassHandle<Loop>
162 : MockPassHandleBase<MockPassHandle<Loop>, Loop, LoopAnalysisManager,
163 LoopStandardAnalysisResults &, LPMUpdater &> {
164 MOCK_METHOD4(run,
165 PreservedAnalyses(Loop &, LoopAnalysisManager &,
166 LoopStandardAnalysisResults &, LPMUpdater &));
167 static void invalidateLoop(Loop &L, LoopAnalysisManager &,
168 LoopStandardAnalysisResults &,
169 LPMUpdater &Updater) {
170 Updater.markLoopAsDeleted(L, L.getName());
172 MockPassHandle() { setDefaults(); }
175 template <>
176 struct MockPassHandle<LoopNest>
177 : MockPassHandleBase<MockPassHandle<LoopNest>, LoopNest,
178 LoopAnalysisManager, LoopStandardAnalysisResults &,
179 LPMUpdater &> {
180 MOCK_METHOD4(run,
181 PreservedAnalyses(LoopNest &, LoopAnalysisManager &,
182 LoopStandardAnalysisResults &, LPMUpdater &));
183 static void invalidateLoopNest(LoopNest &L, LoopAnalysisManager &,
184 LoopStandardAnalysisResults &,
185 LPMUpdater &Updater) {
186 Updater.markLoopAsDeleted(L.getOutermostLoop(), L.getName());
188 MockPassHandle() { setDefaults(); }
191 template <>
192 struct MockPassHandle<Function>
193 : MockPassHandleBase<MockPassHandle<Function>, Function> {
194 MOCK_METHOD2(run, PreservedAnalyses(Function &, FunctionAnalysisManager &));
196 MockPassHandle() { setDefaults(); }
199 template <>
200 struct MockPassHandle<LazyCallGraph::SCC>
201 : MockPassHandleBase<MockPassHandle<LazyCallGraph::SCC>, LazyCallGraph::SCC,
202 CGSCCAnalysisManager, LazyCallGraph &,
203 CGSCCUpdateResult &> {
204 MOCK_METHOD4(run,
205 PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
206 LazyCallGraph &G, CGSCCUpdateResult &UR));
208 static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
209 LazyCallGraph &, CGSCCUpdateResult &UR) {
210 UR.InvalidatedSCCs.insert(&C);
213 MockPassHandle() { setDefaults(); }
216 template <>
217 struct MockPassHandle<Module>
218 : MockPassHandleBase<MockPassHandle<Module>, Module> {
219 MOCK_METHOD2(run, PreservedAnalyses(Module &, ModuleAnalysisManager &));
221 MockPassHandle() { setDefaults(); }
224 /// Mock handles for analyses for the IRUnits Module, CGSCC, Function, Loop.
225 /// These handles define the appropriate run() and invalidate() mock interfaces
226 /// for the respective IRUnit type.
227 template <typename IRUnitT> struct MockAnalysisHandle;
228 template <>
229 struct MockAnalysisHandle<Loop>
230 : MockAnalysisHandleBase<MockAnalysisHandle<Loop>, Loop,
231 LoopAnalysisManager,
232 LoopStandardAnalysisResults &> {
234 MOCK_METHOD3_T(run, typename Analysis::Result(Loop &, LoopAnalysisManager &,
235 LoopStandardAnalysisResults &));
237 MOCK_METHOD3_T(invalidate, bool(Loop &, const PreservedAnalyses &,
238 LoopAnalysisManager::Invalidator &));
240 MockAnalysisHandle() { this->setDefaults(); }
243 template <>
244 struct MockAnalysisHandle<Function>
245 : MockAnalysisHandleBase<MockAnalysisHandle<Function>, Function> {
246 MOCK_METHOD2(run, Analysis::Result(Function &, FunctionAnalysisManager &));
248 MOCK_METHOD3(invalidate, bool(Function &, const PreservedAnalyses &,
249 FunctionAnalysisManager::Invalidator &));
251 MockAnalysisHandle() { setDefaults(); }
254 template <>
255 struct MockAnalysisHandle<LazyCallGraph::SCC>
256 : MockAnalysisHandleBase<MockAnalysisHandle<LazyCallGraph::SCC>,
257 LazyCallGraph::SCC, CGSCCAnalysisManager,
258 LazyCallGraph &> {
259 MOCK_METHOD3(run, Analysis::Result(LazyCallGraph::SCC &,
260 CGSCCAnalysisManager &, LazyCallGraph &));
262 MOCK_METHOD3(invalidate, bool(LazyCallGraph::SCC &, const PreservedAnalyses &,
263 CGSCCAnalysisManager::Invalidator &));
265 MockAnalysisHandle() { setDefaults(); }
268 template <>
269 struct MockAnalysisHandle<Module>
270 : MockAnalysisHandleBase<MockAnalysisHandle<Module>, Module> {
271 MOCK_METHOD2(run, Analysis::Result(Module &, ModuleAnalysisManager &));
273 MOCK_METHOD3(invalidate, bool(Module &, const PreservedAnalyses &,
274 ModuleAnalysisManager::Invalidator &));
276 MockAnalysisHandle() { setDefaults(); }
279 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
280 SMDiagnostic Err;
281 return parseAssemblyString(IR, Err, C);
284 /// Helper for HasName matcher that returns getName both for IRUnit and
285 /// for IRUnit pointer wrapper into llvm::Any (wrapped by PassInstrumentation).
286 template <typename IRUnitT> std::string getName(const IRUnitT &IR) {
287 return std::string(IR.getName());
290 template <> std::string getName(const StringRef &name) {
291 return std::string(name);
294 template <> std::string getName(const Any &WrappedIR) {
295 if (const auto *const *M = llvm::any_cast<const Module *>(&WrappedIR))
296 return (*M)->getName().str();
297 if (const auto *const *F = llvm::any_cast<const Function *>(&WrappedIR))
298 return (*F)->getName().str();
299 if (const auto *const *L = llvm::any_cast<const Loop *>(&WrappedIR))
300 return (*L)->getName().str();
301 if (const auto *const *L = llvm::any_cast<const LoopNest *>(&WrappedIR))
302 return (*L)->getName().str();
303 if (const auto *const *C =
304 llvm::any_cast<const LazyCallGraph::SCC *>(&WrappedIR))
305 return (*C)->getName();
306 return "<UNKNOWN>";
308 /// Define a custom matcher for objects which support a 'getName' method.
310 /// LLVM often has IR objects or analysis objects which expose a name
311 /// and in tests it is convenient to match these by name for readability.
312 /// Usually, this name is either a StringRef or a plain std::string. This
313 /// matcher supports any type exposing a getName() method of this form whose
314 /// return value is compatible with an std::ostream. For StringRef, this uses
315 /// the shift operator defined above.
317 /// It should be used as:
319 /// HasName("my_function")
321 /// No namespace or other qualification is required.
322 MATCHER_P(HasName, Name, "") {
323 *result_listener << "has name '" << getName(arg) << "'";
324 return Name == getName(arg);
327 MATCHER_P(HasNameRegex, Name, "") {
328 *result_listener << "has name '" << getName(arg) << "'";
329 llvm::Regex r(Name);
330 return r.match(getName(arg));
333 struct MockPassInstrumentationCallbacks {
334 PassInstrumentationCallbacks Callbacks;
336 MockPassInstrumentationCallbacks() {
337 ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true));
339 MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
340 MOCK_METHOD2(runBeforeSkippedPass, void(StringRef PassID, llvm::Any));
341 MOCK_METHOD2(runBeforeNonSkippedPass, void(StringRef PassID, llvm::Any));
342 MOCK_METHOD3(runAfterPass,
343 void(StringRef PassID, llvm::Any, const PreservedAnalyses &PA));
344 MOCK_METHOD2(runAfterPassInvalidated,
345 void(StringRef PassID, const PreservedAnalyses &PA));
346 MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
347 MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
349 void registerPassInstrumentation() {
350 Callbacks.registerShouldRunOptionalPassCallback(
351 [this](StringRef P, llvm::Any IR) {
352 return this->runBeforePass(P, IR);
354 Callbacks.registerBeforeSkippedPassCallback(
355 [this](StringRef P, llvm::Any IR) {
356 this->runBeforeSkippedPass(P, IR);
358 Callbacks.registerBeforeNonSkippedPassCallback(
359 [this](StringRef P, llvm::Any IR) {
360 this->runBeforeNonSkippedPass(P, IR);
362 Callbacks.registerAfterPassCallback(
363 [this](StringRef P, llvm::Any IR, const PreservedAnalyses &PA) {
364 this->runAfterPass(P, IR, PA);
366 Callbacks.registerAfterPassInvalidatedCallback(
367 [this](StringRef P, const PreservedAnalyses &PA) {
368 this->runAfterPassInvalidated(P, PA);
370 Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
371 return this->runBeforeAnalysis(P, IR);
373 Callbacks.registerAfterAnalysisCallback(
374 [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); });
377 void ignoreNonMockPassInstrumentation(StringRef IRName) {
378 // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
379 // parts of a pipeline that we do not care about (e.g. various passes added
380 // by default by PassBuilder - Verifier pass etc).
381 // Make sure to avoid ignoring Mock passes/analysis, we definitely want
382 // to check these explicitly.
383 EXPECT_CALL(*this,
384 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
385 .Times(AnyNumber());
386 EXPECT_CALL(
387 *this, runBeforeSkippedPass(Not(HasNameRegex("Mock")), HasName(IRName)))
388 .Times(AnyNumber());
389 EXPECT_CALL(*this, runBeforeNonSkippedPass(Not(HasNameRegex("Mock")),
390 HasName(IRName)))
391 .Times(AnyNumber());
392 EXPECT_CALL(*this,
393 runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName), _))
394 .Times(AnyNumber());
395 EXPECT_CALL(*this,
396 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
397 .Times(AnyNumber());
398 EXPECT_CALL(*this,
399 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
400 .Times(AnyNumber());
404 template <typename IRUnitT>
405 using ExtraMockPassHandle =
406 std::conditional_t<std::is_same_v<IRUnitT, Loop>, MockPassHandle<LoopNest>,
407 MockPassHandle<IRUnitT>>;
409 template <typename PassManagerT> class PassBuilderCallbacksTest;
411 /// This test fixture is shared between all the actual tests below and
412 /// takes care of setting up appropriate defaults.
414 /// The template specialization serves to extract the IRUnit and AM types from
415 /// the given PassManagerT.
416 template <typename TestIRUnitT, typename... ExtraPassArgTs,
417 typename... ExtraAnalysisArgTs>
418 class PassBuilderCallbacksTest<PassManager<
419 TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>,
420 ExtraPassArgTs...>> : public testing::Test {
421 protected:
422 using IRUnitT = TestIRUnitT;
423 using AnalysisManagerT = AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>;
424 using PassManagerT =
425 PassManager<TestIRUnitT, AnalysisManagerT, ExtraPassArgTs...>;
426 using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis;
428 LLVMContext Context;
429 std::unique_ptr<Module> M;
431 MockPassInstrumentationCallbacks CallbacksHandle;
433 PassBuilder PB;
434 ModulePassManager PM;
435 LoopAnalysisManager LAM;
436 FunctionAnalysisManager FAM;
437 CGSCCAnalysisManager CGAM;
438 ModuleAnalysisManager AM;
440 MockPassHandle<IRUnitT> PassHandle;
441 ExtraMockPassHandle<IRUnitT> ExtraPassHandle;
443 MockAnalysisHandle<IRUnitT> AnalysisHandle;
445 static PreservedAnalyses getAnalysisResult(IRUnitT &U, AnalysisManagerT &AM,
446 ExtraAnalysisArgTs &&... Args) {
447 (void)AM.template getResult<AnalysisT>(
448 U, std::forward<ExtraAnalysisArgTs>(Args)...);
449 return PreservedAnalyses::all();
452 PassBuilderCallbacksTest()
453 : M(parseIR(Context,
454 "declare void @bar()\n"
455 "define void @foo(i32 %n) {\n"
456 "entry:\n"
457 " br label %loop\n"
458 "loop:\n"
459 " %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
460 " %iv.next = add i32 %iv, 1\n"
461 " tail call void @bar()\n"
462 " %cmp = icmp eq i32 %iv, %n\n"
463 " br i1 %cmp, label %exit, label %loop\n"
464 "exit:\n"
465 " ret void\n"
466 "}\n")),
467 CallbacksHandle(), PB(nullptr, PipelineTuningOptions(), std::nullopt,
468 &CallbacksHandle.Callbacks),
469 PM(), LAM(), FAM(), CGAM(), AM() {
471 EXPECT_TRUE(&CallbacksHandle.Callbacks ==
472 PB.getPassInstrumentationCallbacks());
474 /// Register a callback for analysis registration.
476 /// The callback is a function taking a reference to an AnalyisManager
477 /// object. When called, the callee gets to register its own analyses with
478 /// this PassBuilder instance.
479 PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) {
480 // Register our mock analysis
481 AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
484 /// Register a callback for pipeline parsing.
486 /// During parsing of a textual pipeline, the PassBuilder will call these
487 /// callbacks for each encountered pass name that it does not know. This
488 /// includes both simple pass names as well as names of sub-pipelines. In
489 /// the latter case, the InnerPipeline is not empty.
490 PB.registerPipelineParsingCallback(
491 [this](StringRef Name, PassManagerT &PM,
492 ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
493 /// Handle parsing of the names of analysis utilities such as
494 /// require<test-analysis> and invalidate<test-analysis> for our
495 /// analysis mock handle
496 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", Name, PM))
497 return true;
499 /// Parse the name of our pass mock handle
500 if (Name == "test-transform") {
501 PM.addPass(PassHandle.getPass());
502 if (std::is_same<IRUnitT, Loop>::value)
503 PM.addPass(ExtraPassHandle.getPass());
504 return true;
506 return false;
509 /// Register builtin analyses and cross-register the analysis proxies
510 PB.registerModuleAnalyses(AM);
511 PB.registerCGSCCAnalyses(CGAM);
512 PB.registerFunctionAnalyses(FAM);
513 PB.registerLoopAnalyses(LAM);
514 PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
518 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
519 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
520 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
521 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
523 /// Test parsing of the name of our mock pass for all IRUnits.
525 /// The pass should by default run our mock analysis and then preserve it.
526 TEST_F(ModuleCallbacksTest, Passes) {
527 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
528 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
529 .WillOnce(&getAnalysisResult);
531 StringRef PipelineText = "test-transform";
532 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
533 << "Pipeline was: " << PipelineText;
535 PM.run(*M, AM);
538 TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
539 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
540 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
541 .WillOnce(&getAnalysisResult);
543 CallbacksHandle.registerPassInstrumentation();
544 // Non-mock instrumentation not specifically mentioned below can be ignored.
545 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
547 // PassInstrumentation calls should happen in-sequence, in the same order
548 // as passes/analyses are scheduled.
549 ::testing::Sequence PISequence;
550 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
551 HasName("<string>")))
552 .InSequence(PISequence);
553 EXPECT_CALL(CallbacksHandle,
554 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"),
555 HasName("<string>")))
556 .InSequence(PISequence);
557 EXPECT_CALL(CallbacksHandle,
558 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
559 HasName("<string>")))
560 .InSequence(PISequence);
561 EXPECT_CALL(
562 CallbacksHandle,
563 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
564 .InSequence(PISequence);
565 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"),
566 HasName("<string>"), _))
567 .InSequence(PISequence);
569 // No passes are skipped, so there should be no calls to
570 // runBeforeSkippedPass().
571 EXPECT_CALL(
572 CallbacksHandle,
573 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
574 .Times(0);
576 StringRef PipelineText = "test-transform";
577 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
578 << "Pipeline was: " << PipelineText;
580 PM.run(*M, AM);
583 TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
584 CallbacksHandle.registerPassInstrumentation();
585 // Non-mock instrumentation run here can safely be ignored.
586 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
587 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
589 // Skip all passes by returning false. Pass managers and adaptor passes are
590 // also passes that observed by the callbacks.
591 EXPECT_CALL(CallbacksHandle, runBeforePass(_, _))
592 .WillRepeatedly(Return(false));
594 EXPECT_CALL(CallbacksHandle,
595 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), _))
596 .Times(3);
598 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
599 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0);
601 // As the pass is skipped there is no nonskippedpass/afterPass,
602 // beforeAnalysis/afterAnalysis as well.
603 EXPECT_CALL(CallbacksHandle,
604 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
605 .Times(0);
606 EXPECT_CALL(CallbacksHandle,
607 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
608 .Times(0);
609 EXPECT_CALL(CallbacksHandle,
610 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
611 .Times(0);
612 EXPECT_CALL(CallbacksHandle,
613 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
614 .Times(0);
616 // Order is important here. `Adaptor` expectations should be checked first
617 // because the its argument contains 'PassManager' (for example:
618 // ModuleToFunctionPassAdaptor{{.*}}PassManager{{.*}}). Check
619 // `runBeforeNonSkippedPass` and `runAfterPass` to show that they are not
620 // skipped.
622 // Pass managers are not ignored.
623 // 5 = (1) ModulePassManager + (2) FunctionPassMangers + (1) LoopPassManager +
624 // (1) CGSCCPassManager
625 EXPECT_CALL(CallbacksHandle,
626 runBeforeNonSkippedPass(HasNameRegex("PassManager"), _))
627 .Times(5);
628 EXPECT_CALL(
629 CallbacksHandle,
630 runBeforeNonSkippedPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _))
631 .Times(1);
632 EXPECT_CALL(CallbacksHandle,
633 runBeforeNonSkippedPass(
634 HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _))
635 .Times(1);
636 EXPECT_CALL(
637 CallbacksHandle,
638 runBeforeNonSkippedPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _))
639 .Times(1);
640 EXPECT_CALL(
641 CallbacksHandle,
642 runBeforeNonSkippedPass(HasNameRegex("FunctionToLoopPassAdaptor"), _))
643 .Times(1);
645 // The `runAfterPass` checks are the same as these of
646 // `runBeforeNonSkippedPass`.
647 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("PassManager"), _, _))
648 .Times(5);
649 EXPECT_CALL(CallbacksHandle,
650 runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _, _))
651 .Times(1);
652 EXPECT_CALL(
653 CallbacksHandle,
654 runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _, _))
655 .Times(1);
656 EXPECT_CALL(CallbacksHandle,
657 runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _, _))
658 .Times(1);
659 EXPECT_CALL(CallbacksHandle,
660 runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _, _))
661 .Times(1);
663 // Ignore analyses introduced by adaptor passes.
664 EXPECT_CALL(CallbacksHandle,
665 runBeforeAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _))
666 .Times(AnyNumber());
667 EXPECT_CALL(CallbacksHandle,
668 runAfterAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _))
669 .Times(AnyNumber());
671 // Register Funtion and Loop version of "test-transform" for testing
672 PB.registerPipelineParsingCallback(
673 [](StringRef Name, FunctionPassManager &FPM,
674 ArrayRef<PassBuilder::PipelineElement>) {
675 if (Name == "test-transform") {
676 FPM.addPass(MockPassHandle<Function>().getPass());
677 return true;
679 return false;
681 PB.registerPipelineParsingCallback(
682 [](StringRef Name, LoopPassManager &LPM,
683 ArrayRef<PassBuilder::PipelineElement>) {
684 if (Name == "test-transform") {
685 LPM.addPass(MockPassHandle<Loop>().getPass());
686 return true;
688 return false;
691 StringRef PipelineText = "test-transform,function(test-transform),cgscc("
692 "function(loop(test-transform)))";
693 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
694 << "Pipeline was: " << PipelineText;
696 PM.run(*M, AM);
699 TEST_F(FunctionCallbacksTest, Passes) {
700 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
701 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).WillOnce(&getAnalysisResult);
703 StringRef PipelineText = "test-transform";
704 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
705 << "Pipeline was: " << PipelineText;
706 PM.run(*M, AM);
709 TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
710 CallbacksHandle.registerPassInstrumentation();
711 // Non-mock instrumentation not specifically mentioned below can be ignored.
712 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
713 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
715 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
716 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).WillOnce(&getAnalysisResult);
718 // PassInstrumentation calls should happen in-sequence, in the same order
719 // as passes/analyses are scheduled.
720 ::testing::Sequence PISequence;
721 EXPECT_CALL(CallbacksHandle,
722 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
723 .InSequence(PISequence);
724 EXPECT_CALL(
725 CallbacksHandle,
726 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
727 .InSequence(PISequence);
728 EXPECT_CALL(
729 CallbacksHandle,
730 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
731 .InSequence(PISequence);
732 EXPECT_CALL(
733 CallbacksHandle,
734 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
735 .InSequence(PISequence);
736 EXPECT_CALL(CallbacksHandle,
737 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo"), _))
738 .InSequence(PISequence);
740 // No passes are skipped, so there should be no calls to
741 // runBeforeSkippedPass().
742 EXPECT_CALL(
743 CallbacksHandle,
744 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
745 .Times(0);
747 // Our mock pass does not invalidate IR.
748 EXPECT_CALL(CallbacksHandle,
749 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
750 .Times(0);
752 StringRef PipelineText = "test-transform";
753 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
754 << "Pipeline was: " << PipelineText;
755 PM.run(*M, AM);
758 TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
759 CallbacksHandle.registerPassInstrumentation();
760 // Non-mock instrumentation run here can safely be ignored.
761 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
762 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
764 // Skip the pass by returning false.
765 EXPECT_CALL(CallbacksHandle,
766 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
767 .WillOnce(Return(false));
769 EXPECT_CALL(
770 CallbacksHandle,
771 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
772 .Times(1);
774 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
775 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0);
777 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
778 // as well.
779 EXPECT_CALL(CallbacksHandle,
780 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
781 .Times(0);
782 EXPECT_CALL(CallbacksHandle,
783 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
784 .Times(0);
785 EXPECT_CALL(CallbacksHandle,
786 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
787 .Times(0);
788 EXPECT_CALL(CallbacksHandle,
789 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
790 .Times(0);
791 EXPECT_CALL(CallbacksHandle,
792 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
793 .Times(0);
794 EXPECT_CALL(CallbacksHandle,
795 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
796 .Times(0);
798 StringRef PipelineText = "test-transform";
799 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
800 << "Pipeline was: " << PipelineText;
801 PM.run(*M, AM);
804 TEST_F(LoopCallbacksTest, Passes) {
805 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
806 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
807 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
808 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _));
810 StringRef PipelineText = "test-transform";
811 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
812 << "Pipeline was: " << PipelineText;
813 PM.run(*M, AM);
816 TEST_F(LoopCallbacksTest, InstrumentedPasses) {
817 CallbacksHandle.registerPassInstrumentation();
818 // Non-mock instrumentation not specifically mentioned below can be ignored.
819 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
820 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
821 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
823 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
824 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
825 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
826 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _));
828 // PassInstrumentation calls should happen in-sequence, in the same order
829 // as passes/analyses are scheduled.
830 ::testing::Sequence PISequence;
831 EXPECT_CALL(CallbacksHandle,
832 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
833 .InSequence(PISequence);
834 EXPECT_CALL(
835 CallbacksHandle,
836 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
837 .InSequence(PISequence);
838 EXPECT_CALL(
839 CallbacksHandle,
840 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
841 .InSequence(PISequence);
842 EXPECT_CALL(
843 CallbacksHandle,
844 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
845 .InSequence(PISequence);
846 EXPECT_CALL(CallbacksHandle,
847 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _))
848 .InSequence(PISequence);
850 EXPECT_CALL(CallbacksHandle,
851 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
852 HasName("loop")))
853 .InSequence(PISequence);
854 EXPECT_CALL(CallbacksHandle,
855 runBeforeNonSkippedPass(
856 HasNameRegex("MockPassHandle<.*LoopNest>"), HasName("loop")))
857 .InSequence(PISequence);
858 EXPECT_CALL(CallbacksHandle,
859 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
860 HasName("loop"), _))
861 .InSequence(PISequence);
863 // Our mock pass does not invalidate IR.
864 EXPECT_CALL(CallbacksHandle,
865 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
866 .Times(0);
868 // No passes are skipped, so there should be no calls to
869 // runBeforeSkippedPass().
870 EXPECT_CALL(
871 CallbacksHandle,
872 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
873 .Times(0);
875 StringRef PipelineText = "test-transform";
876 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
877 << "Pipeline was: " << PipelineText;
878 PM.run(*M, AM);
881 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
882 CallbacksHandle.registerPassInstrumentation();
883 // Non-mock instrumentation not specifically mentioned below can be ignored.
884 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
885 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
886 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
888 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
889 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
890 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(&PassHandle.invalidateLoop),
891 WithArgs<0, 1, 2>(&getAnalysisResult)));
893 // PassInstrumentation calls should happen in-sequence, in the same order
894 // as passes/analyses are scheduled.
895 ::testing::Sequence PISequence;
896 EXPECT_CALL(CallbacksHandle,
897 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
898 .InSequence(PISequence);
899 EXPECT_CALL(
900 CallbacksHandle,
901 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
902 .InSequence(PISequence);
903 EXPECT_CALL(
904 CallbacksHandle,
905 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
906 .InSequence(PISequence);
907 EXPECT_CALL(
908 CallbacksHandle,
909 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
910 .InSequence(PISequence);
911 EXPECT_CALL(CallbacksHandle,
912 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
913 .InSequence(PISequence);
914 EXPECT_CALL(CallbacksHandle,
915 runAfterPassInvalidated(HasNameRegex("^PassManager"), _))
916 .InSequence(PISequence);
918 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
919 EXPECT_CALL(CallbacksHandle,
920 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _))
921 .Times(0);
923 StringRef PipelineText = "test-transform";
924 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
925 << "Pipeline was: " << PipelineText;
926 PM.run(*M, AM);
929 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingLoopNestPasses) {
930 CallbacksHandle.registerPassInstrumentation();
931 // Non-mock instrumentation not specifically mentioned below can be ignored.
932 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
933 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
934 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
936 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
937 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
938 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
939 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _))
940 .WillOnce(DoAll(&ExtraPassHandle.invalidateLoopNest,
941 [&](LoopNest &, LoopAnalysisManager &,
942 LoopStandardAnalysisResults &,
943 LPMUpdater &) { return PreservedAnalyses::all(); }));
945 // PassInstrumentation calls should happen in-sequence, in the same order
946 // as passes/analyses are scheduled.
947 ::testing::Sequence PISequence;
948 EXPECT_CALL(CallbacksHandle,
949 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
950 .InSequence(PISequence);
951 EXPECT_CALL(
952 CallbacksHandle,
953 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
954 .InSequence(PISequence);
955 EXPECT_CALL(
956 CallbacksHandle,
957 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
958 .InSequence(PISequence);
959 EXPECT_CALL(
960 CallbacksHandle,
961 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
962 .InSequence(PISequence);
963 EXPECT_CALL(CallbacksHandle,
964 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _))
965 .InSequence(PISequence);
967 EXPECT_CALL(CallbacksHandle,
968 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
969 HasName("loop")))
970 .InSequence(PISequence);
971 EXPECT_CALL(CallbacksHandle,
972 runBeforeNonSkippedPass(
973 HasNameRegex("MockPassHandle<.*LoopNest>"), HasName("loop")))
974 .InSequence(PISequence);
975 EXPECT_CALL(
976 CallbacksHandle,
977 runAfterPassInvalidated(HasNameRegex("MockPassHandle<.*LoopNest>"), _))
978 .InSequence(PISequence);
980 EXPECT_CALL(CallbacksHandle,
981 runAfterPassInvalidated(HasNameRegex("^PassManager"), _))
982 .InSequence(PISequence);
984 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
985 EXPECT_CALL(CallbacksHandle, runAfterPassInvalidated(
986 HasNameRegex("MockPassHandle<.*Loop>"), _))
987 .Times(0);
988 EXPECT_CALL(CallbacksHandle,
989 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
990 HasName("loop"), _))
991 .Times(0);
993 StringRef PipelineText = "test-transform";
994 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
995 << "Pipeline was: " << PipelineText;
996 PM.run(*M, AM);
999 TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
1000 CallbacksHandle.registerPassInstrumentation();
1001 // Non-mock instrumentation run here can safely be ignored.
1002 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1003 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1004 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
1006 // Skip the pass by returning false.
1007 EXPECT_CALL(
1008 CallbacksHandle,
1009 runBeforePass(HasNameRegex("MockPassHandle<.*Loop>"), HasName("loop")))
1010 .WillOnce(Return(false));
1012 EXPECT_CALL(CallbacksHandle,
1013 runBeforeSkippedPass(HasNameRegex("MockPassHandle<.*Loop>"),
1014 HasName("loop")))
1015 .Times(1);
1017 EXPECT_CALL(CallbacksHandle,
1018 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
1019 HasName("loop")))
1020 .WillOnce(Return(false));
1022 EXPECT_CALL(CallbacksHandle,
1023 runBeforeSkippedPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
1024 HasName("loop")))
1025 .Times(1);
1027 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
1028 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0);
1029 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _)).Times(0);
1031 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
1032 // as well.
1033 EXPECT_CALL(CallbacksHandle, runBeforeNonSkippedPass(
1034 HasNameRegex("MockPassHandle<.*Loop>"), _))
1035 .Times(0);
1036 EXPECT_CALL(CallbacksHandle,
1037 runAfterPass(HasNameRegex("MockPassHandle<.*Loop>"), _, _))
1038 .Times(0);
1039 EXPECT_CALL(CallbacksHandle, runAfterPassInvalidated(
1040 HasNameRegex("MockPassHandle<.*Loop>"), _))
1041 .Times(0);
1042 EXPECT_CALL(
1043 CallbacksHandle,
1044 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle<.*LoopNest>"), _))
1045 .Times(0);
1046 EXPECT_CALL(CallbacksHandle,
1047 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"), _, _))
1048 .Times(0);
1049 EXPECT_CALL(
1050 CallbacksHandle,
1051 runAfterPassInvalidated(HasNameRegex("MockPassHandle<.*LoopNest>"), _))
1052 .Times(0);
1053 EXPECT_CALL(CallbacksHandle,
1054 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1055 .Times(0);
1056 EXPECT_CALL(CallbacksHandle,
1057 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1058 .Times(0);
1060 StringRef PipelineText = "test-transform";
1061 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1062 << "Pipeline was: " << PipelineText;
1063 PM.run(*M, AM);
1066 TEST_F(CGSCCCallbacksTest, Passes) {
1067 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1068 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
1069 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
1071 StringRef PipelineText = "test-transform";
1072 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1073 << "Pipeline was: " << PipelineText;
1074 PM.run(*M, AM);
1077 TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
1078 CallbacksHandle.registerPassInstrumentation();
1079 // Non-mock instrumentation not specifically mentioned below can be ignored.
1080 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1081 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1082 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
1084 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1085 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
1086 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
1088 // PassInstrumentation calls should happen in-sequence, in the same order
1089 // as passes/analyses are scheduled.
1090 ::testing::Sequence PISequence;
1091 EXPECT_CALL(CallbacksHandle,
1092 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1093 .InSequence(PISequence);
1094 EXPECT_CALL(
1095 CallbacksHandle,
1096 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1097 .InSequence(PISequence);
1098 EXPECT_CALL(
1099 CallbacksHandle,
1100 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1101 .InSequence(PISequence);
1102 EXPECT_CALL(
1103 CallbacksHandle,
1104 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1105 .InSequence(PISequence);
1106 EXPECT_CALL(CallbacksHandle,
1107 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), _))
1108 .InSequence(PISequence);
1110 // Our mock pass does not invalidate IR.
1111 EXPECT_CALL(CallbacksHandle,
1112 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
1113 .Times(0);
1115 // No passes are skipped, so there should be no calls to
1116 // runBeforeSkippedPass().
1117 EXPECT_CALL(
1118 CallbacksHandle,
1119 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1120 .Times(0);
1122 StringRef PipelineText = "test-transform";
1123 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1124 << "Pipeline was: " << PipelineText;
1125 PM.run(*M, AM);
1128 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
1129 CallbacksHandle.registerPassInstrumentation();
1130 // Non-mock instrumentation not specifically mentioned below can be ignored.
1131 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1132 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1133 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
1135 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1136 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
1137 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(&PassHandle.invalidateSCC),
1138 WithArgs<0, 1, 2>(&getAnalysisResult)));
1140 // PassInstrumentation calls should happen in-sequence, in the same order
1141 // as passes/analyses are scheduled.
1142 ::testing::Sequence PISequence;
1143 EXPECT_CALL(CallbacksHandle,
1144 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1145 .InSequence(PISequence);
1146 EXPECT_CALL(
1147 CallbacksHandle,
1148 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1149 .InSequence(PISequence);
1150 EXPECT_CALL(
1151 CallbacksHandle,
1152 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1153 .InSequence(PISequence);
1154 EXPECT_CALL(
1155 CallbacksHandle,
1156 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1157 .InSequence(PISequence);
1158 EXPECT_CALL(CallbacksHandle,
1159 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
1160 .InSequence(PISequence);
1161 EXPECT_CALL(CallbacksHandle,
1162 runAfterPassInvalidated(HasNameRegex("^PassManager"), _))
1163 .InSequence(PISequence);
1165 // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
1166 EXPECT_CALL(CallbacksHandle,
1167 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), _))
1168 .Times(0);
1170 StringRef PipelineText = "test-transform";
1171 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1172 << "Pipeline was: " << PipelineText;
1173 PM.run(*M, AM);
1176 TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
1177 CallbacksHandle.registerPassInstrumentation();
1178 // Non-mock instrumentation run here can safely be ignored.
1179 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1180 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1181 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
1183 // Skip the pass by returning false.
1184 EXPECT_CALL(CallbacksHandle,
1185 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1186 .WillOnce(Return(false));
1188 EXPECT_CALL(
1189 CallbacksHandle,
1190 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1191 .Times(1);
1193 // neither Analysis nor Pass are called.
1194 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0);
1195 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0);
1197 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
1198 // as well.
1199 EXPECT_CALL(CallbacksHandle,
1200 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
1201 .Times(0);
1202 EXPECT_CALL(CallbacksHandle,
1203 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
1204 .Times(0);
1205 EXPECT_CALL(CallbacksHandle,
1206 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
1207 .Times(0);
1208 EXPECT_CALL(CallbacksHandle,
1209 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1210 .Times(0);
1211 EXPECT_CALL(CallbacksHandle,
1212 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1213 .Times(0);
1215 StringRef PipelineText = "test-transform";
1216 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1217 << "Pipeline was: " << PipelineText;
1218 PM.run(*M, AM);
1221 /// Test parsing of the names of analysis utilities for our mock analysis
1222 /// for all IRUnits.
1224 /// We first require<>, then invalidate<> it, expecting the analysis to be run
1225 /// once and subsequently invalidated.
1226 TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
1227 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
1228 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
1230 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1231 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1232 << "Pipeline was: " << PipelineText;
1233 PM.run(*M, AM);
1236 TEST_F(CGSCCCallbacksTest, PassUtilities) {
1237 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1238 EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
1240 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1241 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1242 << "Pipeline was: " << PipelineText;
1243 PM.run(*M, AM);
1246 TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
1247 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
1248 EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
1250 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1251 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1252 << "Pipeline was: " << PipelineText;
1253 PM.run(*M, AM);
1256 TEST_F(LoopCallbacksTest, PassUtilities) {
1257 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
1258 EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
1260 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1262 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1263 << "Pipeline was: " << PipelineText;
1264 PM.run(*M, AM);
1267 /// Test parsing of the top-level pipeline.
1269 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
1270 /// from PassBuilder if it encounters an unknown pipeline entry at the top level
1271 /// (i.e., the first entry on the pipeline).
1272 /// This test parses a pipeline named 'another-pipeline', whose only elements
1273 /// may be the test-transform pass or the analysis utilities
1274 TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
1275 PB.registerParseTopLevelPipelineCallback(
1276 [this](ModulePassManager &MPM,
1277 ArrayRef<PassBuilder::PipelineElement> Pipeline) {
1278 auto &FirstName = Pipeline.front().Name;
1279 auto &InnerPipeline = Pipeline.front().InnerPipeline;
1280 if (FirstName == "another-pipeline") {
1281 for (auto &E : InnerPipeline) {
1282 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", E.Name,
1283 PM))
1284 continue;
1286 if (E.Name == "test-transform") {
1287 PM.addPass(PassHandle.getPass());
1288 continue;
1290 return false;
1293 return true;
1296 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
1297 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
1298 .WillOnce(&getAnalysisResult);
1299 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
1301 StringRef PipelineText =
1302 "another-pipeline(test-transform,invalidate<test-analysis>)";
1303 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1304 << "Pipeline was: " << PipelineText;
1305 PM.run(*M, AM);
1307 /// Test the negative case
1308 PipelineText = "another-pipeline(instcombine)";
1309 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Failed())
1310 << "Pipeline was: " << PipelineText;
1312 } // end anonymous namespace