1 //===- unittests/IR/PassBuilderCallbacksTest.cpp - PB Callback Tests --===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Testing/Support/Error.h"
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>
28 using testing::AnyNumber
;
31 using testing::Return
;
32 using testing::WithArgs
;
35 /// A CRTP base for analysis mock handles
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
{
46 class Analysis
: public AnalysisInfoMixin
<Analysis
> {
47 friend AnalysisInfoMixin
<Analysis
>;
48 friend MockAnalysisHandleBase
;
49 static AnalysisKey Key
;
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!");
60 friend MockAnalysisHandleBase
;
64 Result(DerivedT
&Handle
) : Handle(&Handle
) {}
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
>(); }
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.)
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
{
123 class Pass
: public PassInfoMixin
<Pass
> {
124 friend MockPassHandleBase
;
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!");
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)); }
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.)
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
158 template <typename IRUnitT
> struct MockPassHandle
;
160 struct MockPassHandle
<Loop
>
161 : MockPassHandleBase
<MockPassHandle
<Loop
>, Loop
, LoopAnalysisManager
,
162 LoopStandardAnalysisResults
&, LPMUpdater
&> {
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(); }
175 struct MockPassHandle
<LoopNest
>
176 : MockPassHandleBase
<MockPassHandle
<LoopNest
>, LoopNest
,
177 LoopAnalysisManager
, LoopStandardAnalysisResults
&,
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(); }
191 struct MockPassHandle
<Function
>
192 : MockPassHandleBase
<MockPassHandle
<Function
>, Function
> {
193 MOCK_METHOD2(run
, PreservedAnalyses(Function
&, FunctionAnalysisManager
&));
195 MockPassHandle() { setDefaults(); }
199 struct MockPassHandle
<LazyCallGraph::SCC
>
200 : MockPassHandleBase
<MockPassHandle
<LazyCallGraph::SCC
>, LazyCallGraph::SCC
,
201 CGSCCAnalysisManager
, LazyCallGraph
&,
202 CGSCCUpdateResult
&> {
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(); }
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
;
228 struct MockAnalysisHandle
<Loop
>
229 : MockAnalysisHandleBase
<MockAnalysisHandle
<Loop
>, Loop
,
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(); }
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(); }
254 struct MockAnalysisHandle
<LazyCallGraph::SCC
>
255 : MockAnalysisHandleBase
<MockAnalysisHandle
<LazyCallGraph::SCC
>,
256 LazyCallGraph::SCC
, CGSCCAnalysisManager
,
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(); }
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
) {
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();
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
) << "'";
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.
383 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName
)))
386 *this, runBeforeSkippedPass(Not(HasNameRegex("Mock")), HasName(IRName
)))
388 EXPECT_CALL(*this, runBeforeNonSkippedPass(Not(HasNameRegex("Mock")),
392 runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName
), _
))
395 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName
)))
398 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName
)))
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
{
421 using IRUnitT
= TestIRUnitT
;
422 using AnalysisManagerT
= AnalysisManager
<TestIRUnitT
, ExtraAnalysisArgTs
...>;
424 PassManager
<TestIRUnitT
, AnalysisManagerT
, ExtraPassArgTs
...>;
425 using AnalysisT
= typename MockAnalysisHandle
<IRUnitT
>::Analysis
;
428 std::unique_ptr
<Module
> M
;
430 MockPassInstrumentationCallbacks CallbacksHandle
;
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()
453 "declare void @bar()\n"
454 "define void @foo(i32 %n) {\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"
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
))
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());
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
;
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
);
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().
572 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
575 StringRef PipelineText
= "test-transform";
576 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
577 << "Pipeline was: " << PipelineText
;
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"), _
))
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"), _
))
605 EXPECT_CALL(CallbacksHandle
,
606 runAfterPass(HasNameRegex("MockPassHandle"), _
, _
))
608 EXPECT_CALL(CallbacksHandle
,
609 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
611 EXPECT_CALL(CallbacksHandle
,
612 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
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
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"), _
))
629 runBeforeNonSkippedPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _
))
631 EXPECT_CALL(CallbacksHandle
,
632 runBeforeNonSkippedPass(
633 HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _
))
637 runBeforeNonSkippedPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _
))
641 runBeforeNonSkippedPass(HasNameRegex("FunctionToLoopPassAdaptor"), _
))
644 // The `runAfterPass` checks are the same as these of
645 // `runBeforeNonSkippedPass`.
646 EXPECT_CALL(CallbacksHandle
, runAfterPass(HasNameRegex("PassManager"), _
, _
))
648 EXPECT_CALL(CallbacksHandle
,
649 runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _
, _
))
653 runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _
, _
))
655 EXPECT_CALL(CallbacksHandle
,
656 runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _
, _
))
658 EXPECT_CALL(CallbacksHandle
,
659 runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _
, _
))
662 // Ignore analyses introduced by adaptor passes.
663 EXPECT_CALL(CallbacksHandle
,
664 runBeforeAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _
))
666 EXPECT_CALL(CallbacksHandle
,
667 runAfterAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _
))
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());
680 PB
.registerPipelineParsingCallback(
681 [](StringRef Name
, LoopPassManager
&LPM
,
682 ArrayRef
<PassBuilder::PipelineElement
>) {
683 if (Name
== "test-transform") {
684 LPM
.addPass(MockPassHandle
<Loop
>().getPass());
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
;
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
;
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
);
725 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
726 .InSequence(PISequence
);
729 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
730 .InSequence(PISequence
);
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().
743 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
746 // Our mock pass does not invalidate IR.
747 EXPECT_CALL(CallbacksHandle
,
748 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
751 StringRef PipelineText
= "test-transform";
752 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
753 << "Pipeline was: " << PipelineText
;
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));
770 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
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
778 EXPECT_CALL(CallbacksHandle
,
779 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _
))
781 EXPECT_CALL(CallbacksHandle
,
782 runAfterPass(HasNameRegex("MockPassHandle"), _
, _
))
784 EXPECT_CALL(CallbacksHandle
,
785 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
787 EXPECT_CALL(CallbacksHandle
,
788 runAfterPass(HasNameRegex("MockPassHandle"), _
, _
))
790 EXPECT_CALL(CallbacksHandle
,
791 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
793 EXPECT_CALL(CallbacksHandle
,
794 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
797 StringRef PipelineText
= "test-transform";
798 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
799 << "Pipeline was: " << PipelineText
;
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
;
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
);
835 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
836 .InSequence(PISequence
);
839 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
840 .InSequence(PISequence
);
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>"),
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>"),
860 .InSequence(PISequence
);
862 // Our mock pass does not invalidate IR.
863 EXPECT_CALL(CallbacksHandle
,
864 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
867 // No passes are skipped, so there should be no calls to
868 // runBeforeSkippedPass().
871 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
874 StringRef PipelineText
= "test-transform";
875 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
876 << "Pipeline was: " << PipelineText
;
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
);
900 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
901 .InSequence(PISequence
);
904 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
905 .InSequence(PISequence
);
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"), _
))
922 StringRef PipelineText
= "test-transform";
923 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
924 << "Pipeline was: " << PipelineText
;
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
);
952 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
953 .InSequence(PISequence
);
956 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
957 .InSequence(PISequence
);
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>"),
969 .InSequence(PISequence
);
970 EXPECT_CALL(CallbacksHandle
,
971 runBeforeNonSkippedPass(
972 HasNameRegex("MockPassHandle<.*LoopNest>"), HasName("loop")))
973 .InSequence(PISequence
);
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>"), _
))
987 EXPECT_CALL(CallbacksHandle
,
988 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
992 StringRef PipelineText
= "test-transform";
993 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
994 << "Pipeline was: " << PipelineText
;
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.
1008 runBeforePass(HasNameRegex("MockPassHandle<.*Loop>"), HasName("loop")))
1009 .WillOnce(Return(false));
1011 EXPECT_CALL(CallbacksHandle
,
1012 runBeforeSkippedPass(HasNameRegex("MockPassHandle<.*Loop>"),
1016 EXPECT_CALL(CallbacksHandle
,
1017 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
1019 .WillOnce(Return(false));
1021 EXPECT_CALL(CallbacksHandle
,
1022 runBeforeSkippedPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
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
1032 EXPECT_CALL(CallbacksHandle
, runBeforeNonSkippedPass(
1033 HasNameRegex("MockPassHandle<.*Loop>"), _
))
1035 EXPECT_CALL(CallbacksHandle
,
1036 runAfterPass(HasNameRegex("MockPassHandle<.*Loop>"), _
, _
))
1038 EXPECT_CALL(CallbacksHandle
, runAfterPassInvalidated(
1039 HasNameRegex("MockPassHandle<.*Loop>"), _
))
1043 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle<.*LoopNest>"), _
))
1045 EXPECT_CALL(CallbacksHandle
,
1046 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"), _
, _
))
1050 runAfterPassInvalidated(HasNameRegex("MockPassHandle<.*LoopNest>"), _
))
1052 EXPECT_CALL(CallbacksHandle
,
1053 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
1055 EXPECT_CALL(CallbacksHandle
,
1056 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
1059 StringRef PipelineText
= "test-transform";
1060 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1061 << "Pipeline was: " << PipelineText
;
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
;
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
);
1095 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1096 .InSequence(PISequence
);
1099 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1100 .InSequence(PISequence
);
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"), _
))
1114 // No passes are skipped, so there should be no calls to
1115 // runBeforeSkippedPass().
1118 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1121 StringRef PipelineText
= "test-transform";
1122 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1123 << "Pipeline was: " << PipelineText
;
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
);
1147 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1148 .InSequence(PISequence
);
1151 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1152 .InSequence(PISequence
);
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)"), _
))
1169 StringRef PipelineText
= "test-transform";
1170 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1171 << "Pipeline was: " << PipelineText
;
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));
1189 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
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
1198 EXPECT_CALL(CallbacksHandle
,
1199 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _
))
1201 EXPECT_CALL(CallbacksHandle
,
1202 runAfterPass(HasNameRegex("MockPassHandle"), _
, _
))
1204 EXPECT_CALL(CallbacksHandle
,
1205 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
1207 EXPECT_CALL(CallbacksHandle
,
1208 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
1210 EXPECT_CALL(CallbacksHandle
,
1211 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
1214 StringRef PipelineText
= "test-transform";
1215 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1216 << "Pipeline was: " << PipelineText
;
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
;
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
;
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
;
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
;
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
,
1285 if (E
.Name
== "test-transform") {
1286 PM
.addPass(PassHandle
.getPass());
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
;
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