Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / unittests / IR / PassBuilderCallbacksTest.cpp
blobf37f3336051e29707eec00b7c9b6d846def9238e
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() { 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() { 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() { 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() { 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 Any &WrappedIR) {
294 if (const auto *const *M = llvm::any_cast<const Module *>(&WrappedIR))
295 return (*M)->getName().str();
296 if (const auto *const *F = llvm::any_cast<const Function *>(&WrappedIR))
297 return (*F)->getName().str();
298 if (const auto *const *L = llvm::any_cast<const Loop *>(&WrappedIR))
299 return (*L)->getName().str();
300 if (const auto *const *L = llvm::any_cast<const LoopNest *>(&WrappedIR))
301 return (*L)->getName().str();
302 if (const auto *const *C =
303 llvm::any_cast<const LazyCallGraph::SCC *>(&WrappedIR))
304 return (*C)->getName();
305 return "<UNKNOWN>";
307 /// Define a custom matcher for objects which support a 'getName' method.
309 /// LLVM often has IR objects or analysis objects which expose a name
310 /// and in tests it is convenient to match these by name for readability.
311 /// Usually, this name is either a StringRef or a plain std::string. This
312 /// matcher supports any type exposing a getName() method of this form whose
313 /// return value is compatible with an std::ostream. For StringRef, this uses
314 /// the shift operator defined above.
316 /// It should be used as:
318 /// HasName("my_function")
320 /// No namespace or other qualification is required.
321 MATCHER_P(HasName, Name, "") {
322 *result_listener << "has name '" << getName(arg) << "'";
323 return Name == getName(arg);
326 MATCHER_P(HasNameRegex, Name, "") {
327 *result_listener << "has name '" << getName(arg) << "'";
328 llvm::Regex r(Name);
329 return r.match(getName(arg));
332 struct MockPassInstrumentationCallbacks {
333 PassInstrumentationCallbacks Callbacks;
335 MockPassInstrumentationCallbacks() {
336 ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true));
338 MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
339 MOCK_METHOD2(runBeforeSkippedPass, void(StringRef PassID, llvm::Any));
340 MOCK_METHOD2(runBeforeNonSkippedPass, void(StringRef PassID, llvm::Any));
341 MOCK_METHOD3(runAfterPass,
342 void(StringRef PassID, llvm::Any, const PreservedAnalyses &PA));
343 MOCK_METHOD2(runAfterPassInvalidated,
344 void(StringRef PassID, const PreservedAnalyses &PA));
345 MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
346 MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
348 void registerPassInstrumentation() {
349 Callbacks.registerShouldRunOptionalPassCallback(
350 [this](StringRef P, llvm::Any IR) {
351 return this->runBeforePass(P, IR);
353 Callbacks.registerBeforeSkippedPassCallback(
354 [this](StringRef P, llvm::Any IR) {
355 this->runBeforeSkippedPass(P, IR);
357 Callbacks.registerBeforeNonSkippedPassCallback(
358 [this](StringRef P, llvm::Any IR) {
359 this->runBeforeNonSkippedPass(P, IR);
361 Callbacks.registerAfterPassCallback(
362 [this](StringRef P, llvm::Any IR, const PreservedAnalyses &PA) {
363 this->runAfterPass(P, IR, PA);
365 Callbacks.registerAfterPassInvalidatedCallback(
366 [this](StringRef P, const PreservedAnalyses &PA) {
367 this->runAfterPassInvalidated(P, PA);
369 Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
370 return this->runBeforeAnalysis(P, IR);
372 Callbacks.registerAfterAnalysisCallback(
373 [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); });
376 void ignoreNonMockPassInstrumentation(StringRef IRName) {
377 // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
378 // parts of a pipeline that we do not care about (e.g. various passes added
379 // by default by PassBuilder - Verifier pass etc).
380 // Make sure to avoid ignoring Mock passes/analysis, we definitely want
381 // to check these explicitly.
382 EXPECT_CALL(*this,
383 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
384 .Times(AnyNumber());
385 EXPECT_CALL(
386 *this, runBeforeSkippedPass(Not(HasNameRegex("Mock")), HasName(IRName)))
387 .Times(AnyNumber());
388 EXPECT_CALL(*this, runBeforeNonSkippedPass(Not(HasNameRegex("Mock")),
389 HasName(IRName)))
390 .Times(AnyNumber());
391 EXPECT_CALL(*this,
392 runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName), _))
393 .Times(AnyNumber());
394 EXPECT_CALL(*this,
395 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
396 .Times(AnyNumber());
397 EXPECT_CALL(*this,
398 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
399 .Times(AnyNumber());
403 template <typename IRUnitT>
404 using ExtraMockPassHandle =
405 std::conditional_t<std::is_same_v<IRUnitT, Loop>, MockPassHandle<LoopNest>,
406 MockPassHandle<IRUnitT>>;
408 template <typename PassManagerT> class PassBuilderCallbacksTest;
410 /// This test fixture is shared between all the actual tests below and
411 /// takes care of setting up appropriate defaults.
413 /// The template specialization serves to extract the IRUnit and AM types from
414 /// the given PassManagerT.
415 template <typename TestIRUnitT, typename... ExtraPassArgTs,
416 typename... ExtraAnalysisArgTs>
417 class PassBuilderCallbacksTest<PassManager<
418 TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>,
419 ExtraPassArgTs...>> : public testing::Test {
420 protected:
421 using IRUnitT = TestIRUnitT;
422 using AnalysisManagerT = AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>;
423 using PassManagerT =
424 PassManager<TestIRUnitT, AnalysisManagerT, ExtraPassArgTs...>;
425 using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis;
427 LLVMContext Context;
428 std::unique_ptr<Module> M;
430 MockPassInstrumentationCallbacks CallbacksHandle;
432 PassBuilder PB;
433 ModulePassManager PM;
434 LoopAnalysisManager LAM;
435 FunctionAnalysisManager FAM;
436 CGSCCAnalysisManager CGAM;
437 ModuleAnalysisManager AM;
439 MockPassHandle<IRUnitT> PassHandle;
440 ExtraMockPassHandle<IRUnitT> ExtraPassHandle;
442 MockAnalysisHandle<IRUnitT> AnalysisHandle;
444 static PreservedAnalyses getAnalysisResult(IRUnitT &U, AnalysisManagerT &AM,
445 ExtraAnalysisArgTs &&... Args) {
446 (void)AM.template getResult<AnalysisT>(
447 U, std::forward<ExtraAnalysisArgTs>(Args)...);
448 return PreservedAnalyses::all();
451 PassBuilderCallbacksTest()
452 : M(parseIR(Context,
453 "declare void @bar()\n"
454 "define void @foo(i32 %n) {\n"
455 "entry:\n"
456 " br label %loop\n"
457 "loop:\n"
458 " %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
459 " %iv.next = add i32 %iv, 1\n"
460 " tail call void @bar()\n"
461 " %cmp = icmp eq i32 %iv, %n\n"
462 " br i1 %cmp, label %exit, label %loop\n"
463 "exit:\n"
464 " ret void\n"
465 "}\n")),
466 CallbacksHandle(), PB(nullptr, PipelineTuningOptions(), std::nullopt,
467 &CallbacksHandle.Callbacks),
468 PM(), LAM(), FAM(), CGAM(), AM() {
470 EXPECT_TRUE(&CallbacksHandle.Callbacks ==
471 PB.getPassInstrumentationCallbacks());
473 /// Register a callback for analysis registration.
475 /// The callback is a function taking a reference to an AnalyisManager
476 /// object. When called, the callee gets to register its own analyses with
477 /// this PassBuilder instance.
478 PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) {
479 // Register our mock analysis
480 AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
483 /// Register a callback for pipeline parsing.
485 /// During parsing of a textual pipeline, the PassBuilder will call these
486 /// callbacks for each encountered pass name that it does not know. This
487 /// includes both simple pass names as well as names of sub-pipelines. In
488 /// the latter case, the InnerPipeline is not empty.
489 PB.registerPipelineParsingCallback(
490 [this](StringRef Name, PassManagerT &PM,
491 ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
492 /// Handle parsing of the names of analysis utilities such as
493 /// require<test-analysis> and invalidate<test-analysis> for our
494 /// analysis mock handle
495 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", Name, PM))
496 return true;
498 /// Parse the name of our pass mock handle
499 if (Name == "test-transform") {
500 PM.addPass(PassHandle.getPass());
501 if (std::is_same<IRUnitT, Loop>::value)
502 PM.addPass(ExtraPassHandle.getPass());
503 return true;
505 return false;
508 /// Register builtin analyses and cross-register the analysis proxies
509 PB.registerModuleAnalyses(AM);
510 PB.registerCGSCCAnalyses(CGAM);
511 PB.registerFunctionAnalyses(FAM);
512 PB.registerLoopAnalyses(LAM);
513 PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
517 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
518 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
519 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
520 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
522 /// Test parsing of the name of our mock pass for all IRUnits.
524 /// The pass should by default run our mock analysis and then preserve it.
525 TEST_F(ModuleCallbacksTest, Passes) {
526 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
527 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
528 .WillOnce(&getAnalysisResult);
530 StringRef PipelineText = "test-transform";
531 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
532 << "Pipeline was: " << PipelineText;
534 PM.run(*M, AM);
537 TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
538 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
539 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
540 .WillOnce(&getAnalysisResult);
542 CallbacksHandle.registerPassInstrumentation();
543 // Non-mock instrumentation not specifically mentioned below can be ignored.
544 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
546 // PassInstrumentation calls should happen in-sequence, in the same order
547 // as passes/analyses are scheduled.
548 ::testing::Sequence PISequence;
549 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
550 HasName("<string>")))
551 .InSequence(PISequence);
552 EXPECT_CALL(CallbacksHandle,
553 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"),
554 HasName("<string>")))
555 .InSequence(PISequence);
556 EXPECT_CALL(CallbacksHandle,
557 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
558 HasName("<string>")))
559 .InSequence(PISequence);
560 EXPECT_CALL(
561 CallbacksHandle,
562 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
563 .InSequence(PISequence);
564 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"),
565 HasName("<string>"), _))
566 .InSequence(PISequence);
568 // No passes are skipped, so there should be no calls to
569 // runBeforeSkippedPass().
570 EXPECT_CALL(
571 CallbacksHandle,
572 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
573 .Times(0);
575 StringRef PipelineText = "test-transform";
576 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
577 << "Pipeline was: " << PipelineText;
579 PM.run(*M, AM);
582 TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
583 CallbacksHandle.registerPassInstrumentation();
584 // Non-mock instrumentation run here can safely be ignored.
585 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
586 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
588 // Skip all passes by returning false. Pass managers and adaptor passes are
589 // also passes that observed by the callbacks.
590 EXPECT_CALL(CallbacksHandle, runBeforePass(_, _))
591 .WillRepeatedly(Return(false));
593 EXPECT_CALL(CallbacksHandle,
594 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), _))
595 .Times(3);
597 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
598 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0);
600 // As the pass is skipped there is no nonskippedpass/afterPass,
601 // beforeAnalysis/afterAnalysis as well.
602 EXPECT_CALL(CallbacksHandle,
603 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
604 .Times(0);
605 EXPECT_CALL(CallbacksHandle,
606 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
607 .Times(0);
608 EXPECT_CALL(CallbacksHandle,
609 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
610 .Times(0);
611 EXPECT_CALL(CallbacksHandle,
612 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
613 .Times(0);
615 // Order is important here. `Adaptor` expectations should be checked first
616 // because the its argument contains 'PassManager' (for example:
617 // ModuleToFunctionPassAdaptor{{.*}}PassManager{{.*}}). Check
618 // `runBeforeNonSkippedPass` and `runAfterPass` to show that they are not
619 // skipped.
621 // Pass managers are not ignored.
622 // 5 = (1) ModulePassManager + (2) FunctionPassMangers + (1) LoopPassManager +
623 // (1) CGSCCPassManager
624 EXPECT_CALL(CallbacksHandle,
625 runBeforeNonSkippedPass(HasNameRegex("PassManager"), _))
626 .Times(5);
627 EXPECT_CALL(
628 CallbacksHandle,
629 runBeforeNonSkippedPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _))
630 .Times(1);
631 EXPECT_CALL(CallbacksHandle,
632 runBeforeNonSkippedPass(
633 HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _))
634 .Times(1);
635 EXPECT_CALL(
636 CallbacksHandle,
637 runBeforeNonSkippedPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _))
638 .Times(1);
639 EXPECT_CALL(
640 CallbacksHandle,
641 runBeforeNonSkippedPass(HasNameRegex("FunctionToLoopPassAdaptor"), _))
642 .Times(1);
644 // The `runAfterPass` checks are the same as these of
645 // `runBeforeNonSkippedPass`.
646 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("PassManager"), _, _))
647 .Times(5);
648 EXPECT_CALL(CallbacksHandle,
649 runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _, _))
650 .Times(1);
651 EXPECT_CALL(
652 CallbacksHandle,
653 runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _, _))
654 .Times(1);
655 EXPECT_CALL(CallbacksHandle,
656 runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _, _))
657 .Times(1);
658 EXPECT_CALL(CallbacksHandle,
659 runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _, _))
660 .Times(1);
662 // Ignore analyses introduced by adaptor passes.
663 EXPECT_CALL(CallbacksHandle,
664 runBeforeAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _))
665 .Times(AnyNumber());
666 EXPECT_CALL(CallbacksHandle,
667 runAfterAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _))
668 .Times(AnyNumber());
670 // Register Funtion and Loop version of "test-transform" for testing
671 PB.registerPipelineParsingCallback(
672 [](StringRef Name, FunctionPassManager &FPM,
673 ArrayRef<PassBuilder::PipelineElement>) {
674 if (Name == "test-transform") {
675 FPM.addPass(MockPassHandle<Function>().getPass());
676 return true;
678 return false;
680 PB.registerPipelineParsingCallback(
681 [](StringRef Name, LoopPassManager &LPM,
682 ArrayRef<PassBuilder::PipelineElement>) {
683 if (Name == "test-transform") {
684 LPM.addPass(MockPassHandle<Loop>().getPass());
685 return true;
687 return false;
690 StringRef PipelineText = "test-transform,function(test-transform),cgscc("
691 "function(loop(test-transform)))";
692 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
693 << "Pipeline was: " << PipelineText;
695 PM.run(*M, AM);
698 TEST_F(FunctionCallbacksTest, Passes) {
699 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
700 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).WillOnce(&getAnalysisResult);
702 StringRef PipelineText = "test-transform";
703 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
704 << "Pipeline was: " << PipelineText;
705 PM.run(*M, AM);
708 TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
709 CallbacksHandle.registerPassInstrumentation();
710 // Non-mock instrumentation not specifically mentioned below can be ignored.
711 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
712 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
714 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
715 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).WillOnce(&getAnalysisResult);
717 // PassInstrumentation calls should happen in-sequence, in the same order
718 // as passes/analyses are scheduled.
719 ::testing::Sequence PISequence;
720 EXPECT_CALL(CallbacksHandle,
721 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
722 .InSequence(PISequence);
723 EXPECT_CALL(
724 CallbacksHandle,
725 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
726 .InSequence(PISequence);
727 EXPECT_CALL(
728 CallbacksHandle,
729 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
730 .InSequence(PISequence);
731 EXPECT_CALL(
732 CallbacksHandle,
733 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
734 .InSequence(PISequence);
735 EXPECT_CALL(CallbacksHandle,
736 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo"), _))
737 .InSequence(PISequence);
739 // No passes are skipped, so there should be no calls to
740 // runBeforeSkippedPass().
741 EXPECT_CALL(
742 CallbacksHandle,
743 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
744 .Times(0);
746 // Our mock pass does not invalidate IR.
747 EXPECT_CALL(CallbacksHandle,
748 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
749 .Times(0);
751 StringRef PipelineText = "test-transform";
752 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
753 << "Pipeline was: " << PipelineText;
754 PM.run(*M, AM);
757 TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
758 CallbacksHandle.registerPassInstrumentation();
759 // Non-mock instrumentation run here can safely be ignored.
760 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
761 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
763 // Skip the pass by returning false.
764 EXPECT_CALL(CallbacksHandle,
765 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
766 .WillOnce(Return(false));
768 EXPECT_CALL(
769 CallbacksHandle,
770 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
771 .Times(1);
773 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
774 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0);
776 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
777 // as well.
778 EXPECT_CALL(CallbacksHandle,
779 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
780 .Times(0);
781 EXPECT_CALL(CallbacksHandle,
782 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
783 .Times(0);
784 EXPECT_CALL(CallbacksHandle,
785 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
786 .Times(0);
787 EXPECT_CALL(CallbacksHandle,
788 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
789 .Times(0);
790 EXPECT_CALL(CallbacksHandle,
791 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
792 .Times(0);
793 EXPECT_CALL(CallbacksHandle,
794 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
795 .Times(0);
797 StringRef PipelineText = "test-transform";
798 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
799 << "Pipeline was: " << PipelineText;
800 PM.run(*M, AM);
803 TEST_F(LoopCallbacksTest, Passes) {
804 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
805 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
806 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
807 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _));
809 StringRef PipelineText = "test-transform";
810 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
811 << "Pipeline was: " << PipelineText;
812 PM.run(*M, AM);
815 TEST_F(LoopCallbacksTest, InstrumentedPasses) {
816 CallbacksHandle.registerPassInstrumentation();
817 // Non-mock instrumentation not specifically mentioned below can be ignored.
818 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
819 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
820 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
822 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
823 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
824 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
825 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _));
827 // PassInstrumentation calls should happen in-sequence, in the same order
828 // as passes/analyses are scheduled.
829 ::testing::Sequence PISequence;
830 EXPECT_CALL(CallbacksHandle,
831 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
832 .InSequence(PISequence);
833 EXPECT_CALL(
834 CallbacksHandle,
835 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
836 .InSequence(PISequence);
837 EXPECT_CALL(
838 CallbacksHandle,
839 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
840 .InSequence(PISequence);
841 EXPECT_CALL(
842 CallbacksHandle,
843 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
844 .InSequence(PISequence);
845 EXPECT_CALL(CallbacksHandle,
846 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _))
847 .InSequence(PISequence);
849 EXPECT_CALL(CallbacksHandle,
850 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
851 HasName("loop")))
852 .InSequence(PISequence);
853 EXPECT_CALL(CallbacksHandle,
854 runBeforeNonSkippedPass(
855 HasNameRegex("MockPassHandle<.*LoopNest>"), HasName("loop")))
856 .InSequence(PISequence);
857 EXPECT_CALL(CallbacksHandle,
858 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
859 HasName("loop"), _))
860 .InSequence(PISequence);
862 // Our mock pass does not invalidate IR.
863 EXPECT_CALL(CallbacksHandle,
864 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
865 .Times(0);
867 // No passes are skipped, so there should be no calls to
868 // runBeforeSkippedPass().
869 EXPECT_CALL(
870 CallbacksHandle,
871 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
872 .Times(0);
874 StringRef PipelineText = "test-transform";
875 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
876 << "Pipeline was: " << PipelineText;
877 PM.run(*M, AM);
880 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
881 CallbacksHandle.registerPassInstrumentation();
882 // Non-mock instrumentation not specifically mentioned below can be ignored.
883 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
884 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
885 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
887 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
888 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
889 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(&PassHandle.invalidateLoop),
890 WithArgs<0, 1, 2>(&getAnalysisResult)));
892 // PassInstrumentation calls should happen in-sequence, in the same order
893 // as passes/analyses are scheduled.
894 ::testing::Sequence PISequence;
895 EXPECT_CALL(CallbacksHandle,
896 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
897 .InSequence(PISequence);
898 EXPECT_CALL(
899 CallbacksHandle,
900 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
901 .InSequence(PISequence);
902 EXPECT_CALL(
903 CallbacksHandle,
904 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
905 .InSequence(PISequence);
906 EXPECT_CALL(
907 CallbacksHandle,
908 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
909 .InSequence(PISequence);
910 EXPECT_CALL(CallbacksHandle,
911 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
912 .InSequence(PISequence);
913 EXPECT_CALL(CallbacksHandle,
914 runAfterPassInvalidated(HasNameRegex("^PassManager"), _))
915 .InSequence(PISequence);
917 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
918 EXPECT_CALL(CallbacksHandle,
919 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _))
920 .Times(0);
922 StringRef PipelineText = "test-transform";
923 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
924 << "Pipeline was: " << PipelineText;
925 PM.run(*M, AM);
928 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingLoopNestPasses) {
929 CallbacksHandle.registerPassInstrumentation();
930 // Non-mock instrumentation not specifically mentioned below can be ignored.
931 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
932 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
933 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
935 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
936 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
937 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
938 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _))
939 .WillOnce(DoAll(&ExtraPassHandle.invalidateLoopNest,
940 [&](LoopNest &, LoopAnalysisManager &,
941 LoopStandardAnalysisResults &,
942 LPMUpdater &) { return PreservedAnalyses::all(); }));
944 // PassInstrumentation calls should happen in-sequence, in the same order
945 // as passes/analyses are scheduled.
946 ::testing::Sequence PISequence;
947 EXPECT_CALL(CallbacksHandle,
948 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
949 .InSequence(PISequence);
950 EXPECT_CALL(
951 CallbacksHandle,
952 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
953 .InSequence(PISequence);
954 EXPECT_CALL(
955 CallbacksHandle,
956 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
957 .InSequence(PISequence);
958 EXPECT_CALL(
959 CallbacksHandle,
960 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
961 .InSequence(PISequence);
962 EXPECT_CALL(CallbacksHandle,
963 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _))
964 .InSequence(PISequence);
966 EXPECT_CALL(CallbacksHandle,
967 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
968 HasName("loop")))
969 .InSequence(PISequence);
970 EXPECT_CALL(CallbacksHandle,
971 runBeforeNonSkippedPass(
972 HasNameRegex("MockPassHandle<.*LoopNest>"), HasName("loop")))
973 .InSequence(PISequence);
974 EXPECT_CALL(
975 CallbacksHandle,
976 runAfterPassInvalidated(HasNameRegex("MockPassHandle<.*LoopNest>"), _))
977 .InSequence(PISequence);
979 EXPECT_CALL(CallbacksHandle,
980 runAfterPassInvalidated(HasNameRegex("^PassManager"), _))
981 .InSequence(PISequence);
983 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
984 EXPECT_CALL(CallbacksHandle, runAfterPassInvalidated(
985 HasNameRegex("MockPassHandle<.*Loop>"), _))
986 .Times(0);
987 EXPECT_CALL(CallbacksHandle,
988 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
989 HasName("loop"), _))
990 .Times(0);
992 StringRef PipelineText = "test-transform";
993 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
994 << "Pipeline was: " << PipelineText;
995 PM.run(*M, AM);
998 TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
999 CallbacksHandle.registerPassInstrumentation();
1000 // Non-mock instrumentation run here can safely be ignored.
1001 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1002 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1003 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
1005 // Skip the pass by returning false.
1006 EXPECT_CALL(
1007 CallbacksHandle,
1008 runBeforePass(HasNameRegex("MockPassHandle<.*Loop>"), HasName("loop")))
1009 .WillOnce(Return(false));
1011 EXPECT_CALL(CallbacksHandle,
1012 runBeforeSkippedPass(HasNameRegex("MockPassHandle<.*Loop>"),
1013 HasName("loop")))
1014 .Times(1);
1016 EXPECT_CALL(CallbacksHandle,
1017 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
1018 HasName("loop")))
1019 .WillOnce(Return(false));
1021 EXPECT_CALL(CallbacksHandle,
1022 runBeforeSkippedPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
1023 HasName("loop")))
1024 .Times(1);
1026 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
1027 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0);
1028 EXPECT_CALL(ExtraPassHandle, run(HasName("loop"), _, _, _)).Times(0);
1030 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
1031 // as well.
1032 EXPECT_CALL(CallbacksHandle, runBeforeNonSkippedPass(
1033 HasNameRegex("MockPassHandle<.*Loop>"), _))
1034 .Times(0);
1035 EXPECT_CALL(CallbacksHandle,
1036 runAfterPass(HasNameRegex("MockPassHandle<.*Loop>"), _, _))
1037 .Times(0);
1038 EXPECT_CALL(CallbacksHandle, runAfterPassInvalidated(
1039 HasNameRegex("MockPassHandle<.*Loop>"), _))
1040 .Times(0);
1041 EXPECT_CALL(
1042 CallbacksHandle,
1043 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle<.*LoopNest>"), _))
1044 .Times(0);
1045 EXPECT_CALL(CallbacksHandle,
1046 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"), _, _))
1047 .Times(0);
1048 EXPECT_CALL(
1049 CallbacksHandle,
1050 runAfterPassInvalidated(HasNameRegex("MockPassHandle<.*LoopNest>"), _))
1051 .Times(0);
1052 EXPECT_CALL(CallbacksHandle,
1053 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1054 .Times(0);
1055 EXPECT_CALL(CallbacksHandle,
1056 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1057 .Times(0);
1059 StringRef PipelineText = "test-transform";
1060 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1061 << "Pipeline was: " << PipelineText;
1062 PM.run(*M, AM);
1065 TEST_F(CGSCCCallbacksTest, Passes) {
1066 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1067 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
1068 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
1070 StringRef PipelineText = "test-transform";
1071 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1072 << "Pipeline was: " << PipelineText;
1073 PM.run(*M, AM);
1076 TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
1077 CallbacksHandle.registerPassInstrumentation();
1078 // Non-mock instrumentation not specifically mentioned below can be ignored.
1079 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1080 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1081 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
1083 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1084 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
1085 .WillOnce(WithArgs<0, 1, 2>(&getAnalysisResult));
1087 // PassInstrumentation calls should happen in-sequence, in the same order
1088 // as passes/analyses are scheduled.
1089 ::testing::Sequence PISequence;
1090 EXPECT_CALL(CallbacksHandle,
1091 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1092 .InSequence(PISequence);
1093 EXPECT_CALL(
1094 CallbacksHandle,
1095 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1096 .InSequence(PISequence);
1097 EXPECT_CALL(
1098 CallbacksHandle,
1099 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1100 .InSequence(PISequence);
1101 EXPECT_CALL(
1102 CallbacksHandle,
1103 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1104 .InSequence(PISequence);
1105 EXPECT_CALL(CallbacksHandle,
1106 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), _))
1107 .InSequence(PISequence);
1109 // Our mock pass does not invalidate IR.
1110 EXPECT_CALL(CallbacksHandle,
1111 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
1112 .Times(0);
1114 // No passes are skipped, so there should be no calls to
1115 // runBeforeSkippedPass().
1116 EXPECT_CALL(
1117 CallbacksHandle,
1118 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1119 .Times(0);
1121 StringRef PipelineText = "test-transform";
1122 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1123 << "Pipeline was: " << PipelineText;
1124 PM.run(*M, AM);
1127 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
1128 CallbacksHandle.registerPassInstrumentation();
1129 // Non-mock instrumentation not specifically mentioned below can be ignored.
1130 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1131 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1132 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
1134 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1135 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
1136 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(&PassHandle.invalidateSCC),
1137 WithArgs<0, 1, 2>(&getAnalysisResult)));
1139 // PassInstrumentation calls should happen in-sequence, in the same order
1140 // as passes/analyses are scheduled.
1141 ::testing::Sequence PISequence;
1142 EXPECT_CALL(CallbacksHandle,
1143 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1144 .InSequence(PISequence);
1145 EXPECT_CALL(
1146 CallbacksHandle,
1147 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1148 .InSequence(PISequence);
1149 EXPECT_CALL(
1150 CallbacksHandle,
1151 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1152 .InSequence(PISequence);
1153 EXPECT_CALL(
1154 CallbacksHandle,
1155 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1156 .InSequence(PISequence);
1157 EXPECT_CALL(CallbacksHandle,
1158 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
1159 .InSequence(PISequence);
1160 EXPECT_CALL(CallbacksHandle,
1161 runAfterPassInvalidated(HasNameRegex("^PassManager"), _))
1162 .InSequence(PISequence);
1164 // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
1165 EXPECT_CALL(CallbacksHandle,
1166 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), _))
1167 .Times(0);
1169 StringRef PipelineText = "test-transform";
1170 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1171 << "Pipeline was: " << PipelineText;
1172 PM.run(*M, AM);
1175 TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
1176 CallbacksHandle.registerPassInstrumentation();
1177 // Non-mock instrumentation run here can safely be ignored.
1178 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
1179 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
1180 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
1182 // Skip the pass by returning false.
1183 EXPECT_CALL(CallbacksHandle,
1184 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1185 .WillOnce(Return(false));
1187 EXPECT_CALL(
1188 CallbacksHandle,
1189 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1190 .Times(1);
1192 // neither Analysis nor Pass are called.
1193 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0);
1194 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0);
1196 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
1197 // as well.
1198 EXPECT_CALL(CallbacksHandle,
1199 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
1200 .Times(0);
1201 EXPECT_CALL(CallbacksHandle,
1202 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
1203 .Times(0);
1204 EXPECT_CALL(CallbacksHandle,
1205 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
1206 .Times(0);
1207 EXPECT_CALL(CallbacksHandle,
1208 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1209 .Times(0);
1210 EXPECT_CALL(CallbacksHandle,
1211 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
1212 .Times(0);
1214 StringRef PipelineText = "test-transform";
1215 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1216 << "Pipeline was: " << PipelineText;
1217 PM.run(*M, AM);
1220 /// Test parsing of the names of analysis utilities for our mock analysis
1221 /// for all IRUnits.
1223 /// We first require<>, then invalidate<> it, expecting the analysis to be run
1224 /// once and subsequently invalidated.
1225 TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
1226 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
1227 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
1229 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1230 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1231 << "Pipeline was: " << PipelineText;
1232 PM.run(*M, AM);
1235 TEST_F(CGSCCCallbacksTest, PassUtilities) {
1236 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
1237 EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
1239 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1240 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1241 << "Pipeline was: " << PipelineText;
1242 PM.run(*M, AM);
1245 TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
1246 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
1247 EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
1249 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1250 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1251 << "Pipeline was: " << PipelineText;
1252 PM.run(*M, AM);
1255 TEST_F(LoopCallbacksTest, PassUtilities) {
1256 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
1257 EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
1259 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
1261 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1262 << "Pipeline was: " << PipelineText;
1263 PM.run(*M, AM);
1266 /// Test parsing of the top-level pipeline.
1268 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
1269 /// from PassBuilder if it encounters an unknown pipeline entry at the top level
1270 /// (i.e., the first entry on the pipeline).
1271 /// This test parses a pipeline named 'another-pipeline', whose only elements
1272 /// may be the test-transform pass or the analysis utilities
1273 TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
1274 PB.registerParseTopLevelPipelineCallback(
1275 [this](ModulePassManager &MPM,
1276 ArrayRef<PassBuilder::PipelineElement> Pipeline) {
1277 auto &FirstName = Pipeline.front().Name;
1278 auto &InnerPipeline = Pipeline.front().InnerPipeline;
1279 if (FirstName == "another-pipeline") {
1280 for (auto &E : InnerPipeline) {
1281 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", E.Name,
1282 PM))
1283 continue;
1285 if (E.Name == "test-transform") {
1286 PM.addPass(PassHandle.getPass());
1287 continue;
1289 return false;
1292 return true;
1295 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
1296 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
1297 .WillOnce(&getAnalysisResult);
1298 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
1300 StringRef PipelineText =
1301 "another-pipeline(test-transform,invalidate<test-analysis>)";
1302 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded())
1303 << "Pipeline was: " << PipelineText;
1304 PM.run(*M, AM);
1306 /// Test the negative case
1307 PipelineText = "another-pipeline(instcombine)";
1308 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Failed())
1309 << "Pipeline was: " << PipelineText;
1311 } // end anonymous namespace