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
<Loop
>() { 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
<Function
>() { 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
<LazyCallGraph::SCC
>() { 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
<Module
>() { 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 llvm::Any
&WrappedIR
) {
294 if (any_isa
<const Module
*>(WrappedIR
))
295 return any_cast
<const Module
*>(WrappedIR
)->getName().str();
296 if (any_isa
<const Function
*>(WrappedIR
))
297 return any_cast
<const Function
*>(WrappedIR
)->getName().str();
298 if (any_isa
<const Loop
*>(WrappedIR
))
299 return any_cast
<const Loop
*>(WrappedIR
)->getName().str();
300 if (any_isa
<const LoopNest
*>(WrappedIR
))
301 return any_cast
<const LoopNest
*>(WrappedIR
)->getName().str();
302 if (any_isa
<const LazyCallGraph::SCC
*>(WrappedIR
))
303 return any_cast
<const LazyCallGraph::SCC
*>(WrappedIR
)->getName();
306 /// Define a custom matcher for objects which support a 'getName' method.
308 /// LLVM often has IR objects or analysis objects which expose a name
309 /// and in tests it is convenient to match these by name for readability.
310 /// Usually, this name is either a StringRef or a plain std::string. This
311 /// matcher supports any type exposing a getName() method of this form whose
312 /// return value is compatible with an std::ostream. For StringRef, this uses
313 /// the shift operator defined above.
315 /// It should be used as:
317 /// HasName("my_function")
319 /// No namespace or other qualification is required.
320 MATCHER_P(HasName
, Name
, "") {
321 *result_listener
<< "has name '" << getName(arg
) << "'";
322 return Name
== getName(arg
);
325 MATCHER_P(HasNameRegex
, Name
, "") {
326 *result_listener
<< "has name '" << getName(arg
) << "'";
328 return r
.match(getName(arg
));
331 struct MockPassInstrumentationCallbacks
{
332 PassInstrumentationCallbacks Callbacks
;
334 MockPassInstrumentationCallbacks() {
335 ON_CALL(*this, runBeforePass(_
, _
)).WillByDefault(Return(true));
337 MOCK_METHOD2(runBeforePass
, bool(StringRef PassID
, llvm::Any
));
338 MOCK_METHOD2(runBeforeSkippedPass
, void(StringRef PassID
, llvm::Any
));
339 MOCK_METHOD2(runBeforeNonSkippedPass
, void(StringRef PassID
, llvm::Any
));
340 MOCK_METHOD3(runAfterPass
,
341 void(StringRef PassID
, llvm::Any
, const PreservedAnalyses
&PA
));
342 MOCK_METHOD2(runAfterPassInvalidated
,
343 void(StringRef PassID
, const PreservedAnalyses
&PA
));
344 MOCK_METHOD2(runBeforeAnalysis
, void(StringRef PassID
, llvm::Any
));
345 MOCK_METHOD2(runAfterAnalysis
, void(StringRef PassID
, llvm::Any
));
347 void registerPassInstrumentation() {
348 Callbacks
.registerShouldRunOptionalPassCallback(
349 [this](StringRef P
, llvm::Any IR
) {
350 return this->runBeforePass(P
, IR
);
352 Callbacks
.registerBeforeSkippedPassCallback(
353 [this](StringRef P
, llvm::Any IR
) {
354 this->runBeforeSkippedPass(P
, IR
);
356 Callbacks
.registerBeforeNonSkippedPassCallback(
357 [this](StringRef P
, llvm::Any IR
) {
358 this->runBeforeNonSkippedPass(P
, IR
);
360 Callbacks
.registerAfterPassCallback(
361 [this](StringRef P
, llvm::Any IR
, const PreservedAnalyses
&PA
) {
362 this->runAfterPass(P
, IR
, PA
);
364 Callbacks
.registerAfterPassInvalidatedCallback(
365 [this](StringRef P
, const PreservedAnalyses
&PA
) {
366 this->runAfterPassInvalidated(P
, PA
);
368 Callbacks
.registerBeforeAnalysisCallback([this](StringRef P
, llvm::Any IR
) {
369 return this->runBeforeAnalysis(P
, IR
);
371 Callbacks
.registerAfterAnalysisCallback(
372 [this](StringRef P
, llvm::Any IR
) { this->runAfterAnalysis(P
, IR
); });
375 void ignoreNonMockPassInstrumentation(StringRef IRName
) {
376 // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
377 // parts of a pipeline that we do not care about (e.g. various passes added
378 // by default by PassBuilder - Verifier pass etc).
379 // Make sure to avoid ignoring Mock passes/analysis, we definitely want
380 // to check these explicitly.
382 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName
)))
385 *this, runBeforeSkippedPass(Not(HasNameRegex("Mock")), HasName(IRName
)))
387 EXPECT_CALL(*this, runBeforeNonSkippedPass(Not(HasNameRegex("Mock")),
391 runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName
), _
))
394 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName
)))
397 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName
)))
402 template <typename IRUnitT
>
403 using ExtraMockPassHandle
=
404 std::conditional_t
<std::is_same
<IRUnitT
, Loop
>::value
,
405 MockPassHandle
<LoopNest
>, MockPassHandle
<IRUnitT
>>;
407 template <typename PassManagerT
> class PassBuilderCallbacksTest
;
409 /// This test fixture is shared between all the actual tests below and
410 /// takes care of setting up appropriate defaults.
412 /// The template specialization serves to extract the IRUnit and AM types from
413 /// the given PassManagerT.
414 template <typename TestIRUnitT
, typename
... ExtraPassArgTs
,
415 typename
... ExtraAnalysisArgTs
>
416 class PassBuilderCallbacksTest
<PassManager
<
417 TestIRUnitT
, AnalysisManager
<TestIRUnitT
, ExtraAnalysisArgTs
...>,
418 ExtraPassArgTs
...>> : public testing::Test
{
420 using IRUnitT
= TestIRUnitT
;
421 using AnalysisManagerT
= AnalysisManager
<TestIRUnitT
, ExtraAnalysisArgTs
...>;
423 PassManager
<TestIRUnitT
, AnalysisManagerT
, ExtraPassArgTs
...>;
424 using AnalysisT
= typename MockAnalysisHandle
<IRUnitT
>::Analysis
;
427 std::unique_ptr
<Module
> M
;
429 MockPassInstrumentationCallbacks CallbacksHandle
;
432 ModulePassManager PM
;
433 LoopAnalysisManager LAM
;
434 FunctionAnalysisManager FAM
;
435 CGSCCAnalysisManager CGAM
;
436 ModuleAnalysisManager AM
;
438 MockPassHandle
<IRUnitT
> PassHandle
;
439 ExtraMockPassHandle
<IRUnitT
> ExtraPassHandle
;
441 MockAnalysisHandle
<IRUnitT
> AnalysisHandle
;
443 static PreservedAnalyses
getAnalysisResult(IRUnitT
&U
, AnalysisManagerT
&AM
,
444 ExtraAnalysisArgTs
&&... Args
) {
445 (void)AM
.template getResult
<AnalysisT
>(
446 U
, std::forward
<ExtraAnalysisArgTs
>(Args
)...);
447 return PreservedAnalyses::all();
450 PassBuilderCallbacksTest()
452 "declare void @bar()\n"
453 "define void @foo(i32 %n) {\n"
457 " %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
458 " %iv.next = add i32 %iv, 1\n"
459 " tail call void @bar()\n"
460 " %cmp = icmp eq i32 %iv, %n\n"
461 " br i1 %cmp, label %exit, label %loop\n"
466 PB(nullptr, PipelineTuningOptions(), None
, &CallbacksHandle
.Callbacks
),
467 PM(), LAM(), FAM(), CGAM(), AM() {
469 EXPECT_TRUE(&CallbacksHandle
.Callbacks
==
470 PB
.getPassInstrumentationCallbacks());
472 /// Register a callback for analysis registration.
474 /// The callback is a function taking a reference to an AnalyisManager
475 /// object. When called, the callee gets to register its own analyses with
476 /// this PassBuilder instance.
477 PB
.registerAnalysisRegistrationCallback([this](AnalysisManagerT
&AM
) {
478 // Register our mock analysis
479 AM
.registerPass([this] { return AnalysisHandle
.getAnalysis(); });
482 /// Register a callback for pipeline parsing.
484 /// During parsing of a textual pipeline, the PassBuilder will call these
485 /// callbacks for each encountered pass name that it does not know. This
486 /// includes both simple pass names as well as names of sub-pipelines. In
487 /// the latter case, the InnerPipeline is not empty.
488 PB
.registerPipelineParsingCallback(
489 [this](StringRef Name
, PassManagerT
&PM
,
490 ArrayRef
<PassBuilder::PipelineElement
> InnerPipeline
) {
491 /// Handle parsing of the names of analysis utilities such as
492 /// require<test-analysis> and invalidate<test-analysis> for our
493 /// analysis mock handle
494 if (parseAnalysisUtilityPasses
<AnalysisT
>("test-analysis", Name
, PM
))
497 /// Parse the name of our pass mock handle
498 if (Name
== "test-transform") {
499 PM
.addPass(PassHandle
.getPass());
500 if (std::is_same
<IRUnitT
, Loop
>::value
)
501 PM
.addPass(ExtraPassHandle
.getPass());
507 /// Register builtin analyses and cross-register the analysis proxies
508 PB
.registerModuleAnalyses(AM
);
509 PB
.registerCGSCCAnalyses(CGAM
);
510 PB
.registerFunctionAnalyses(FAM
);
511 PB
.registerLoopAnalyses(LAM
);
512 PB
.crossRegisterProxies(LAM
, FAM
, CGAM
, AM
);
516 using ModuleCallbacksTest
= PassBuilderCallbacksTest
<ModulePassManager
>;
517 using CGSCCCallbacksTest
= PassBuilderCallbacksTest
<CGSCCPassManager
>;
518 using FunctionCallbacksTest
= PassBuilderCallbacksTest
<FunctionPassManager
>;
519 using LoopCallbacksTest
= PassBuilderCallbacksTest
<LoopPassManager
>;
521 /// Test parsing of the name of our mock pass for all IRUnits.
523 /// The pass should by default run our mock analysis and then preserve it.
524 TEST_F(ModuleCallbacksTest
, Passes
) {
525 EXPECT_CALL(AnalysisHandle
, run(HasName("<string>"), _
));
526 EXPECT_CALL(PassHandle
, run(HasName("<string>"), _
))
527 .WillOnce(&getAnalysisResult
);
529 StringRef PipelineText
= "test-transform";
530 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
531 << "Pipeline was: " << PipelineText
;
536 TEST_F(ModuleCallbacksTest
, InstrumentedPasses
) {
537 EXPECT_CALL(AnalysisHandle
, run(HasName("<string>"), _
));
538 EXPECT_CALL(PassHandle
, run(HasName("<string>"), _
))
539 .WillOnce(&getAnalysisResult
);
541 CallbacksHandle
.registerPassInstrumentation();
542 // Non-mock instrumentation not specifically mentioned below can be ignored.
543 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
545 // PassInstrumentation calls should happen in-sequence, in the same order
546 // as passes/analyses are scheduled.
547 ::testing::Sequence PISequence
;
548 EXPECT_CALL(CallbacksHandle
, runBeforePass(HasNameRegex("MockPassHandle"),
549 HasName("<string>")))
550 .InSequence(PISequence
);
551 EXPECT_CALL(CallbacksHandle
,
552 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"),
553 HasName("<string>")))
554 .InSequence(PISequence
);
555 EXPECT_CALL(CallbacksHandle
,
556 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
557 HasName("<string>")))
558 .InSequence(PISequence
);
561 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
562 .InSequence(PISequence
);
563 EXPECT_CALL(CallbacksHandle
, runAfterPass(HasNameRegex("MockPassHandle"),
564 HasName("<string>"), _
))
565 .InSequence(PISequence
);
567 // No passes are skipped, so there should be no calls to
568 // runBeforeSkippedPass().
571 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
574 StringRef PipelineText
= "test-transform";
575 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
576 << "Pipeline was: " << PipelineText
;
581 TEST_F(ModuleCallbacksTest
, InstrumentedSkippedPasses
) {
582 CallbacksHandle
.registerPassInstrumentation();
583 // Non-mock instrumentation run here can safely be ignored.
584 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
585 CallbacksHandle
.ignoreNonMockPassInstrumentation("foo");
587 // Skip all passes by returning false. Pass managers and adaptor passes are
588 // also passes that observed by the callbacks.
589 EXPECT_CALL(CallbacksHandle
, runBeforePass(_
, _
))
590 .WillRepeatedly(Return(false));
592 EXPECT_CALL(CallbacksHandle
,
593 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), _
))
596 EXPECT_CALL(AnalysisHandle
, run(HasName("<string>"), _
)).Times(0);
597 EXPECT_CALL(PassHandle
, run(HasName("<string>"), _
)).Times(0);
599 // As the pass is skipped there is no nonskippedpass/afterPass,
600 // beforeAnalysis/afterAnalysis as well.
601 EXPECT_CALL(CallbacksHandle
,
602 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _
))
604 EXPECT_CALL(CallbacksHandle
,
605 runAfterPass(HasNameRegex("MockPassHandle"), _
, _
))
607 EXPECT_CALL(CallbacksHandle
,
608 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
610 EXPECT_CALL(CallbacksHandle
,
611 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
614 // Order is important here. `Adaptor` expectations should be checked first
615 // because the its argument contains 'PassManager' (for example:
616 // ModuleToFunctionPassAdaptor{{.*}}PassManager{{.*}}). Check
617 // `runBeforeNonSkippedPass` and `runAfterPass` to show that they are not
620 // Pass managers are not ignored.
621 // 5 = (1) ModulePassManager + (2) FunctionPassMangers + (1) LoopPassManager +
622 // (1) CGSCCPassManager
623 EXPECT_CALL(CallbacksHandle
,
624 runBeforeNonSkippedPass(HasNameRegex("PassManager"), _
))
628 runBeforeNonSkippedPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _
))
630 EXPECT_CALL(CallbacksHandle
,
631 runBeforeNonSkippedPass(
632 HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _
))
636 runBeforeNonSkippedPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _
))
640 runBeforeNonSkippedPass(HasNameRegex("FunctionToLoopPassAdaptor"), _
))
643 // The `runAfterPass` checks are the same as these of
644 // `runBeforeNonSkippedPass`.
645 EXPECT_CALL(CallbacksHandle
, runAfterPass(HasNameRegex("PassManager"), _
, _
))
647 EXPECT_CALL(CallbacksHandle
,
648 runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _
, _
))
652 runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _
, _
))
654 EXPECT_CALL(CallbacksHandle
,
655 runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _
, _
))
657 EXPECT_CALL(CallbacksHandle
,
658 runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _
, _
))
661 // Ignore analyses introduced by adaptor passes.
662 EXPECT_CALL(CallbacksHandle
,
663 runBeforeAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _
))
665 EXPECT_CALL(CallbacksHandle
,
666 runAfterAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _
))
669 // Register Funtion and Loop version of "test-transform" for testing
670 PB
.registerPipelineParsingCallback(
671 [](StringRef Name
, FunctionPassManager
&FPM
,
672 ArrayRef
<PassBuilder::PipelineElement
>) {
673 if (Name
== "test-transform") {
674 FPM
.addPass(MockPassHandle
<Function
>().getPass());
679 PB
.registerPipelineParsingCallback(
680 [](StringRef Name
, LoopPassManager
&LPM
,
681 ArrayRef
<PassBuilder::PipelineElement
>) {
682 if (Name
== "test-transform") {
683 LPM
.addPass(MockPassHandle
<Loop
>().getPass());
689 StringRef PipelineText
= "test-transform,function(test-transform),cgscc("
690 "function(loop(test-transform)))";
691 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
692 << "Pipeline was: " << PipelineText
;
697 TEST_F(FunctionCallbacksTest
, Passes
) {
698 EXPECT_CALL(AnalysisHandle
, run(HasName("foo"), _
));
699 EXPECT_CALL(PassHandle
, run(HasName("foo"), _
)).WillOnce(&getAnalysisResult
);
701 StringRef PipelineText
= "test-transform";
702 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
703 << "Pipeline was: " << PipelineText
;
707 TEST_F(FunctionCallbacksTest
, InstrumentedPasses
) {
708 CallbacksHandle
.registerPassInstrumentation();
709 // Non-mock instrumentation not specifically mentioned below can be ignored.
710 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
711 CallbacksHandle
.ignoreNonMockPassInstrumentation("foo");
713 EXPECT_CALL(AnalysisHandle
, run(HasName("foo"), _
));
714 EXPECT_CALL(PassHandle
, run(HasName("foo"), _
)).WillOnce(&getAnalysisResult
);
716 // PassInstrumentation calls should happen in-sequence, in the same order
717 // as passes/analyses are scheduled.
718 ::testing::Sequence PISequence
;
719 EXPECT_CALL(CallbacksHandle
,
720 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
721 .InSequence(PISequence
);
724 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
725 .InSequence(PISequence
);
728 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
729 .InSequence(PISequence
);
732 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
733 .InSequence(PISequence
);
734 EXPECT_CALL(CallbacksHandle
,
735 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo"), _
))
736 .InSequence(PISequence
);
738 // No passes are skipped, so there should be no calls to
739 // runBeforeSkippedPass().
742 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
745 // Our mock pass does not invalidate IR.
746 EXPECT_CALL(CallbacksHandle
,
747 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
750 StringRef PipelineText
= "test-transform";
751 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
752 << "Pipeline was: " << PipelineText
;
756 TEST_F(FunctionCallbacksTest
, InstrumentedSkippedPasses
) {
757 CallbacksHandle
.registerPassInstrumentation();
758 // Non-mock instrumentation run here can safely be ignored.
759 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
760 CallbacksHandle
.ignoreNonMockPassInstrumentation("foo");
762 // Skip the pass by returning false.
763 EXPECT_CALL(CallbacksHandle
,
764 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
765 .WillOnce(Return(false));
769 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo")))
772 EXPECT_CALL(AnalysisHandle
, run(HasName("foo"), _
)).Times(0);
773 EXPECT_CALL(PassHandle
, run(HasName("foo"), _
)).Times(0);
775 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
777 EXPECT_CALL(CallbacksHandle
,
778 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _
))
780 EXPECT_CALL(CallbacksHandle
,
781 runAfterPass(HasNameRegex("MockPassHandle"), _
, _
))
783 EXPECT_CALL(CallbacksHandle
,
784 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
786 EXPECT_CALL(CallbacksHandle
,
787 runAfterPass(HasNameRegex("MockPassHandle"), _
, _
))
789 EXPECT_CALL(CallbacksHandle
,
790 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
792 EXPECT_CALL(CallbacksHandle
,
793 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
796 StringRef PipelineText
= "test-transform";
797 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
798 << "Pipeline was: " << PipelineText
;
802 TEST_F(LoopCallbacksTest
, Passes
) {
803 EXPECT_CALL(AnalysisHandle
, run(HasName("loop"), _
, _
));
804 EXPECT_CALL(PassHandle
, run(HasName("loop"), _
, _
, _
))
805 .WillOnce(WithArgs
<0, 1, 2>(&getAnalysisResult
));
806 EXPECT_CALL(ExtraPassHandle
, run(HasName("loop"), _
, _
, _
));
808 StringRef PipelineText
= "test-transform";
809 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
810 << "Pipeline was: " << PipelineText
;
814 TEST_F(LoopCallbacksTest
, InstrumentedPasses
) {
815 CallbacksHandle
.registerPassInstrumentation();
816 // Non-mock instrumentation not specifically mentioned below can be ignored.
817 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
818 CallbacksHandle
.ignoreNonMockPassInstrumentation("foo");
819 CallbacksHandle
.ignoreNonMockPassInstrumentation("loop");
821 EXPECT_CALL(AnalysisHandle
, run(HasName("loop"), _
, _
));
822 EXPECT_CALL(PassHandle
, run(HasName("loop"), _
, _
, _
))
823 .WillOnce(WithArgs
<0, 1, 2>(&getAnalysisResult
));
824 EXPECT_CALL(ExtraPassHandle
, run(HasName("loop"), _
, _
, _
));
826 // PassInstrumentation calls should happen in-sequence, in the same order
827 // as passes/analyses are scheduled.
828 ::testing::Sequence PISequence
;
829 EXPECT_CALL(CallbacksHandle
,
830 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
831 .InSequence(PISequence
);
834 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
835 .InSequence(PISequence
);
838 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
839 .InSequence(PISequence
);
842 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
843 .InSequence(PISequence
);
844 EXPECT_CALL(CallbacksHandle
,
845 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _
))
846 .InSequence(PISequence
);
848 EXPECT_CALL(CallbacksHandle
,
849 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
851 .InSequence(PISequence
);
852 EXPECT_CALL(CallbacksHandle
,
853 runBeforeNonSkippedPass(
854 HasNameRegex("MockPassHandle<.*LoopNest>"), HasName("loop")))
855 .InSequence(PISequence
);
856 EXPECT_CALL(CallbacksHandle
,
857 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
859 .InSequence(PISequence
);
861 // Our mock pass does not invalidate IR.
862 EXPECT_CALL(CallbacksHandle
,
863 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
866 // No passes are skipped, so there should be no calls to
867 // runBeforeSkippedPass().
870 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
873 StringRef PipelineText
= "test-transform";
874 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
875 << "Pipeline was: " << PipelineText
;
879 TEST_F(LoopCallbacksTest
, InstrumentedInvalidatingPasses
) {
880 CallbacksHandle
.registerPassInstrumentation();
881 // Non-mock instrumentation not specifically mentioned below can be ignored.
882 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
883 CallbacksHandle
.ignoreNonMockPassInstrumentation("foo");
884 CallbacksHandle
.ignoreNonMockPassInstrumentation("loop");
886 EXPECT_CALL(AnalysisHandle
, run(HasName("loop"), _
, _
));
887 EXPECT_CALL(PassHandle
, run(HasName("loop"), _
, _
, _
))
888 .WillOnce(DoAll(WithArgs
<0, 1, 2, 3>(&PassHandle
.invalidateLoop
),
889 WithArgs
<0, 1, 2>(&getAnalysisResult
)));
891 // PassInstrumentation calls should happen in-sequence, in the same order
892 // as passes/analyses are scheduled.
893 ::testing::Sequence PISequence
;
894 EXPECT_CALL(CallbacksHandle
,
895 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
896 .InSequence(PISequence
);
899 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
900 .InSequence(PISequence
);
903 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
904 .InSequence(PISequence
);
907 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
908 .InSequence(PISequence
);
909 EXPECT_CALL(CallbacksHandle
,
910 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
911 .InSequence(PISequence
);
912 EXPECT_CALL(CallbacksHandle
,
913 runAfterPassInvalidated(HasNameRegex("^PassManager"), _
))
914 .InSequence(PISequence
);
916 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
917 EXPECT_CALL(CallbacksHandle
,
918 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _
))
921 StringRef PipelineText
= "test-transform";
922 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
923 << "Pipeline was: " << PipelineText
;
927 TEST_F(LoopCallbacksTest
, InstrumentedInvalidatingLoopNestPasses
) {
928 CallbacksHandle
.registerPassInstrumentation();
929 // Non-mock instrumentation not specifically mentioned below can be ignored.
930 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
931 CallbacksHandle
.ignoreNonMockPassInstrumentation("foo");
932 CallbacksHandle
.ignoreNonMockPassInstrumentation("loop");
934 EXPECT_CALL(AnalysisHandle
, run(HasName("loop"), _
, _
));
935 EXPECT_CALL(PassHandle
, run(HasName("loop"), _
, _
, _
))
936 .WillOnce(WithArgs
<0, 1, 2>(&getAnalysisResult
));
937 EXPECT_CALL(ExtraPassHandle
, run(HasName("loop"), _
, _
, _
))
938 .WillOnce(DoAll(&ExtraPassHandle
.invalidateLoopNest
,
939 [&](LoopNest
&, LoopAnalysisManager
&,
940 LoopStandardAnalysisResults
&,
941 LPMUpdater
&) { return PreservedAnalyses::all(); }));
943 // PassInstrumentation calls should happen in-sequence, in the same order
944 // as passes/analyses are scheduled.
945 ::testing::Sequence PISequence
;
946 EXPECT_CALL(CallbacksHandle
,
947 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
948 .InSequence(PISequence
);
951 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop")))
952 .InSequence(PISequence
);
955 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
956 .InSequence(PISequence
);
959 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
960 .InSequence(PISequence
);
961 EXPECT_CALL(CallbacksHandle
,
962 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _
))
963 .InSequence(PISequence
);
965 EXPECT_CALL(CallbacksHandle
,
966 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
968 .InSequence(PISequence
);
969 EXPECT_CALL(CallbacksHandle
,
970 runBeforeNonSkippedPass(
971 HasNameRegex("MockPassHandle<.*LoopNest>"), HasName("loop")))
972 .InSequence(PISequence
);
975 runAfterPassInvalidated(HasNameRegex("MockPassHandle<.*LoopNest>"), _
))
976 .InSequence(PISequence
);
978 EXPECT_CALL(CallbacksHandle
,
979 runAfterPassInvalidated(HasNameRegex("^PassManager"), _
))
980 .InSequence(PISequence
);
982 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
983 EXPECT_CALL(CallbacksHandle
, runAfterPassInvalidated(
984 HasNameRegex("MockPassHandle<.*Loop>"), _
))
986 EXPECT_CALL(CallbacksHandle
,
987 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
991 StringRef PipelineText
= "test-transform";
992 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
993 << "Pipeline was: " << PipelineText
;
997 TEST_F(LoopCallbacksTest
, InstrumentedSkippedPasses
) {
998 CallbacksHandle
.registerPassInstrumentation();
999 // Non-mock instrumentation run here can safely be ignored.
1000 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
1001 CallbacksHandle
.ignoreNonMockPassInstrumentation("foo");
1002 CallbacksHandle
.ignoreNonMockPassInstrumentation("loop");
1004 // Skip the pass by returning false.
1007 runBeforePass(HasNameRegex("MockPassHandle<.*Loop>"), HasName("loop")))
1008 .WillOnce(Return(false));
1010 EXPECT_CALL(CallbacksHandle
,
1011 runBeforeSkippedPass(HasNameRegex("MockPassHandle<.*Loop>"),
1015 EXPECT_CALL(CallbacksHandle
,
1016 runBeforePass(HasNameRegex("MockPassHandle<.*LoopNest>"),
1018 .WillOnce(Return(false));
1020 EXPECT_CALL(CallbacksHandle
,
1021 runBeforeSkippedPass(HasNameRegex("MockPassHandle<.*LoopNest>"),
1025 EXPECT_CALL(AnalysisHandle
, run(HasName("loop"), _
, _
)).Times(0);
1026 EXPECT_CALL(PassHandle
, run(HasName("loop"), _
, _
, _
)).Times(0);
1027 EXPECT_CALL(ExtraPassHandle
, run(HasName("loop"), _
, _
, _
)).Times(0);
1029 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
1031 EXPECT_CALL(CallbacksHandle
, runBeforeNonSkippedPass(
1032 HasNameRegex("MockPassHandle<.*Loop>"), _
))
1034 EXPECT_CALL(CallbacksHandle
,
1035 runAfterPass(HasNameRegex("MockPassHandle<.*Loop>"), _
, _
))
1037 EXPECT_CALL(CallbacksHandle
, runAfterPassInvalidated(
1038 HasNameRegex("MockPassHandle<.*Loop>"), _
))
1042 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle<.*LoopNest>"), _
))
1044 EXPECT_CALL(CallbacksHandle
,
1045 runAfterPass(HasNameRegex("MockPassHandle<.*LoopNest>"), _
, _
))
1049 runAfterPassInvalidated(HasNameRegex("MockPassHandle<.*LoopNest>"), _
))
1051 EXPECT_CALL(CallbacksHandle
,
1052 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
1054 EXPECT_CALL(CallbacksHandle
,
1055 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
1058 StringRef PipelineText
= "test-transform";
1059 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1060 << "Pipeline was: " << PipelineText
;
1064 TEST_F(CGSCCCallbacksTest
, Passes
) {
1065 EXPECT_CALL(AnalysisHandle
, run(HasName("(foo)"), _
, _
));
1066 EXPECT_CALL(PassHandle
, run(HasName("(foo)"), _
, _
, _
))
1067 .WillOnce(WithArgs
<0, 1, 2>(&getAnalysisResult
));
1069 StringRef PipelineText
= "test-transform";
1070 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1071 << "Pipeline was: " << PipelineText
;
1075 TEST_F(CGSCCCallbacksTest
, InstrumentedPasses
) {
1076 CallbacksHandle
.registerPassInstrumentation();
1077 // Non-mock instrumentation not specifically mentioned below can be ignored.
1078 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
1079 CallbacksHandle
.ignoreNonMockPassInstrumentation("foo");
1080 CallbacksHandle
.ignoreNonMockPassInstrumentation("(foo)");
1082 EXPECT_CALL(AnalysisHandle
, run(HasName("(foo)"), _
, _
));
1083 EXPECT_CALL(PassHandle
, run(HasName("(foo)"), _
, _
, _
))
1084 .WillOnce(WithArgs
<0, 1, 2>(&getAnalysisResult
));
1086 // PassInstrumentation calls should happen in-sequence, in the same order
1087 // as passes/analyses are scheduled.
1088 ::testing::Sequence PISequence
;
1089 EXPECT_CALL(CallbacksHandle
,
1090 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1091 .InSequence(PISequence
);
1094 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1095 .InSequence(PISequence
);
1098 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1099 .InSequence(PISequence
);
1102 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1103 .InSequence(PISequence
);
1104 EXPECT_CALL(CallbacksHandle
,
1105 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), _
))
1106 .InSequence(PISequence
);
1108 // Our mock pass does not invalidate IR.
1109 EXPECT_CALL(CallbacksHandle
,
1110 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
1113 // No passes are skipped, so there should be no calls to
1114 // runBeforeSkippedPass().
1117 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1120 StringRef PipelineText
= "test-transform";
1121 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1122 << "Pipeline was: " << PipelineText
;
1126 TEST_F(CGSCCCallbacksTest
, InstrumentedInvalidatingPasses
) {
1127 CallbacksHandle
.registerPassInstrumentation();
1128 // Non-mock instrumentation not specifically mentioned below can be ignored.
1129 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
1130 CallbacksHandle
.ignoreNonMockPassInstrumentation("foo");
1131 CallbacksHandle
.ignoreNonMockPassInstrumentation("(foo)");
1133 EXPECT_CALL(AnalysisHandle
, run(HasName("(foo)"), _
, _
));
1134 EXPECT_CALL(PassHandle
, run(HasName("(foo)"), _
, _
, _
))
1135 .WillOnce(DoAll(WithArgs
<0, 1, 2, 3>(&PassHandle
.invalidateSCC
),
1136 WithArgs
<0, 1, 2>(&getAnalysisResult
)));
1138 // PassInstrumentation calls should happen in-sequence, in the same order
1139 // as passes/analyses are scheduled.
1140 ::testing::Sequence PISequence
;
1141 EXPECT_CALL(CallbacksHandle
,
1142 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1143 .InSequence(PISequence
);
1146 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1147 .InSequence(PISequence
);
1150 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1151 .InSequence(PISequence
);
1154 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
1155 .InSequence(PISequence
);
1156 EXPECT_CALL(CallbacksHandle
,
1157 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
1158 .InSequence(PISequence
);
1159 EXPECT_CALL(CallbacksHandle
,
1160 runAfterPassInvalidated(HasNameRegex("^PassManager"), _
))
1161 .InSequence(PISequence
);
1163 // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
1164 EXPECT_CALL(CallbacksHandle
,
1165 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), _
))
1168 StringRef PipelineText
= "test-transform";
1169 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1170 << "Pipeline was: " << PipelineText
;
1174 TEST_F(CGSCCCallbacksTest
, InstrumentedSkippedPasses
) {
1175 CallbacksHandle
.registerPassInstrumentation();
1176 // Non-mock instrumentation run here can safely be ignored.
1177 CallbacksHandle
.ignoreNonMockPassInstrumentation("<string>");
1178 CallbacksHandle
.ignoreNonMockPassInstrumentation("foo");
1179 CallbacksHandle
.ignoreNonMockPassInstrumentation("(foo)");
1181 // Skip the pass by returning false.
1182 EXPECT_CALL(CallbacksHandle
,
1183 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1184 .WillOnce(Return(false));
1188 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
1191 // neither Analysis nor Pass are called.
1192 EXPECT_CALL(AnalysisHandle
, run(HasName("(foo)"), _
, _
)).Times(0);
1193 EXPECT_CALL(PassHandle
, run(HasName("(foo)"), _
, _
, _
)).Times(0);
1195 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
1197 EXPECT_CALL(CallbacksHandle
,
1198 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _
))
1200 EXPECT_CALL(CallbacksHandle
,
1201 runAfterPass(HasNameRegex("MockPassHandle"), _
, _
))
1203 EXPECT_CALL(CallbacksHandle
,
1204 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _
))
1206 EXPECT_CALL(CallbacksHandle
,
1207 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
1209 EXPECT_CALL(CallbacksHandle
,
1210 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _
))
1213 StringRef PipelineText
= "test-transform";
1214 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1215 << "Pipeline was: " << PipelineText
;
1219 /// Test parsing of the names of analysis utilities for our mock analysis
1220 /// for all IRUnits.
1222 /// We first require<>, then invalidate<> it, expecting the analysis to be run
1223 /// once and subsequently invalidated.
1224 TEST_F(ModuleCallbacksTest
, AnalysisUtilities
) {
1225 EXPECT_CALL(AnalysisHandle
, run(HasName("<string>"), _
));
1226 EXPECT_CALL(AnalysisHandle
, invalidate(HasName("<string>"), _
, _
));
1228 StringRef PipelineText
= "require<test-analysis>,invalidate<test-analysis>";
1229 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1230 << "Pipeline was: " << PipelineText
;
1234 TEST_F(CGSCCCallbacksTest
, PassUtilities
) {
1235 EXPECT_CALL(AnalysisHandle
, run(HasName("(foo)"), _
, _
));
1236 EXPECT_CALL(AnalysisHandle
, invalidate(HasName("(foo)"), _
, _
));
1238 StringRef PipelineText
= "require<test-analysis>,invalidate<test-analysis>";
1239 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1240 << "Pipeline was: " << PipelineText
;
1244 TEST_F(FunctionCallbacksTest
, AnalysisUtilities
) {
1245 EXPECT_CALL(AnalysisHandle
, run(HasName("foo"), _
));
1246 EXPECT_CALL(AnalysisHandle
, invalidate(HasName("foo"), _
, _
));
1248 StringRef PipelineText
= "require<test-analysis>,invalidate<test-analysis>";
1249 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1250 << "Pipeline was: " << PipelineText
;
1254 TEST_F(LoopCallbacksTest
, PassUtilities
) {
1255 EXPECT_CALL(AnalysisHandle
, run(HasName("loop"), _
, _
));
1256 EXPECT_CALL(AnalysisHandle
, invalidate(HasName("loop"), _
, _
));
1258 StringRef PipelineText
= "require<test-analysis>,invalidate<test-analysis>";
1260 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1261 << "Pipeline was: " << PipelineText
;
1265 /// Test parsing of the top-level pipeline.
1267 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
1268 /// from PassBuilder if it encounters an unknown pipeline entry at the top level
1269 /// (i.e., the first entry on the pipeline).
1270 /// This test parses a pipeline named 'another-pipeline', whose only elements
1271 /// may be the test-transform pass or the analysis utilities
1272 TEST_F(ModuleCallbacksTest
, ParseTopLevelPipeline
) {
1273 PB
.registerParseTopLevelPipelineCallback(
1274 [this](ModulePassManager
&MPM
,
1275 ArrayRef
<PassBuilder::PipelineElement
> Pipeline
) {
1276 auto &FirstName
= Pipeline
.front().Name
;
1277 auto &InnerPipeline
= Pipeline
.front().InnerPipeline
;
1278 if (FirstName
== "another-pipeline") {
1279 for (auto &E
: InnerPipeline
) {
1280 if (parseAnalysisUtilityPasses
<AnalysisT
>("test-analysis", E
.Name
,
1284 if (E
.Name
== "test-transform") {
1285 PM
.addPass(PassHandle
.getPass());
1294 EXPECT_CALL(AnalysisHandle
, run(HasName("<string>"), _
));
1295 EXPECT_CALL(PassHandle
, run(HasName("<string>"), _
))
1296 .WillOnce(&getAnalysisResult
);
1297 EXPECT_CALL(AnalysisHandle
, invalidate(HasName("<string>"), _
, _
));
1299 StringRef PipelineText
=
1300 "another-pipeline(test-transform,invalidate<test-analysis>)";
1301 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Succeeded())
1302 << "Pipeline was: " << PipelineText
;
1305 /// Test the negative case
1306 PipelineText
= "another-pipeline(instcombine)";
1307 ASSERT_THAT_ERROR(PB
.parsePassPipeline(PM
, PipelineText
), Failed())
1308 << "Pipeline was: " << PipelineText
;
1310 } // end anonymous namespace