[ARM] Selection for MVE VMOVN
[llvm-core.git] / unittests / IR / PassBuilderCallbacksTest.cpp
blob7306257851a19172ec560e51a8f91d5e3536b46b
1 //===- unittests/IR/PassBuilderCallbacksTest.cpp - PB Callback Tests --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Testing/Support/Error.h"
10 #include <functional>
11 #include <gmock/gmock.h>
12 #include <gtest/gtest.h>
13 #include <llvm/ADT/Any.h>
14 #include <llvm/Analysis/CGSCCPassManager.h>
15 #include <llvm/Analysis/LoopAnalysisManager.h>
16 #include <llvm/AsmParser/Parser.h>
17 #include <llvm/IR/LLVMContext.h>
18 #include <llvm/IR/PassInstrumentation.h>
19 #include <llvm/IR/PassManager.h>
20 #include <llvm/Passes/PassBuilder.h>
21 #include <llvm/Support/Regex.h>
22 #include <llvm/Support/SourceMgr.h>
23 #include <llvm/Transforms/Scalar/LoopPassManager.h>
25 using namespace llvm;
27 namespace {
28 using testing::AnyNumber;
29 using testing::AtLeast;
30 using testing::DoDefault;
31 using testing::Not;
32 using testing::Return;
33 using testing::Expectation;
34 using testing::Invoke;
35 using testing::WithArgs;
36 using testing::_;
38 /// A CRTP base for analysis mock handles
39 ///
40 /// This class reconciles mocking with the value semantics implementation of the
41 /// AnalysisManager. Analysis mock handles should derive from this class and
42 /// call \c setDefault() in their constroctur for wiring up the defaults defined
43 /// by this base with their mock run() and invalidate() implementations.
44 template <typename DerivedT, typename IRUnitT,
45 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
46 typename... ExtraArgTs>
47 class MockAnalysisHandleBase {
48 public:
49 class Analysis : public AnalysisInfoMixin<Analysis> {
50 friend AnalysisInfoMixin<Analysis>;
51 friend MockAnalysisHandleBase;
52 static AnalysisKey Key;
54 DerivedT *Handle;
56 Analysis(DerivedT &Handle) : Handle(&Handle) {
57 static_assert(std::is_base_of<MockAnalysisHandleBase, DerivedT>::value,
58 "Must pass the derived type to this template!");
61 public:
62 class Result {
63 friend MockAnalysisHandleBase;
65 DerivedT *Handle;
67 Result(DerivedT &Handle) : Handle(&Handle) {}
69 public:
70 // Forward invalidation events to the mock handle.
71 bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
72 typename AnalysisManagerT::Invalidator &Inv) {
73 return Handle->invalidate(IR, PA, Inv);
77 Result run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) {
78 return Handle->run(IR, AM, ExtraArgs...);
82 Analysis getAnalysis() { return Analysis(static_cast<DerivedT &>(*this)); }
83 typename Analysis::Result getResult() {
84 return typename Analysis::Result(static_cast<DerivedT &>(*this));
86 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
88 protected:
89 // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within
90 // the template, so we use a boring static function.
91 static bool invalidateCallback(IRUnitT &IR, const PreservedAnalyses &PA,
92 typename AnalysisManagerT::Invalidator &Inv) {
93 auto PAC = PA.template getChecker<Analysis>();
94 return !PAC.preserved() &&
95 !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
98 /// Derived classes should call this in their constructor to set up default
99 /// mock actions. (We can't do this in our constructor because this has to
100 /// run after the DerivedT is constructed.)
101 void setDefaults() {
102 ON_CALL(static_cast<DerivedT &>(*this),
103 run(_, _, testing::Matcher<ExtraArgTs>(_)...))
104 .WillByDefault(Return(this->getResult()));
105 ON_CALL(static_cast<DerivedT &>(*this), invalidate(_, _, _))
106 .WillByDefault(Invoke(&invalidateCallback));
110 /// A CRTP base for pass mock handles
112 /// This class reconciles mocking with the value semantics implementation of the
113 /// PassManager. Pass mock handles should derive from this class and
114 /// call \c setDefault() in their constroctur for wiring up the defaults defined
115 /// by this base with their mock run() and invalidate() implementations.
116 template <typename DerivedT, typename IRUnitT, typename AnalysisManagerT,
117 typename... ExtraArgTs>
118 AnalysisKey MockAnalysisHandleBase<DerivedT, IRUnitT, AnalysisManagerT,
119 ExtraArgTs...>::Analysis::Key;
121 template <typename DerivedT, typename IRUnitT,
122 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
123 typename... ExtraArgTs>
124 class MockPassHandleBase {
125 public:
126 class Pass : public PassInfoMixin<Pass> {
127 friend MockPassHandleBase;
129 DerivedT *Handle;
131 Pass(DerivedT &Handle) : Handle(&Handle) {
132 static_assert(std::is_base_of<MockPassHandleBase, DerivedT>::value,
133 "Must pass the derived type to this template!");
136 public:
137 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
138 ExtraArgTs... ExtraArgs) {
139 return Handle->run(IR, AM, ExtraArgs...);
143 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
145 Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); }
147 protected:
148 /// Derived classes should call this in their constructor to set up default
149 /// mock actions. (We can't do this in our constructor because this has to
150 /// run after the DerivedT is constructed.)
151 void setDefaults() {
152 ON_CALL(static_cast<DerivedT &>(*this),
153 run(_, _, testing::Matcher<ExtraArgTs>(_)...))
154 .WillByDefault(Return(PreservedAnalyses::all()));
158 /// Mock handles for passes for the IRUnits Module, CGSCC, Function, Loop.
159 /// These handles define the appropriate run() mock interface for the respective
160 /// IRUnit type.
161 template <typename IRUnitT> struct MockPassHandle;
162 template <>
163 struct MockPassHandle<Loop>
164 : MockPassHandleBase<MockPassHandle<Loop>, Loop, LoopAnalysisManager,
165 LoopStandardAnalysisResults &, LPMUpdater &> {
166 MOCK_METHOD4(run,
167 PreservedAnalyses(Loop &, LoopAnalysisManager &,
168 LoopStandardAnalysisResults &, LPMUpdater &));
169 static void invalidateLoop(Loop &L, LoopAnalysisManager &,
170 LoopStandardAnalysisResults &,
171 LPMUpdater &Updater) {
172 Updater.markLoopAsDeleted(L, L.getName());
174 MockPassHandle() { setDefaults(); }
177 template <>
178 struct MockPassHandle<Function>
179 : MockPassHandleBase<MockPassHandle<Function>, Function> {
180 MOCK_METHOD2(run, PreservedAnalyses(Function &, FunctionAnalysisManager &));
182 MockPassHandle() { setDefaults(); }
185 template <>
186 struct MockPassHandle<LazyCallGraph::SCC>
187 : MockPassHandleBase<MockPassHandle<LazyCallGraph::SCC>, LazyCallGraph::SCC,
188 CGSCCAnalysisManager, LazyCallGraph &,
189 CGSCCUpdateResult &> {
190 MOCK_METHOD4(run,
191 PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
192 LazyCallGraph &G, CGSCCUpdateResult &UR));
194 static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
195 LazyCallGraph &, CGSCCUpdateResult &UR) {
196 UR.InvalidatedSCCs.insert(&C);
199 MockPassHandle() { setDefaults(); }
202 template <>
203 struct MockPassHandle<Module>
204 : MockPassHandleBase<MockPassHandle<Module>, Module> {
205 MOCK_METHOD2(run, PreservedAnalyses(Module &, ModuleAnalysisManager &));
207 MockPassHandle() { setDefaults(); }
210 /// Mock handles for analyses for the IRUnits Module, CGSCC, Function, Loop.
211 /// These handles define the appropriate run() and invalidate() mock interfaces
212 /// for the respective IRUnit type.
213 template <typename IRUnitT> struct MockAnalysisHandle;
214 template <>
215 struct MockAnalysisHandle<Loop>
216 : MockAnalysisHandleBase<MockAnalysisHandle<Loop>, Loop,
217 LoopAnalysisManager,
218 LoopStandardAnalysisResults &> {
220 MOCK_METHOD3_T(run, typename Analysis::Result(Loop &, LoopAnalysisManager &,
221 LoopStandardAnalysisResults &));
223 MOCK_METHOD3_T(invalidate, bool(Loop &, const PreservedAnalyses &,
224 LoopAnalysisManager::Invalidator &));
226 MockAnalysisHandle<Loop>() { this->setDefaults(); }
229 template <>
230 struct MockAnalysisHandle<Function>
231 : MockAnalysisHandleBase<MockAnalysisHandle<Function>, Function> {
232 MOCK_METHOD2(run, Analysis::Result(Function &, FunctionAnalysisManager &));
234 MOCK_METHOD3(invalidate, bool(Function &, const PreservedAnalyses &,
235 FunctionAnalysisManager::Invalidator &));
237 MockAnalysisHandle<Function>() { setDefaults(); }
240 template <>
241 struct MockAnalysisHandle<LazyCallGraph::SCC>
242 : MockAnalysisHandleBase<MockAnalysisHandle<LazyCallGraph::SCC>,
243 LazyCallGraph::SCC, CGSCCAnalysisManager,
244 LazyCallGraph &> {
245 MOCK_METHOD3(run, Analysis::Result(LazyCallGraph::SCC &,
246 CGSCCAnalysisManager &, LazyCallGraph &));
248 MOCK_METHOD3(invalidate, bool(LazyCallGraph::SCC &, const PreservedAnalyses &,
249 CGSCCAnalysisManager::Invalidator &));
251 MockAnalysisHandle<LazyCallGraph::SCC>() { setDefaults(); }
254 template <>
255 struct MockAnalysisHandle<Module>
256 : MockAnalysisHandleBase<MockAnalysisHandle<Module>, Module> {
257 MOCK_METHOD2(run, Analysis::Result(Module &, ModuleAnalysisManager &));
259 MOCK_METHOD3(invalidate, bool(Module &, const PreservedAnalyses &,
260 ModuleAnalysisManager::Invalidator &));
262 MockAnalysisHandle<Module>() { setDefaults(); }
265 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
266 SMDiagnostic Err;
267 return parseAssemblyString(IR, Err, C);
270 /// Helper for HasName matcher that returns getName both for IRUnit and
271 /// for IRUnit pointer wrapper into llvm::Any (wrapped by PassInstrumentation).
272 template <typename IRUnitT> std::string getName(const IRUnitT &IR) {
273 return IR.getName();
276 template <> std::string getName(const StringRef &name) { return name; }
278 template <> std::string getName(const llvm::Any &WrappedIR) {
279 if (any_isa<const Module *>(WrappedIR))
280 return any_cast<const Module *>(WrappedIR)->getName().str();
281 if (any_isa<const Function *>(WrappedIR))
282 return any_cast<const Function *>(WrappedIR)->getName().str();
283 if (any_isa<const Loop *>(WrappedIR))
284 return any_cast<const Loop *>(WrappedIR)->getName().str();
285 if (any_isa<const LazyCallGraph::SCC *>(WrappedIR))
286 return any_cast<const LazyCallGraph::SCC *>(WrappedIR)->getName();
287 return "<UNKNOWN>";
289 /// Define a custom matcher for objects which support a 'getName' method.
291 /// LLVM often has IR objects or analysis objects which expose a name
292 /// and in tests it is convenient to match these by name for readability.
293 /// Usually, this name is either a StringRef or a plain std::string. This
294 /// matcher supports any type exposing a getName() method of this form whose
295 /// return value is compatible with an std::ostream. For StringRef, this uses
296 /// the shift operator defined above.
298 /// It should be used as:
300 /// HasName("my_function")
302 /// No namespace or other qualification is required.
303 MATCHER_P(HasName, Name, "") {
304 *result_listener << "has name '" << getName(arg) << "'";
305 return Name == getName(arg);
308 MATCHER_P(HasNameRegex, Name, "") {
309 *result_listener << "has name '" << getName(arg) << "'";
310 llvm::Regex r(Name);
311 return r.match(getName(arg));
314 struct MockPassInstrumentationCallbacks {
315 PassInstrumentationCallbacks Callbacks;
317 MockPassInstrumentationCallbacks() {
318 ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true));
320 MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
321 MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any));
322 MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID));
323 MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
324 MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
326 void registerPassInstrumentation() {
327 Callbacks.registerBeforePassCallback([this](StringRef P, llvm::Any IR) {
328 return this->runBeforePass(P, IR);
330 Callbacks.registerAfterPassCallback(
331 [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); });
332 Callbacks.registerAfterPassInvalidatedCallback(
333 [this](StringRef P) { this->runAfterPassInvalidated(P); });
334 Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
335 return this->runBeforeAnalysis(P, IR);
337 Callbacks.registerAfterAnalysisCallback(
338 [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); });
341 void ignoreNonMockPassInstrumentation(StringRef IRName) {
342 // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
343 // parts of a pipeline that we do not care about (e.g. various passes added
344 // by default by PassBuilder - Verifier pass etc).
345 // Make sure to avoid ignoring Mock passes/analysis, we definitely want
346 // to check these explicitly.
347 EXPECT_CALL(*this,
348 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
349 .Times(AnyNumber());
350 EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName)))
351 .Times(AnyNumber());
352 EXPECT_CALL(*this,
353 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
354 .Times(AnyNumber());
355 EXPECT_CALL(*this,
356 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
357 .Times(AnyNumber());
361 template <typename PassManagerT> class PassBuilderCallbacksTest;
363 /// This test fixture is shared between all the actual tests below and
364 /// takes care of setting up appropriate defaults.
366 /// The template specialization serves to extract the IRUnit and AM types from
367 /// the given PassManagerT.
368 template <typename TestIRUnitT, typename... ExtraPassArgTs,
369 typename... ExtraAnalysisArgTs>
370 class PassBuilderCallbacksTest<PassManager<
371 TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>,
372 ExtraPassArgTs...>> : public testing::Test {
373 protected:
374 using IRUnitT = TestIRUnitT;
375 using AnalysisManagerT = AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>;
376 using PassManagerT =
377 PassManager<TestIRUnitT, AnalysisManagerT, ExtraPassArgTs...>;
378 using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis;
380 LLVMContext Context;
381 std::unique_ptr<Module> M;
383 MockPassInstrumentationCallbacks CallbacksHandle;
385 PassBuilder PB;
386 ModulePassManager PM;
387 LoopAnalysisManager LAM;
388 FunctionAnalysisManager FAM;
389 CGSCCAnalysisManager CGAM;
390 ModuleAnalysisManager AM;
392 MockPassHandle<IRUnitT> PassHandle;
393 MockAnalysisHandle<IRUnitT> AnalysisHandle;
395 static PreservedAnalyses getAnalysisResult(IRUnitT &U, AnalysisManagerT &AM,
396 ExtraAnalysisArgTs &&... Args) {
397 (void)AM.template getResult<AnalysisT>(
398 U, std::forward<ExtraAnalysisArgTs>(Args)...);
399 return PreservedAnalyses::all();
402 PassBuilderCallbacksTest()
403 : M(parseIR(Context,
404 "declare void @bar()\n"
405 "define void @foo(i32 %n) {\n"
406 "entry:\n"
407 " br label %loop\n"
408 "loop:\n"
409 " %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
410 " %iv.next = add i32 %iv, 1\n"
411 " tail call void @bar()\n"
412 " %cmp = icmp eq i32 %iv, %n\n"
413 " br i1 %cmp, label %exit, label %loop\n"
414 "exit:\n"
415 " ret void\n"
416 "}\n")),
417 CallbacksHandle(),
418 PB(nullptr, PipelineTuningOptions(), None, &CallbacksHandle.Callbacks),
419 PM(true), LAM(true), FAM(true), CGAM(true), AM(true) {
421 /// Register a callback for analysis registration.
423 /// The callback is a function taking a reference to an AnalyisManager
424 /// object. When called, the callee gets to register its own analyses with
425 /// this PassBuilder instance.
426 PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) {
427 // Register our mock analysis
428 AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
431 /// Register a callback for pipeline parsing.
433 /// During parsing of a textual pipeline, the PassBuilder will call these
434 /// callbacks for each encountered pass name that it does not know. This
435 /// includes both simple pass names as well as names of sub-pipelines. In
436 /// the latter case, the InnerPipeline is not empty.
437 PB.registerPipelineParsingCallback(
438 [this](StringRef Name, PassManagerT &PM,
439 ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
440 /// Handle parsing of the names of analysis utilities such as
441 /// require<test-analysis> and invalidate<test-analysis> for our
442 /// analysis mock handle
443 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", Name, PM))
444 return true;
446 /// Parse the name of our pass mock handle
447 if (Name == "test-transform") {
448 PM.addPass(PassHandle.getPass());
449 return true;
451 return false;
454 /// Register builtin analyses and cross-register the analysis proxies
455 PB.registerModuleAnalyses(AM);
456 PB.registerCGSCCAnalyses(CGAM);
457 PB.registerFunctionAnalyses(FAM);
458 PB.registerLoopAnalyses(LAM);
459 PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
463 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
464 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
465 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
466 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
468 /// Test parsing of the name of our mock pass for all IRUnits.
470 /// The pass should by default run our mock analysis and then preserve it.
471 TEST_F(ModuleCallbacksTest, Passes) {
472 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
473 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
474 .WillOnce(Invoke(getAnalysisResult));
476 StringRef PipelineText = "test-transform";
477 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
478 << "Pipeline was: " << PipelineText;
480 PM.run(*M, AM);
483 TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
484 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
485 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
486 .WillOnce(Invoke(getAnalysisResult));
488 CallbacksHandle.registerPassInstrumentation();
489 // Non-mock instrumentation not specifically mentioned below can be ignored.
490 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
492 // PassInstrumentation calls should happen in-sequence, in the same order
493 // as passes/analyses are scheduled.
494 ::testing::Sequence PISequence;
495 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
496 HasName("<string>")))
497 .InSequence(PISequence);
498 EXPECT_CALL(CallbacksHandle,
499 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
500 HasName("<string>")))
501 .InSequence(PISequence);
502 EXPECT_CALL(
503 CallbacksHandle,
504 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
505 .InSequence(PISequence);
506 EXPECT_CALL(CallbacksHandle,
507 runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
508 .InSequence(PISequence);
510 StringRef PipelineText = "test-transform";
511 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
512 << "Pipeline was: " << PipelineText;
514 PM.run(*M, AM);
517 TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
518 CallbacksHandle.registerPassInstrumentation();
519 // Non-mock instrumentation run here can safely be ignored.
520 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
522 // Skip the pass by returning false.
523 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
524 HasName("<string>")))
525 .WillOnce(Return(false));
527 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
528 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0);
530 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
531 // as well.
532 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
533 .Times(0);
534 EXPECT_CALL(CallbacksHandle,
535 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
536 .Times(0);
537 EXPECT_CALL(CallbacksHandle,
538 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
539 .Times(0);
541 StringRef PipelineText = "test-transform";
542 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
543 << "Pipeline was: " << PipelineText;
545 PM.run(*M, AM);
548 TEST_F(FunctionCallbacksTest, Passes) {
549 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
550 EXPECT_CALL(PassHandle, run(HasName("foo"), _))
551 .WillOnce(Invoke(getAnalysisResult));
553 StringRef PipelineText = "test-transform";
554 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
555 << "Pipeline was: " << PipelineText;
556 PM.run(*M, AM);
559 TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
560 CallbacksHandle.registerPassInstrumentation();
561 // Non-mock instrumentation not specifically mentioned below can be ignored.
562 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
563 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
565 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
566 EXPECT_CALL(PassHandle, run(HasName("foo"), _))
567 .WillOnce(Invoke(getAnalysisResult));
569 // PassInstrumentation calls should happen in-sequence, in the same order
570 // as passes/analyses are scheduled.
571 ::testing::Sequence PISequence;
572 EXPECT_CALL(CallbacksHandle,
573 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
574 .InSequence(PISequence);
575 EXPECT_CALL(
576 CallbacksHandle,
577 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
578 .InSequence(PISequence);
579 EXPECT_CALL(
580 CallbacksHandle,
581 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
582 .InSequence(PISequence);
583 EXPECT_CALL(CallbacksHandle,
584 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo")))
585 .InSequence(PISequence);
587 // Our mock pass does not invalidate IR.
588 EXPECT_CALL(CallbacksHandle,
589 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
590 .Times(0);
592 StringRef PipelineText = "test-transform";
593 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
594 << "Pipeline was: " << PipelineText;
595 PM.run(*M, AM);
598 TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
599 CallbacksHandle.registerPassInstrumentation();
600 // Non-mock instrumentation run here can safely be ignored.
601 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
602 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
604 // Skip the pass by returning false.
605 EXPECT_CALL(CallbacksHandle,
606 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
607 .WillOnce(Return(false));
609 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
610 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0);
612 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
613 // as well.
614 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
615 .Times(0);
616 EXPECT_CALL(CallbacksHandle,
617 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
618 .Times(0);
619 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
620 .Times(0);
621 EXPECT_CALL(CallbacksHandle,
622 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
623 .Times(0);
624 EXPECT_CALL(CallbacksHandle,
625 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
626 .Times(0);
628 StringRef PipelineText = "test-transform";
629 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
630 << "Pipeline was: " << PipelineText;
631 PM.run(*M, AM);
634 TEST_F(LoopCallbacksTest, Passes) {
635 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
636 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
637 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
639 StringRef PipelineText = "test-transform";
640 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
641 << "Pipeline was: " << PipelineText;
642 PM.run(*M, AM);
645 TEST_F(LoopCallbacksTest, InstrumentedPasses) {
646 CallbacksHandle.registerPassInstrumentation();
647 // Non-mock instrumentation not specifically mentioned below can be ignored.
648 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
649 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
650 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
652 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
653 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
654 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
656 // PassInstrumentation calls should happen in-sequence, in the same order
657 // as passes/analyses are scheduled.
658 ::testing::Sequence PISequence;
659 EXPECT_CALL(CallbacksHandle,
660 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
661 .InSequence(PISequence);
662 EXPECT_CALL(
663 CallbacksHandle,
664 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
665 .InSequence(PISequence);
666 EXPECT_CALL(
667 CallbacksHandle,
668 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
669 .InSequence(PISequence);
670 EXPECT_CALL(CallbacksHandle,
671 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
672 .InSequence(PISequence);
674 // Our mock pass does not invalidate IR.
675 EXPECT_CALL(CallbacksHandle,
676 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
677 .Times(0);
679 StringRef PipelineText = "test-transform";
680 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
681 << "Pipeline was: " << PipelineText;
682 PM.run(*M, AM);
685 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
686 CallbacksHandle.registerPassInstrumentation();
687 // Non-mock instrumentation not specifically mentioned below can be ignored.
688 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
689 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
690 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
692 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
693 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
694 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateLoop)),
695 WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
697 // PassInstrumentation calls should happen in-sequence, in the same order
698 // as passes/analyses are scheduled.
699 ::testing::Sequence PISequence;
700 EXPECT_CALL(CallbacksHandle,
701 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
702 .InSequence(PISequence);
703 EXPECT_CALL(
704 CallbacksHandle,
705 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
706 .InSequence(PISequence);
707 EXPECT_CALL(
708 CallbacksHandle,
709 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
710 .InSequence(PISequence);
711 EXPECT_CALL(CallbacksHandle,
712 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
713 .InSequence(PISequence);
714 EXPECT_CALL(CallbacksHandle,
715 runAfterPassInvalidated(HasNameRegex("^PassManager")))
716 .InSequence(PISequence);
718 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
719 EXPECT_CALL(CallbacksHandle,
720 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
721 .Times(0);
723 StringRef PipelineText = "test-transform";
724 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
725 << "Pipeline was: " << PipelineText;
726 PM.run(*M, AM);
729 TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
730 CallbacksHandle.registerPassInstrumentation();
731 // Non-mock instrumentation run here can safely be ignored.
732 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
733 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
734 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
736 // Skip the pass by returning false.
737 EXPECT_CALL(CallbacksHandle,
738 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
739 .WillOnce(Return(false));
741 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
742 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0);
744 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
745 // as well.
746 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
747 .Times(0);
748 EXPECT_CALL(CallbacksHandle,
749 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
750 .Times(0);
751 EXPECT_CALL(CallbacksHandle,
752 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
753 .Times(0);
754 EXPECT_CALL(CallbacksHandle,
755 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
756 .Times(0);
758 StringRef PipelineText = "test-transform";
759 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
760 << "Pipeline was: " << PipelineText;
761 PM.run(*M, AM);
764 TEST_F(CGSCCCallbacksTest, Passes) {
765 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
766 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
767 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
769 StringRef PipelineText = "test-transform";
770 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
771 << "Pipeline was: " << PipelineText;
772 PM.run(*M, AM);
775 TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
776 CallbacksHandle.registerPassInstrumentation();
777 // Non-mock instrumentation not specifically mentioned below can be ignored.
778 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
779 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
780 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
782 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
783 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
784 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
786 // PassInstrumentation calls should happen in-sequence, in the same order
787 // as passes/analyses are scheduled.
788 ::testing::Sequence PISequence;
789 EXPECT_CALL(CallbacksHandle,
790 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
791 .InSequence(PISequence);
792 EXPECT_CALL(
793 CallbacksHandle,
794 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
795 .InSequence(PISequence);
796 EXPECT_CALL(
797 CallbacksHandle,
798 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
799 .InSequence(PISequence);
800 EXPECT_CALL(CallbacksHandle,
801 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
802 .InSequence(PISequence);
804 // Our mock pass does not invalidate IR.
805 EXPECT_CALL(CallbacksHandle,
806 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
807 .Times(0);
809 StringRef PipelineText = "test-transform";
810 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
811 << "Pipeline was: " << PipelineText;
812 PM.run(*M, AM);
815 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
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("(foo)");
822 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
823 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
824 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateSCC)),
825 WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
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("(foo)")))
832 .InSequence(PISequence);
833 EXPECT_CALL(
834 CallbacksHandle,
835 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
836 .InSequence(PISequence);
837 EXPECT_CALL(
838 CallbacksHandle,
839 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
840 .InSequence(PISequence);
841 EXPECT_CALL(CallbacksHandle,
842 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
843 .InSequence(PISequence);
844 EXPECT_CALL(CallbacksHandle,
845 runAfterPassInvalidated(HasNameRegex("^PassManager")))
846 .InSequence(PISequence);
848 // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
849 EXPECT_CALL(CallbacksHandle,
850 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
851 .Times(0);
853 StringRef PipelineText = "test-transform";
854 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
855 << "Pipeline was: " << PipelineText;
856 PM.run(*M, AM);
859 TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
860 CallbacksHandle.registerPassInstrumentation();
861 // Non-mock instrumentation run here can safely be ignored.
862 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
863 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
864 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
866 // Skip the pass by returning false.
867 EXPECT_CALL(CallbacksHandle,
868 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
869 .WillOnce(Return(false));
871 // neither Analysis nor Pass are called.
872 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0);
873 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0);
875 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
876 // as well.
877 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
878 .Times(0);
879 EXPECT_CALL(CallbacksHandle,
880 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
881 .Times(0);
882 EXPECT_CALL(CallbacksHandle,
883 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
884 .Times(0);
885 EXPECT_CALL(CallbacksHandle,
886 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
887 .Times(0);
889 StringRef PipelineText = "test-transform";
890 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
891 << "Pipeline was: " << PipelineText;
892 PM.run(*M, AM);
895 /// Test parsing of the names of analysis utilities for our mock analysis
896 /// for all IRUnits.
898 /// We first require<>, then invalidate<> it, expecting the analysis to be run
899 /// once and subsequently invalidated.
900 TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
901 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
902 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
904 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
905 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
906 << "Pipeline was: " << PipelineText;
907 PM.run(*M, AM);
910 TEST_F(CGSCCCallbacksTest, PassUtilities) {
911 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
912 EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
914 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
915 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
916 << "Pipeline was: " << PipelineText;
917 PM.run(*M, AM);
920 TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
921 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
922 EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
924 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
925 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
926 << "Pipeline was: " << PipelineText;
927 PM.run(*M, AM);
930 TEST_F(LoopCallbacksTest, PassUtilities) {
931 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
932 EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
934 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
936 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
937 << "Pipeline was: " << PipelineText;
938 PM.run(*M, AM);
941 /// Test parsing of the top-level pipeline.
943 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
944 /// from PassBuilder if it encounters an unknown pipeline entry at the top level
945 /// (i.e., the first entry on the pipeline).
946 /// This test parses a pipeline named 'another-pipeline', whose only elements
947 /// may be the test-transform pass or the analysis utilities
948 TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
949 PB.registerParseTopLevelPipelineCallback([this](
950 ModulePassManager &MPM, ArrayRef<PassBuilder::PipelineElement> Pipeline,
951 bool VerifyEachPass, bool DebugLogging) {
952 auto &FirstName = Pipeline.front().Name;
953 auto &InnerPipeline = Pipeline.front().InnerPipeline;
954 if (FirstName == "another-pipeline") {
955 for (auto &E : InnerPipeline) {
956 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", E.Name, PM))
957 continue;
959 if (E.Name == "test-transform") {
960 PM.addPass(PassHandle.getPass());
961 continue;
963 return false;
966 return true;
969 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
970 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
971 .WillOnce(Invoke(getAnalysisResult));
972 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
974 StringRef PipelineText =
975 "another-pipeline(test-transform,invalidate<test-analysis>)";
976 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
977 << "Pipeline was: " << PipelineText;
978 PM.run(*M, AM);
980 /// Test the negative case
981 PipelineText = "another-pipeline(instcombine)";
982 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed())
983 << "Pipeline was: " << PipelineText;
985 } // end anonymous namespace