Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / unittests / IR / PassBuilderCallbacksTest.cpp
blob7cd938fcddb9c47740e6d01878d137e1882a83d6
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(), PB(nullptr, None, &CallbacksHandle.Callbacks),
418 PM(true), LAM(true), FAM(true), CGAM(true), AM(true) {
420 /// Register a callback for analysis registration.
422 /// The callback is a function taking a reference to an AnalyisManager
423 /// object. When called, the callee gets to register its own analyses with
424 /// this PassBuilder instance.
425 PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) {
426 // Register our mock analysis
427 AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
430 /// Register a callback for pipeline parsing.
432 /// During parsing of a textual pipeline, the PassBuilder will call these
433 /// callbacks for each encountered pass name that it does not know. This
434 /// includes both simple pass names as well as names of sub-pipelines. In
435 /// the latter case, the InnerPipeline is not empty.
436 PB.registerPipelineParsingCallback(
437 [this](StringRef Name, PassManagerT &PM,
438 ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
439 /// Handle parsing of the names of analysis utilities such as
440 /// require<test-analysis> and invalidate<test-analysis> for our
441 /// analysis mock handle
442 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", Name, PM))
443 return true;
445 /// Parse the name of our pass mock handle
446 if (Name == "test-transform") {
447 PM.addPass(PassHandle.getPass());
448 return true;
450 return false;
453 /// Register builtin analyses and cross-register the analysis proxies
454 PB.registerModuleAnalyses(AM);
455 PB.registerCGSCCAnalyses(CGAM);
456 PB.registerFunctionAnalyses(FAM);
457 PB.registerLoopAnalyses(LAM);
458 PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
462 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
463 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
464 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
465 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
467 /// Test parsing of the name of our mock pass for all IRUnits.
469 /// The pass should by default run our mock analysis and then preserve it.
470 TEST_F(ModuleCallbacksTest, Passes) {
471 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
472 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
473 .WillOnce(Invoke(getAnalysisResult));
475 StringRef PipelineText = "test-transform";
476 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
477 << "Pipeline was: " << PipelineText;
479 PM.run(*M, AM);
482 TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
483 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
484 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
485 .WillOnce(Invoke(getAnalysisResult));
487 CallbacksHandle.registerPassInstrumentation();
488 // Non-mock instrumentation not specifically mentioned below can be ignored.
489 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
491 // PassInstrumentation calls should happen in-sequence, in the same order
492 // as passes/analyses are scheduled.
493 ::testing::Sequence PISequence;
494 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
495 HasName("<string>")))
496 .InSequence(PISequence);
497 EXPECT_CALL(CallbacksHandle,
498 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
499 HasName("<string>")))
500 .InSequence(PISequence);
501 EXPECT_CALL(
502 CallbacksHandle,
503 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
504 .InSequence(PISequence);
505 EXPECT_CALL(CallbacksHandle,
506 runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
507 .InSequence(PISequence);
509 StringRef PipelineText = "test-transform";
510 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
511 << "Pipeline was: " << PipelineText;
513 PM.run(*M, AM);
516 TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
517 CallbacksHandle.registerPassInstrumentation();
518 // Non-mock instrumentation run here can safely be ignored.
519 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
521 // Skip the pass by returning false.
522 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
523 HasName("<string>")))
524 .WillOnce(Return(false));
526 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
527 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0);
529 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
530 // as well.
531 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
532 .Times(0);
533 EXPECT_CALL(CallbacksHandle,
534 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
535 .Times(0);
536 EXPECT_CALL(CallbacksHandle,
537 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
538 .Times(0);
540 StringRef PipelineText = "test-transform";
541 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
542 << "Pipeline was: " << PipelineText;
544 PM.run(*M, AM);
547 TEST_F(FunctionCallbacksTest, Passes) {
548 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
549 EXPECT_CALL(PassHandle, run(HasName("foo"), _))
550 .WillOnce(Invoke(getAnalysisResult));
552 StringRef PipelineText = "test-transform";
553 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
554 << "Pipeline was: " << PipelineText;
555 PM.run(*M, AM);
558 TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
559 CallbacksHandle.registerPassInstrumentation();
560 // Non-mock instrumentation not specifically mentioned below can be ignored.
561 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
562 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
564 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
565 EXPECT_CALL(PassHandle, run(HasName("foo"), _))
566 .WillOnce(Invoke(getAnalysisResult));
568 // PassInstrumentation calls should happen in-sequence, in the same order
569 // as passes/analyses are scheduled.
570 ::testing::Sequence PISequence;
571 EXPECT_CALL(CallbacksHandle,
572 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
573 .InSequence(PISequence);
574 EXPECT_CALL(
575 CallbacksHandle,
576 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
577 .InSequence(PISequence);
578 EXPECT_CALL(
579 CallbacksHandle,
580 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
581 .InSequence(PISequence);
582 EXPECT_CALL(CallbacksHandle,
583 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo")))
584 .InSequence(PISequence);
586 // Our mock pass does not invalidate IR.
587 EXPECT_CALL(CallbacksHandle,
588 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
589 .Times(0);
591 StringRef PipelineText = "test-transform";
592 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
593 << "Pipeline was: " << PipelineText;
594 PM.run(*M, AM);
597 TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
598 CallbacksHandle.registerPassInstrumentation();
599 // Non-mock instrumentation run here can safely be ignored.
600 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
601 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
603 // Skip the pass by returning false.
604 EXPECT_CALL(CallbacksHandle,
605 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
606 .WillOnce(Return(false));
608 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
609 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0);
611 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
612 // as well.
613 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
614 .Times(0);
615 EXPECT_CALL(CallbacksHandle,
616 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
617 .Times(0);
618 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
619 .Times(0);
620 EXPECT_CALL(CallbacksHandle,
621 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
622 .Times(0);
623 EXPECT_CALL(CallbacksHandle,
624 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
625 .Times(0);
627 StringRef PipelineText = "test-transform";
628 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
629 << "Pipeline was: " << PipelineText;
630 PM.run(*M, AM);
633 TEST_F(LoopCallbacksTest, Passes) {
634 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
635 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
636 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
638 StringRef PipelineText = "test-transform";
639 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
640 << "Pipeline was: " << PipelineText;
641 PM.run(*M, AM);
644 TEST_F(LoopCallbacksTest, InstrumentedPasses) {
645 CallbacksHandle.registerPassInstrumentation();
646 // Non-mock instrumentation not specifically mentioned below can be ignored.
647 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
648 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
649 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
651 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
652 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
653 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
655 // PassInstrumentation calls should happen in-sequence, in the same order
656 // as passes/analyses are scheduled.
657 ::testing::Sequence PISequence;
658 EXPECT_CALL(CallbacksHandle,
659 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
660 .InSequence(PISequence);
661 EXPECT_CALL(
662 CallbacksHandle,
663 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
664 .InSequence(PISequence);
665 EXPECT_CALL(
666 CallbacksHandle,
667 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
668 .InSequence(PISequence);
669 EXPECT_CALL(CallbacksHandle,
670 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
671 .InSequence(PISequence);
673 // Our mock pass does not invalidate IR.
674 EXPECT_CALL(CallbacksHandle,
675 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
676 .Times(0);
678 StringRef PipelineText = "test-transform";
679 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
680 << "Pipeline was: " << PipelineText;
681 PM.run(*M, AM);
684 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
685 CallbacksHandle.registerPassInstrumentation();
686 // Non-mock instrumentation not specifically mentioned below can be ignored.
687 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
688 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
689 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
691 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
692 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
693 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateLoop)),
694 WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
696 // PassInstrumentation calls should happen in-sequence, in the same order
697 // as passes/analyses are scheduled.
698 ::testing::Sequence PISequence;
699 EXPECT_CALL(CallbacksHandle,
700 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
701 .InSequence(PISequence);
702 EXPECT_CALL(
703 CallbacksHandle,
704 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
705 .InSequence(PISequence);
706 EXPECT_CALL(
707 CallbacksHandle,
708 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
709 .InSequence(PISequence);
710 EXPECT_CALL(CallbacksHandle,
711 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
712 .InSequence(PISequence);
713 EXPECT_CALL(CallbacksHandle,
714 runAfterPassInvalidated(HasNameRegex("^PassManager")))
715 .InSequence(PISequence);
717 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
718 EXPECT_CALL(CallbacksHandle,
719 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
720 .Times(0);
722 StringRef PipelineText = "test-transform";
723 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
724 << "Pipeline was: " << PipelineText;
725 PM.run(*M, AM);
728 TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
729 CallbacksHandle.registerPassInstrumentation();
730 // Non-mock instrumentation run here can safely be ignored.
731 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
732 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
733 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
735 // Skip the pass by returning false.
736 EXPECT_CALL(CallbacksHandle,
737 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
738 .WillOnce(Return(false));
740 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
741 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0);
743 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
744 // as well.
745 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
746 .Times(0);
747 EXPECT_CALL(CallbacksHandle,
748 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
749 .Times(0);
750 EXPECT_CALL(CallbacksHandle,
751 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
752 .Times(0);
753 EXPECT_CALL(CallbacksHandle,
754 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
755 .Times(0);
757 StringRef PipelineText = "test-transform";
758 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
759 << "Pipeline was: " << PipelineText;
760 PM.run(*M, AM);
763 TEST_F(CGSCCCallbacksTest, Passes) {
764 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
765 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
766 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
768 StringRef PipelineText = "test-transform";
769 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
770 << "Pipeline was: " << PipelineText;
771 PM.run(*M, AM);
774 TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
775 CallbacksHandle.registerPassInstrumentation();
776 // Non-mock instrumentation not specifically mentioned below can be ignored.
777 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
778 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
780 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
781 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
782 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
784 // PassInstrumentation calls should happen in-sequence, in the same order
785 // as passes/analyses are scheduled.
786 ::testing::Sequence PISequence;
787 EXPECT_CALL(CallbacksHandle,
788 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
789 .InSequence(PISequence);
790 EXPECT_CALL(
791 CallbacksHandle,
792 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
793 .InSequence(PISequence);
794 EXPECT_CALL(
795 CallbacksHandle,
796 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
797 .InSequence(PISequence);
798 EXPECT_CALL(CallbacksHandle,
799 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
800 .InSequence(PISequence);
802 // Our mock pass does not invalidate IR.
803 EXPECT_CALL(CallbacksHandle,
804 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
805 .Times(0);
807 StringRef PipelineText = "test-transform";
808 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
809 << "Pipeline was: " << PipelineText;
810 PM.run(*M, AM);
813 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
814 CallbacksHandle.registerPassInstrumentation();
815 // Non-mock instrumentation not specifically mentioned below can be ignored.
816 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
817 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
819 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
820 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
821 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateSCC)),
822 WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
824 // PassInstrumentation calls should happen in-sequence, in the same order
825 // as passes/analyses are scheduled.
826 ::testing::Sequence PISequence;
827 EXPECT_CALL(CallbacksHandle,
828 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
829 .InSequence(PISequence);
830 EXPECT_CALL(
831 CallbacksHandle,
832 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
833 .InSequence(PISequence);
834 EXPECT_CALL(
835 CallbacksHandle,
836 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
837 .InSequence(PISequence);
838 EXPECT_CALL(CallbacksHandle,
839 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
840 .InSequence(PISequence);
841 EXPECT_CALL(CallbacksHandle,
842 runAfterPassInvalidated(HasNameRegex("^PassManager")))
843 .InSequence(PISequence);
845 // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
846 EXPECT_CALL(CallbacksHandle,
847 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
848 .Times(0);
850 StringRef PipelineText = "test-transform";
851 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
852 << "Pipeline was: " << PipelineText;
853 PM.run(*M, AM);
856 TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
857 CallbacksHandle.registerPassInstrumentation();
858 // Non-mock instrumentation run here can safely be ignored.
859 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
860 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
862 // Skip the pass by returning false.
863 EXPECT_CALL(CallbacksHandle,
864 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
865 .WillOnce(Return(false));
867 // neither Analysis nor Pass are called.
868 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0);
869 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0);
871 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
872 // as well.
873 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
874 .Times(0);
875 EXPECT_CALL(CallbacksHandle,
876 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
877 .Times(0);
878 EXPECT_CALL(CallbacksHandle,
879 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
880 .Times(0);
881 EXPECT_CALL(CallbacksHandle,
882 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
883 .Times(0);
885 StringRef PipelineText = "test-transform";
886 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
887 << "Pipeline was: " << PipelineText;
888 PM.run(*M, AM);
891 /// Test parsing of the names of analysis utilities for our mock analysis
892 /// for all IRUnits.
894 /// We first require<>, then invalidate<> it, expecting the analysis to be run
895 /// once and subsequently invalidated.
896 TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
897 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
898 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
900 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
901 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
902 << "Pipeline was: " << PipelineText;
903 PM.run(*M, AM);
906 TEST_F(CGSCCCallbacksTest, PassUtilities) {
907 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
908 EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
910 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
911 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
912 << "Pipeline was: " << PipelineText;
913 PM.run(*M, AM);
916 TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
917 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
918 EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
920 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
921 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
922 << "Pipeline was: " << PipelineText;
923 PM.run(*M, AM);
926 TEST_F(LoopCallbacksTest, PassUtilities) {
927 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
928 EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
930 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
932 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
933 << "Pipeline was: " << PipelineText;
934 PM.run(*M, AM);
937 /// Test parsing of the top-level pipeline.
939 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
940 /// from PassBuilder if it encounters an unknown pipeline entry at the top level
941 /// (i.e., the first entry on the pipeline).
942 /// This test parses a pipeline named 'another-pipeline', whose only elements
943 /// may be the test-transform pass or the analysis utilities
944 TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
945 PB.registerParseTopLevelPipelineCallback([this](
946 ModulePassManager &MPM, ArrayRef<PassBuilder::PipelineElement> Pipeline,
947 bool VerifyEachPass, bool DebugLogging) {
948 auto &FirstName = Pipeline.front().Name;
949 auto &InnerPipeline = Pipeline.front().InnerPipeline;
950 if (FirstName == "another-pipeline") {
951 for (auto &E : InnerPipeline) {
952 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", E.Name, PM))
953 continue;
955 if (E.Name == "test-transform") {
956 PM.addPass(PassHandle.getPass());
957 continue;
959 return false;
962 return true;
965 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
966 EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
967 .WillOnce(Invoke(getAnalysisResult));
968 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
970 StringRef PipelineText =
971 "another-pipeline(test-transform,invalidate<test-analysis>)";
972 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
973 << "Pipeline was: " << PipelineText;
974 PM.run(*M, AM);
976 /// Test the negative case
977 PipelineText = "another-pipeline(instcombine)";
978 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed())
979 << "Pipeline was: " << PipelineText;
981 } // end anonymous namespace