1//===- unittests/MIR/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//===----------------------------------------------------------------------===//
8
9#include "llvm/Analysis/CGSCCPassManager.h"
10#include "llvm/Analysis/LoopAnalysisManager.h"
11#include "llvm/CodeGen/FreeMachineFunction.h"
12#include "llvm/MC/TargetRegistry.h"
13#include "llvm/Target/TargetMachine.h"
14#include "llvm/Testing/Support/Error.h"
15#include <functional>
16#include <gmock/gmock.h>
17#include <gtest/gtest.h>
18#include <llvm/ADT/Any.h>
19#include <llvm/AsmParser/Parser.h>
20#include <llvm/CodeGen/MIRParser/MIRParser.h>
21#include <llvm/CodeGen/MachineFunction.h>
22#include <llvm/CodeGen/MachineModuleInfo.h>
23#include <llvm/CodeGen/MachinePassManager.h>
24#include <llvm/IR/LLVMContext.h>
25#include <llvm/IR/PassInstrumentation.h>
26#include <llvm/IR/PassManager.h>
27#include <llvm/Passes/PassBuilder.h>
28#include <llvm/Support/Regex.h>
29#include <llvm/Support/SourceMgr.h>
30#include <llvm/Support/TargetSelect.h>
31
32using namespace llvm;
33
34namespace {
35using testing::_;
36using testing::AnyNumber;
37using testing::DoAll;
38using testing::Not;
39using testing::Return;
40using testing::WithArgs;
41
42StringRef MIRString = R"MIR(
43--- |
44 define void @test() {
45 ret void
46 }
47...
48---
49name: test
50body: |
51 bb.0 (%ir-block.0):
52 RET64
53...
54)MIR";
55
56/// Helper for HasName matcher that returns getName both for IRUnit and
57/// for IRUnit pointer wrapper into llvm::Any (wrapped by PassInstrumentation).
58template <typename IRUnitT> std::string getName(const IRUnitT &IR) {
59 return std::string(IR.getName());
60}
61
62template <> std::string getName(const StringRef &name) {
63 return std::string(name);
64}
65
66template <> std::string getName(const Any &WrappedIR) {
67 if (const auto *const *M = llvm::any_cast<const Module *>(Value: &WrappedIR))
68 return (*M)->getName().str();
69 if (const auto *const *F = llvm::any_cast<const Function *>(Value: &WrappedIR))
70 return (*F)->getName().str();
71 if (const auto *const *MF =
72 llvm::any_cast<const MachineFunction *>(Value: &WrappedIR))
73 return (*MF)->getName().str();
74 return "<UNKNOWN>";
75}
76/// Define a custom matcher for objects which support a 'getName' method.
77///
78/// LLVM often has IR objects or analysis objects which expose a name
79/// and in tests it is convenient to match these by name for readability.
80/// Usually, this name is either a StringRef or a plain std::string. This
81/// matcher supports any type exposing a getName() method of this form whose
82/// return value is compatible with an std::ostream. For StringRef, this uses
83/// the shift operator defined above.
84///
85/// It should be used as:
86///
87/// HasName("my_function")
88///
89/// No namespace or other qualification is required.
90MATCHER_P(HasName, Name, "") {
91 *result_listener << "has name '" << getName(arg) << "'";
92 return Name == getName(arg);
93}
94
95MATCHER_P(HasNameRegex, Name, "") {
96 *result_listener << "has name '" << getName(arg) << "'";
97 llvm::Regex r(Name);
98 return r.match(String: getName(arg));
99}
100
101struct MockPassInstrumentationCallbacks {
102 MockPassInstrumentationCallbacks() {
103 ON_CALL(*this, runBeforePass(_, _)).WillByDefault(action: Return(value: true));
104 }
105 MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
106 MOCK_METHOD2(runBeforeSkippedPass, void(StringRef PassID, llvm::Any));
107 MOCK_METHOD2(runBeforeNonSkippedPass, void(StringRef PassID, llvm::Any));
108 MOCK_METHOD3(runAfterPass,
109 void(StringRef PassID, llvm::Any, const PreservedAnalyses &PA));
110 MOCK_METHOD2(runAfterPassInvalidated,
111 void(StringRef PassID, const PreservedAnalyses &PA));
112 MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
113 MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
114
115 void registerPassInstrumentation(PassInstrumentationCallbacks &Callbacks) {
116 Callbacks.registerShouldRunOptionalPassCallback(
117 C: [this](StringRef P, llvm::Any IR) {
118 return this->runBeforePass(gmock_a0: P, gmock_a1: IR);
119 });
120 Callbacks.registerBeforeSkippedPassCallback(
121 C: [this](StringRef P, llvm::Any IR) {
122 this->runBeforeSkippedPass(gmock_a0: P, gmock_a1: IR);
123 });
124 Callbacks.registerBeforeNonSkippedPassCallback(
125 C: [this](StringRef P, llvm::Any IR) {
126 this->runBeforeNonSkippedPass(gmock_a0: P, gmock_a1: IR);
127 });
128 Callbacks.registerAfterPassCallback(
129 C: [this](StringRef P, llvm::Any IR, const PreservedAnalyses &PA) {
130 this->runAfterPass(gmock_a0: P, gmock_a1: IR, gmock_a2: PA);
131 });
132 Callbacks.registerAfterPassInvalidatedCallback(
133 C: [this](StringRef P, const PreservedAnalyses &PA) {
134 this->runAfterPassInvalidated(gmock_a0: P, gmock_a1: PA);
135 });
136 Callbacks.registerBeforeAnalysisCallback(C: [this](StringRef P, llvm::Any IR) {
137 return this->runBeforeAnalysis(gmock_a0: P, gmock_a1: IR);
138 });
139 Callbacks.registerAfterAnalysisCallback(
140 C: [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(gmock_a0: P, gmock_a1: IR); });
141 }
142
143 void ignoreNonMockPassInstrumentation(StringRef IRName) {
144 // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
145 // parts of a pipeline that we do not care about (e.g. various passes added
146 // by default by PassBuilder - Verifier pass etc).
147 // Make sure to avoid ignoring Mock passes/analysis, we definitely want
148 // to check these explicitly.
149 EXPECT_CALL(*this,
150 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
151 .Times(a_cardinality: AnyNumber())
152 .WillRepeatedly(action: Return(value: false));
153 EXPECT_CALL(
154 *this, runBeforeSkippedPass(Not(HasNameRegex("Mock")), HasName(IRName)))
155 .Times(a_cardinality: AnyNumber());
156 EXPECT_CALL(*this, runBeforeNonSkippedPass(Not(HasNameRegex("Mock")),
157 HasName(IRName)))
158 .Times(a_cardinality: AnyNumber());
159 EXPECT_CALL(*this,
160 runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName), _))
161 .Times(a_cardinality: AnyNumber());
162 EXPECT_CALL(*this,
163 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
164 .Times(a_cardinality: AnyNumber());
165 EXPECT_CALL(*this,
166 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
167 .Times(a_cardinality: AnyNumber());
168 }
169};
170
171template <typename DerivedT> class MockAnalysisHandleBase {
172public:
173 class Analysis : public AnalysisInfoMixin<Analysis> {
174 friend AnalysisInfoMixin<Analysis>;
175 friend MockAnalysisHandleBase;
176 static AnalysisKey Key;
177
178 DerivedT *Handle;
179
180 Analysis(DerivedT &Handle) : Handle(&Handle) {
181 static_assert(std::is_base_of<MockAnalysisHandleBase, DerivedT>::value,
182 "Must pass the derived type to this template!");
183 }
184
185 public:
186 class Result {
187 friend MockAnalysisHandleBase;
188
189 DerivedT *Handle;
190
191 Result(DerivedT &Handle) : Handle(&Handle) {}
192
193 public:
194 // Forward invalidation events to the mock handle.
195 bool invalidate(MachineFunction &IR, const PreservedAnalyses &PA,
196 MachineFunctionAnalysisManager::Invalidator &Inv) {
197 return Handle->invalidate(IR, PA, Inv);
198 }
199 };
200
201 Result run(MachineFunction &IR, MachineFunctionAnalysisManager &AM) {
202 return Handle->run(IR, AM);
203 }
204 };
205
206 Analysis getAnalysis() { return Analysis(static_cast<DerivedT &>(*this)); }
207 typename Analysis::Result getResult() {
208 return typename Analysis::Result(static_cast<DerivedT &>(*this));
209 }
210 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
211
212protected:
213 // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within
214 // the template, so we use a boring static function.
215 static bool
216 invalidateCallback(MachineFunction &IR, const PreservedAnalyses &PA,
217 MachineFunctionAnalysisManager::Invalidator &Inv) {
218 auto PAC = PA.template getChecker<Analysis>();
219 return !PAC.preserved() &&
220 !PAC.template preservedSet<AllAnalysesOn<MachineFunction>>();
221 }
222
223 /// Derived classes should call this in their constructor to set up default
224 /// mock actions. (We can't do this in our constructor because this has to
225 /// run after the DerivedT is constructed.)
226 void setDefaults() {
227 ON_CALL(static_cast<DerivedT &>(*this), run(_, _))
228 .WillByDefault(Return(this->getResult()));
229 ON_CALL(static_cast<DerivedT &>(*this), invalidate(_, _, _))
230 .WillByDefault(&invalidateCallback);
231 }
232};
233
234template <typename DerivedT> class MockPassHandleBase {
235public:
236 class Pass : public PassInfoMixin<Pass> {
237 friend MockPassHandleBase;
238
239 DerivedT *Handle;
240
241 Pass(DerivedT &Handle) : Handle(&Handle) {
242 static_assert(std::is_base_of<MockPassHandleBase, DerivedT>::value,
243 "Must pass the derived type to this template!");
244 }
245
246 public:
247 PreservedAnalyses run(MachineFunction &IR,
248 MachineFunctionAnalysisManager &AM) {
249 return Handle->run(IR, AM);
250 }
251 };
252
253 static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
254
255 Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); }
256
257protected:
258 /// Derived classes should call this in their constructor to set up default
259 /// mock actions. (We can't do this in our constructor because this has to
260 /// run after the DerivedT is constructed.)
261 void setDefaults() {
262 ON_CALL(static_cast<DerivedT &>(*this), run(_, _))
263 .WillByDefault(Return(value: PreservedAnalyses::all()));
264 }
265};
266
267struct MockAnalysisHandle : public MockAnalysisHandleBase<MockAnalysisHandle> {
268 MOCK_METHOD2(run, Analysis::Result(MachineFunction &,
269 MachineFunctionAnalysisManager &));
270
271 MOCK_METHOD3(invalidate, bool(MachineFunction &, const PreservedAnalyses &,
272 MachineFunctionAnalysisManager::Invalidator &));
273
274 MockAnalysisHandle() { setDefaults(); }
275};
276
277template <typename DerivedT>
278AnalysisKey MockAnalysisHandleBase<DerivedT>::Analysis::Key;
279
280class MockPassHandle : public MockPassHandleBase<MockPassHandle> {
281public:
282 MOCK_METHOD2(run, PreservedAnalyses(MachineFunction &,
283 MachineFunctionAnalysisManager &));
284
285 MockPassHandle() { setDefaults(); }
286};
287
288class MachineFunctionCallbacksTest : public testing::Test {
289protected:
290 static void SetUpTestCase() {
291 InitializeAllTargetInfos();
292 InitializeAllTargets();
293 InitializeAllTargetMCs();
294 }
295
296 LLVMContext Context;
297
298 std::unique_ptr<LLVMTargetMachine> TM;
299 std::unique_ptr<MachineModuleInfo> MMI;
300
301 std::unique_ptr<Module> M;
302
303 PassInstrumentationCallbacks PIC;
304 std::unique_ptr<PassBuilder> PB;
305 ModulePassManager MPM;
306 MachineFunctionAnalysisManager MFAM;
307 LoopAnalysisManager LAM;
308 FunctionAnalysisManager FAM;
309 CGSCCAnalysisManager CGAM;
310 ModuleAnalysisManager MAM;
311
312 MockPassInstrumentationCallbacks CallbacksHandle;
313 MockPassHandle PassHandle;
314 MockAnalysisHandle AnalysisHandle;
315
316 static std::unique_ptr<Module> parseMIR(StringRef MIRCode,
317 LLVMContext &Context,
318 TargetMachine &TM,
319 MachineModuleInfo &MMI) {
320 SMDiagnostic Diagnostic;
321 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(InputData: MIRCode);
322 std::unique_ptr<MIRParser> MIR =
323 createMIRParser(Contents: std::move(MBuffer), Context);
324 assert(MIR);
325
326 std::unique_ptr<Module> Mod = MIR->parseIRModule();
327 assert(Mod);
328
329 // Module identifier is used in tests below.
330 Mod->setModuleIdentifier("module");
331 Mod->setDataLayout(TM.createDataLayout());
332
333 [[maybe_unused]] bool Ret = MIR->parseMachineFunctions(M&: *Mod, MMI);
334 assert(!Ret);
335
336 return Mod;
337 }
338
339 static PreservedAnalyses
340 getAnalysisResult(MachineFunction &U, MachineFunctionAnalysisManager &MFAM) {
341 MFAM.getResult<MockAnalysisHandle::Analysis>(IR&: U);
342 return PreservedAnalyses::all();
343 }
344
345 void SetUp() override {
346 std::string Error;
347 auto TripleName = "x86_64-pc-linux-gnu";
348 auto *T = TargetRegistry::lookupTarget(Triple: TripleName, Error);
349 if (!T)
350 GTEST_SKIP();
351 TM = std::unique_ptr<LLVMTargetMachine>(
352 static_cast<LLVMTargetMachine *>(T->createTargetMachine(
353 TT: TripleName, CPU: "", Features: "", Options: TargetOptions(), RM: std::nullopt)));
354 if (!TM)
355 GTEST_SKIP();
356
357 MMI = std::make_unique<MachineModuleInfo>(args: TM.get());
358 M = parseMIR(MIRCode: MIRString, Context, TM&: *TM, MMI&: *MMI);
359 PB = std::make_unique<PassBuilder>(args: TM.get(), args: PipelineTuningOptions(),
360 args: std::nullopt, args: &PIC);
361
362 /// Register a callback for analysis registration.
363 ///
364 /// The callback is a function taking a reference to an AnalyisManager
365 /// object. When called, the callee gets to register its own analyses with
366 /// this PassBuilder instance.
367 PB->registerAnalysisRegistrationCallback(
368 C: [this](MachineFunctionAnalysisManager &AM) {
369 // Register our mock analysis
370 AM.registerPass(PassBuilder: [this] { return AnalysisHandle.getAnalysis(); });
371 });
372
373 /// Register a callback for pipeline parsing.
374 ///
375 /// During parsing of a textual pipeline, the PassBuilder will call these
376 /// callbacks for each encountered pass name that it does not know. This
377 /// includes both simple pass names as well as names of sub-pipelines. In
378 /// the latter case, the InnerPipeline is not empty.
379 PB->registerPipelineParsingCallback(
380 C: [this](StringRef Name, MachineFunctionPassManager &PM,
381 ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
382 if (parseAnalysisUtilityPasses<MockAnalysisHandle::Analysis>(
383 AnalysisName: "test-analysis", PipelineName: Name, PM))
384 return true;
385
386 /// Parse the name of our pass mock handle
387 if (Name == "test-transform") {
388 PM.addPass(Pass: PassHandle.getPass());
389 return true;
390 }
391 return false;
392 });
393
394 /// Register builtin analyses and cross-register the analysis proxies
395 PB->registerModuleAnalyses(MAM);
396 PB->registerCGSCCAnalyses(CGAM);
397 PB->registerFunctionAnalyses(FAM);
398 PB->registerLoopAnalyses(LAM);
399 PB->registerMachineFunctionAnalyses(MFAM);
400 PB->crossRegisterProxies(LAM, FAM, CGAM, MAM, MFAM: &MFAM);
401 MAM.registerPass(PassBuilder: [&] { return MachineModuleAnalysis(*MMI); });
402 }
403};
404
405TEST_F(MachineFunctionCallbacksTest, Passes) {
406 EXPECT_CALL(AnalysisHandle, run(HasName("test"), _));
407 EXPECT_CALL(PassHandle, run(HasName("test"), _)).WillOnce(once_action: &getAnalysisResult);
408
409 StringRef PipelineText = "test-transform";
410 ASSERT_THAT_ERROR(PB->parsePassPipeline(MPM, PipelineText), Succeeded())
411 << "Pipeline was: " << PipelineText;
412 MPM.run(IR&: *M, AM&: MAM);
413}
414
415TEST_F(MachineFunctionCallbacksTest, InstrumentedPasses) {
416 CallbacksHandle.registerPassInstrumentation(Callbacks&: PIC);
417 // Non-mock instrumentation not specifically mentioned below can be ignored.
418 CallbacksHandle.ignoreNonMockPassInstrumentation(IRName: "test");
419 CallbacksHandle.ignoreNonMockPassInstrumentation(IRName: "module");
420
421 // PassInstrumentation calls should happen in-sequence, in the same order
422 // as passes/analyses are scheduled.
423 ::testing::Sequence PISequence;
424 EXPECT_CALL(CallbacksHandle,
425 runBeforePass(HasNameRegex("MockPassHandle"), HasName("test")))
426 .InSequence(s: PISequence)
427 .WillOnce(once_action: Return(value: true));
428 EXPECT_CALL(
429 CallbacksHandle,
430 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("test")))
431 .InSequence(s: PISequence);
432 EXPECT_CALL(
433 CallbacksHandle,
434 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("test")))
435 .InSequence(s: PISequence);
436 EXPECT_CALL(
437 CallbacksHandle,
438 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("test")))
439 .InSequence(s: PISequence);
440 EXPECT_CALL(CallbacksHandle,
441 runAfterPass(HasNameRegex("MockPassHandle"), HasName("test"), _))
442 .InSequence(s: PISequence);
443 EXPECT_CALL(
444 CallbacksHandle,
445 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("test")))
446 .Times(n: 0);
447
448 EXPECT_CALL(AnalysisHandle, run(HasName("test"), _));
449 EXPECT_CALL(PassHandle, run(HasName("test"), _)).WillOnce(once_action: &getAnalysisResult);
450
451 StringRef PipelineText = "test-transform";
452 ASSERT_THAT_ERROR(PB->parsePassPipeline(MPM, PipelineText), Succeeded())
453 << "Pipeline was: " << PipelineText;
454 MPM.run(IR&: *M, AM&: MAM);
455}
456
457TEST_F(MachineFunctionCallbacksTest, InstrumentedSkippedPasses) {
458 CallbacksHandle.registerPassInstrumentation(Callbacks&: PIC);
459 // Non-mock instrumentation run here can safely be ignored.
460 CallbacksHandle.ignoreNonMockPassInstrumentation(IRName: "test");
461 CallbacksHandle.ignoreNonMockPassInstrumentation(IRName: "module");
462
463 // Skip the pass by returning false.
464 EXPECT_CALL(CallbacksHandle,
465 runBeforePass(HasNameRegex("MockPassHandle"), HasName("test")))
466 .WillOnce(once_action: Return(value: false));
467
468 EXPECT_CALL(
469 CallbacksHandle,
470 runBeforeSkippedPass(HasNameRegex("MockPassHandle"), HasName("test")))
471 .Times(n: 1);
472
473 EXPECT_CALL(AnalysisHandle, run(HasName("test"), _)).Times(n: 0);
474 EXPECT_CALL(PassHandle, run(HasName("test"), _)).Times(n: 0);
475
476 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
477 // as well.
478 EXPECT_CALL(CallbacksHandle,
479 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _))
480 .Times(n: 0);
481 EXPECT_CALL(CallbacksHandle,
482 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
483 .Times(n: 0);
484 EXPECT_CALL(CallbacksHandle,
485 runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _))
486 .Times(n: 0);
487 EXPECT_CALL(CallbacksHandle,
488 runAfterPass(HasNameRegex("MockPassHandle"), _, _))
489 .Times(n: 0);
490 EXPECT_CALL(CallbacksHandle,
491 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
492 .Times(n: 0);
493 EXPECT_CALL(CallbacksHandle,
494 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
495 .Times(n: 0);
496
497 StringRef PipelineText = "test-transform";
498 ASSERT_THAT_ERROR(PB->parsePassPipeline(MPM, PipelineText), Succeeded())
499 << "Pipeline was: " << PipelineText;
500 MPM.run(IR&: *M, AM&: MAM);
501}
502
503// Check that the Module -> MachineFunction adaptor properly calls
504// runAfterPassInvalidated.
505TEST_F(MachineFunctionCallbacksTest, InstrumentedFreeMFPass) {
506 CallbacksHandle.registerPassInstrumentation(Callbacks&: PIC);
507 // Non-mock instrumentation run here can safely be ignored.
508 CallbacksHandle.ignoreNonMockPassInstrumentation(IRName: "test");
509 CallbacksHandle.ignoreNonMockPassInstrumentation(IRName: "module");
510
511 ::testing::Sequence PISequence;
512 EXPECT_CALL(
513 CallbacksHandle,
514 runBeforePass(HasNameRegex("FreeMachineFunctionPass"), HasName("test")))
515 .InSequence(s: PISequence)
516 .WillOnce(once_action: Return(value: true));
517 EXPECT_CALL(CallbacksHandle,
518 runBeforeNonSkippedPass(HasNameRegex("FreeMachineFunctionPass"),
519 HasName("test")))
520 .InSequence(s: PISequence);
521 EXPECT_CALL(CallbacksHandle, runAfterPassInvalidated(
522 HasNameRegex("FreeMachineFunctionPass"), _))
523 .InSequence(s: PISequence);
524
525 // runAfterPass should not be called since the MachineFunction is no longer
526 // valid after FreeMachineFunctionPass.
527 EXPECT_CALL(CallbacksHandle,
528 runAfterPass(HasNameRegex("FreeMachineFunctionPass"), _, _))
529 .Times(n: 0);
530
531 MPM.addPass(
532 Pass: createModuleToMachineFunctionPassAdaptor(Pass: FreeMachineFunctionPass()));
533 MPM.run(IR&: *M, AM&: MAM);
534}
535
536// Check that the Module -> MachineFunction adaptor and MachineFunction pass
537// manager properly call runAfterPassInvalidated.
538TEST_F(MachineFunctionCallbacksTest, InstrumentedFreeMFPass2) {
539 CallbacksHandle.registerPassInstrumentation(Callbacks&: PIC);
540 // Non-mock instrumentation run here can safely be ignored.
541 CallbacksHandle.ignoreNonMockPassInstrumentation(IRName: "test");
542 CallbacksHandle.ignoreNonMockPassInstrumentation(IRName: "module");
543
544 ::testing::Sequence PISequence;
545 EXPECT_CALL(
546 CallbacksHandle,
547 runBeforePass(HasNameRegex("FreeMachineFunctionPass"), HasName("test")))
548 .InSequence(s: PISequence)
549 .WillOnce(once_action: Return(value: true));
550 EXPECT_CALL(CallbacksHandle,
551 runBeforeNonSkippedPass(HasNameRegex("FreeMachineFunctionPass"),
552 HasName("test")))
553 .InSequence(s: PISequence);
554 EXPECT_CALL(CallbacksHandle, runAfterPassInvalidated(
555 HasNameRegex("FreeMachineFunctionPass"), _))
556 .InSequence(s: PISequence);
557 EXPECT_CALL(CallbacksHandle,
558 runAfterPassInvalidated(HasNameRegex("PassManager"), _))
559 .InSequence(s: PISequence);
560
561 // runAfterPass should not be called since the MachineFunction is no longer
562 // valid after FreeMachineFunctionPass.
563 EXPECT_CALL(CallbacksHandle,
564 runAfterPass(HasNameRegex("FreeMachineFunctionPass"), _, _))
565 .Times(n: 0);
566 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("PassManager"), _, _))
567 .Times(n: 0);
568
569 MachineFunctionPassManager MFPM;
570 MFPM.addPass(Pass: FreeMachineFunctionPass());
571 MPM.addPass(Pass: createModuleToMachineFunctionPassAdaptor(Pass: std::move(MFPM)));
572 MPM.run(IR&: *M, AM&: MAM);
573}
574
575} // end anonymous namespace
576

source code of llvm/unittests/MIR/PassBuilderCallbacksTest.cpp