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