PassBuilderCallbacksTest.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  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. //===----------------------------------------------------------------------===//
  8. #include "llvm/Testing/Support/Error.h"
  9. #include <functional>
  10. #include <gmock/gmock.h>
  11. #include <gtest/gtest.h>
  12. #include <llvm/ADT/Any.h>
  13. #include <llvm/Analysis/CGSCCPassManager.h>
  14. #include <llvm/Analysis/LoopAnalysisManager.h>
  15. #include <llvm/AsmParser/Parser.h>
  16. #include <llvm/IR/LLVMContext.h>
  17. #include <llvm/IR/PassInstrumentation.h>
  18. #include <llvm/IR/PassManager.h>
  19. #include <llvm/Passes/PassBuilder.h>
  20. #include <llvm/Support/Regex.h>
  21. #include <llvm/Support/SourceMgr.h>
  22. #include <llvm/Transforms/Scalar/LoopPassManager.h>
  23. using namespace llvm;
  24. namespace {
  25. using testing::AnyNumber;
  26. using testing::AtLeast;
  27. using testing::DoDefault;
  28. using testing::Not;
  29. using testing::Return;
  30. using testing::Expectation;
  31. using testing::Invoke;
  32. using testing::WithArgs;
  33. using testing::_;
  34. /// A CRTP base for analysis mock handles
  35. ///
  36. /// This class reconciles mocking with the value semantics implementation of the
  37. /// AnalysisManager. Analysis mock handles should derive from this class and
  38. /// call \c setDefault() in their constroctur for wiring up the defaults defined
  39. /// by this base with their mock run() and invalidate() implementations.
  40. template <typename DerivedT, typename IRUnitT,
  41. typename AnalysisManagerT = AnalysisManager<IRUnitT>,
  42. typename... ExtraArgTs>
  43. class MockAnalysisHandleBase {
  44. public:
  45. class Analysis : public AnalysisInfoMixin<Analysis> {
  46. friend AnalysisInfoMixin<Analysis>;
  47. friend MockAnalysisHandleBase;
  48. static AnalysisKey Key;
  49. DerivedT *Handle;
  50. Analysis(DerivedT &Handle) : Handle(&Handle) {
  51. static_assert(std::is_base_of<MockAnalysisHandleBase, DerivedT>::value,
  52. "Must pass the derived type to this template!");
  53. }
  54. public:
  55. class Result {
  56. friend MockAnalysisHandleBase;
  57. DerivedT *Handle;
  58. Result(DerivedT &Handle) : Handle(&Handle) {}
  59. public:
  60. // Forward invalidation events to the mock handle.
  61. bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
  62. typename AnalysisManagerT::Invalidator &Inv) {
  63. return Handle->invalidate(IR, PA, Inv);
  64. }
  65. };
  66. Result run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) {
  67. return Handle->run(IR, AM, ExtraArgs...);
  68. }
  69. };
  70. Analysis getAnalysis() { return Analysis(static_cast<DerivedT &>(*this)); }
  71. typename Analysis::Result getResult() {
  72. return typename Analysis::Result(static_cast<DerivedT &>(*this));
  73. }
  74. static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
  75. protected:
  76. // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within
  77. // the template, so we use a boring static function.
  78. static bool invalidateCallback(IRUnitT &IR, const PreservedAnalyses &PA,
  79. typename AnalysisManagerT::Invalidator &Inv) {
  80. auto PAC = PA.template getChecker<Analysis>();
  81. return !PAC.preserved() &&
  82. !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
  83. }
  84. /// Derived classes should call this in their constructor to set up default
  85. /// mock actions. (We can't do this in our constructor because this has to
  86. /// run after the DerivedT is constructed.)
  87. void setDefaults() {
  88. ON_CALL(static_cast<DerivedT &>(*this),
  89. run(_, _, testing::Matcher<ExtraArgTs>(_)...))
  90. .WillByDefault(Return(this->getResult()));
  91. ON_CALL(static_cast<DerivedT &>(*this), invalidate(_, _, _))
  92. .WillByDefault(Invoke(&invalidateCallback));
  93. }
  94. };
  95. /// A CRTP base for pass mock handles
  96. ///
  97. /// This class reconciles mocking with the value semantics implementation of the
  98. /// PassManager. Pass mock handles should derive from this class and
  99. /// call \c setDefault() in their constroctur for wiring up the defaults defined
  100. /// by this base with their mock run() and invalidate() implementations.
  101. template <typename DerivedT, typename IRUnitT, typename AnalysisManagerT,
  102. typename... ExtraArgTs>
  103. AnalysisKey MockAnalysisHandleBase<DerivedT, IRUnitT, AnalysisManagerT,
  104. ExtraArgTs...>::Analysis::Key;
  105. template <typename DerivedT, typename IRUnitT,
  106. typename AnalysisManagerT = AnalysisManager<IRUnitT>,
  107. typename... ExtraArgTs>
  108. class MockPassHandleBase {
  109. public:
  110. class Pass : public PassInfoMixin<Pass> {
  111. friend MockPassHandleBase;
  112. DerivedT *Handle;
  113. Pass(DerivedT &Handle) : Handle(&Handle) {
  114. static_assert(std::is_base_of<MockPassHandleBase, DerivedT>::value,
  115. "Must pass the derived type to this template!");
  116. }
  117. public:
  118. PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
  119. ExtraArgTs... ExtraArgs) {
  120. return Handle->run(IR, AM, ExtraArgs...);
  121. }
  122. };
  123. static StringRef getName() { return llvm::getTypeName<DerivedT>(); }
  124. Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); }
  125. protected:
  126. /// Derived classes should call this in their constructor to set up default
  127. /// mock actions. (We can't do this in our constructor because this has to
  128. /// run after the DerivedT is constructed.)
  129. void setDefaults() {
  130. ON_CALL(static_cast<DerivedT &>(*this),
  131. run(_, _, testing::Matcher<ExtraArgTs>(_)...))
  132. .WillByDefault(Return(PreservedAnalyses::all()));
  133. }
  134. };
  135. /// Mock handles for passes for the IRUnits Module, CGSCC, Function, Loop.
  136. /// These handles define the appropriate run() mock interface for the respective
  137. /// IRUnit type.
  138. template <typename IRUnitT> struct MockPassHandle;
  139. template <>
  140. struct MockPassHandle<Loop>
  141. : MockPassHandleBase<MockPassHandle<Loop>, Loop, LoopAnalysisManager,
  142. LoopStandardAnalysisResults &, LPMUpdater &> {
  143. MOCK_METHOD4(run,
  144. PreservedAnalyses(Loop &, LoopAnalysisManager &,
  145. LoopStandardAnalysisResults &, LPMUpdater &));
  146. static void invalidateLoop(Loop &L, LoopAnalysisManager &,
  147. LoopStandardAnalysisResults &,
  148. LPMUpdater &Updater) {
  149. Updater.markLoopAsDeleted(L, L.getName());
  150. }
  151. MockPassHandle() { setDefaults(); }
  152. };
  153. template <>
  154. struct MockPassHandle<Function>
  155. : MockPassHandleBase<MockPassHandle<Function>, Function> {
  156. MOCK_METHOD2(run, PreservedAnalyses(Function &, FunctionAnalysisManager &));
  157. MockPassHandle() { setDefaults(); }
  158. };
  159. template <>
  160. struct MockPassHandle<LazyCallGraph::SCC>
  161. : MockPassHandleBase<MockPassHandle<LazyCallGraph::SCC>, LazyCallGraph::SCC,
  162. CGSCCAnalysisManager, LazyCallGraph &,
  163. CGSCCUpdateResult &> {
  164. MOCK_METHOD4(run,
  165. PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
  166. LazyCallGraph &G, CGSCCUpdateResult &UR));
  167. static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
  168. LazyCallGraph &, CGSCCUpdateResult &UR) {
  169. UR.InvalidatedSCCs.insert(&C);
  170. }
  171. MockPassHandle() { setDefaults(); }
  172. };
  173. template <>
  174. struct MockPassHandle<Module>
  175. : MockPassHandleBase<MockPassHandle<Module>, Module> {
  176. MOCK_METHOD2(run, PreservedAnalyses(Module &, ModuleAnalysisManager &));
  177. MockPassHandle() { setDefaults(); }
  178. };
  179. /// Mock handles for analyses for the IRUnits Module, CGSCC, Function, Loop.
  180. /// These handles define the appropriate run() and invalidate() mock interfaces
  181. /// for the respective IRUnit type.
  182. template <typename IRUnitT> struct MockAnalysisHandle;
  183. template <>
  184. struct MockAnalysisHandle<Loop>
  185. : MockAnalysisHandleBase<MockAnalysisHandle<Loop>, Loop,
  186. LoopAnalysisManager,
  187. LoopStandardAnalysisResults &> {
  188. MOCK_METHOD3_T(run, typename Analysis::Result(Loop &, LoopAnalysisManager &,
  189. LoopStandardAnalysisResults &));
  190. MOCK_METHOD3_T(invalidate, bool(Loop &, const PreservedAnalyses &,
  191. LoopAnalysisManager::Invalidator &));
  192. MockAnalysisHandle<Loop>() { this->setDefaults(); }
  193. };
  194. template <>
  195. struct MockAnalysisHandle<Function>
  196. : MockAnalysisHandleBase<MockAnalysisHandle<Function>, Function> {
  197. MOCK_METHOD2(run, Analysis::Result(Function &, FunctionAnalysisManager &));
  198. MOCK_METHOD3(invalidate, bool(Function &, const PreservedAnalyses &,
  199. FunctionAnalysisManager::Invalidator &));
  200. MockAnalysisHandle<Function>() { setDefaults(); }
  201. };
  202. template <>
  203. struct MockAnalysisHandle<LazyCallGraph::SCC>
  204. : MockAnalysisHandleBase<MockAnalysisHandle<LazyCallGraph::SCC>,
  205. LazyCallGraph::SCC, CGSCCAnalysisManager,
  206. LazyCallGraph &> {
  207. MOCK_METHOD3(run, Analysis::Result(LazyCallGraph::SCC &,
  208. CGSCCAnalysisManager &, LazyCallGraph &));
  209. MOCK_METHOD3(invalidate, bool(LazyCallGraph::SCC &, const PreservedAnalyses &,
  210. CGSCCAnalysisManager::Invalidator &));
  211. MockAnalysisHandle<LazyCallGraph::SCC>() { setDefaults(); }
  212. };
  213. template <>
  214. struct MockAnalysisHandle<Module>
  215. : MockAnalysisHandleBase<MockAnalysisHandle<Module>, Module> {
  216. MOCK_METHOD2(run, Analysis::Result(Module &, ModuleAnalysisManager &));
  217. MOCK_METHOD3(invalidate, bool(Module &, const PreservedAnalyses &,
  218. ModuleAnalysisManager::Invalidator &));
  219. MockAnalysisHandle<Module>() { setDefaults(); }
  220. };
  221. static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
  222. SMDiagnostic Err;
  223. return parseAssemblyString(IR, Err, C);
  224. }
  225. /// Helper for HasName matcher that returns getName both for IRUnit and
  226. /// for IRUnit pointer wrapper into llvm::Any (wrapped by PassInstrumentation).
  227. template <typename IRUnitT> std::string getName(const IRUnitT &IR) {
  228. return IR.getName();
  229. }
  230. template <> std::string getName(const StringRef &name) { return name; }
  231. template <> std::string getName(const llvm::Any &WrappedIR) {
  232. if (any_isa<const Module *>(WrappedIR))
  233. return any_cast<const Module *>(WrappedIR)->getName().str();
  234. if (any_isa<const Function *>(WrappedIR))
  235. return any_cast<const Function *>(WrappedIR)->getName().str();
  236. if (any_isa<const Loop *>(WrappedIR))
  237. return any_cast<const Loop *>(WrappedIR)->getName().str();
  238. if (any_isa<const LazyCallGraph::SCC *>(WrappedIR))
  239. return any_cast<const LazyCallGraph::SCC *>(WrappedIR)->getName();
  240. return "<UNKNOWN>";
  241. }
  242. /// Define a custom matcher for objects which support a 'getName' method.
  243. ///
  244. /// LLVM often has IR objects or analysis objects which expose a name
  245. /// and in tests it is convenient to match these by name for readability.
  246. /// Usually, this name is either a StringRef or a plain std::string. This
  247. /// matcher supports any type exposing a getName() method of this form whose
  248. /// return value is compatible with an std::ostream. For StringRef, this uses
  249. /// the shift operator defined above.
  250. ///
  251. /// It should be used as:
  252. ///
  253. /// HasName("my_function")
  254. ///
  255. /// No namespace or other qualification is required.
  256. MATCHER_P(HasName, Name, "") {
  257. *result_listener << "has name '" << getName(arg) << "'";
  258. return Name == getName(arg);
  259. }
  260. MATCHER_P(HasNameRegex, Name, "") {
  261. *result_listener << "has name '" << getName(arg) << "'";
  262. llvm::Regex r(Name);
  263. return r.match(getName(arg));
  264. }
  265. struct MockPassInstrumentationCallbacks {
  266. PassInstrumentationCallbacks Callbacks;
  267. MockPassInstrumentationCallbacks() {
  268. ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true));
  269. }
  270. MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
  271. MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any));
  272. MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID));
  273. MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
  274. MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
  275. void registerPassInstrumentation() {
  276. Callbacks.registerBeforePassCallback([this](StringRef P, llvm::Any IR) {
  277. return this->runBeforePass(P, IR);
  278. });
  279. Callbacks.registerAfterPassCallback(
  280. [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); });
  281. Callbacks.registerAfterPassInvalidatedCallback(
  282. [this](StringRef P) { this->runAfterPassInvalidated(P); });
  283. Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
  284. return this->runBeforeAnalysis(P, IR);
  285. });
  286. Callbacks.registerAfterAnalysisCallback(
  287. [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); });
  288. }
  289. void ignoreNonMockPassInstrumentation(StringRef IRName) {
  290. // Generic EXPECT_CALLs are needed to match instrumentation on unimportant
  291. // parts of a pipeline that we do not care about (e.g. various passes added
  292. // by default by PassBuilder - Verifier pass etc).
  293. // Make sure to avoid ignoring Mock passes/analysis, we definitely want
  294. // to check these explicitly.
  295. EXPECT_CALL(*this,
  296. runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
  297. .Times(AnyNumber());
  298. EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName)))
  299. .Times(AnyNumber());
  300. EXPECT_CALL(*this,
  301. runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
  302. .Times(AnyNumber());
  303. EXPECT_CALL(*this,
  304. runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName)))
  305. .Times(AnyNumber());
  306. }
  307. };
  308. template <typename PassManagerT> class PassBuilderCallbacksTest;
  309. /// This test fixture is shared between all the actual tests below and
  310. /// takes care of setting up appropriate defaults.
  311. ///
  312. /// The template specialization serves to extract the IRUnit and AM types from
  313. /// the given PassManagerT.
  314. template <typename TestIRUnitT, typename... ExtraPassArgTs,
  315. typename... ExtraAnalysisArgTs>
  316. class PassBuilderCallbacksTest<PassManager<
  317. TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>,
  318. ExtraPassArgTs...>> : public testing::Test {
  319. protected:
  320. using IRUnitT = TestIRUnitT;
  321. using AnalysisManagerT = AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>;
  322. using PassManagerT =
  323. PassManager<TestIRUnitT, AnalysisManagerT, ExtraPassArgTs...>;
  324. using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis;
  325. LLVMContext Context;
  326. std::unique_ptr<Module> M;
  327. MockPassInstrumentationCallbacks CallbacksHandle;
  328. PassBuilder PB;
  329. ModulePassManager PM;
  330. LoopAnalysisManager LAM;
  331. FunctionAnalysisManager FAM;
  332. CGSCCAnalysisManager CGAM;
  333. ModuleAnalysisManager AM;
  334. MockPassHandle<IRUnitT> PassHandle;
  335. MockAnalysisHandle<IRUnitT> AnalysisHandle;
  336. static PreservedAnalyses getAnalysisResult(IRUnitT &U, AnalysisManagerT &AM,
  337. ExtraAnalysisArgTs &&... Args) {
  338. (void)AM.template getResult<AnalysisT>(
  339. U, std::forward<ExtraAnalysisArgTs>(Args)...);
  340. return PreservedAnalyses::all();
  341. }
  342. PassBuilderCallbacksTest()
  343. : M(parseIR(Context,
  344. "declare void @bar()\n"
  345. "define void @foo(i32 %n) {\n"
  346. "entry:\n"
  347. " br label %loop\n"
  348. "loop:\n"
  349. " %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
  350. " %iv.next = add i32 %iv, 1\n"
  351. " tail call void @bar()\n"
  352. " %cmp = icmp eq i32 %iv, %n\n"
  353. " br i1 %cmp, label %exit, label %loop\n"
  354. "exit:\n"
  355. " ret void\n"
  356. "}\n")),
  357. CallbacksHandle(),
  358. PB(nullptr, PipelineTuningOptions(), None, &CallbacksHandle.Callbacks),
  359. PM(true), LAM(true), FAM(true), CGAM(true), AM(true) {
  360. /// Register a callback for analysis registration.
  361. ///
  362. /// The callback is a function taking a reference to an AnalyisManager
  363. /// object. When called, the callee gets to register its own analyses with
  364. /// this PassBuilder instance.
  365. PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) {
  366. // Register our mock analysis
  367. AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
  368. });
  369. /// Register a callback for pipeline parsing.
  370. ///
  371. /// During parsing of a textual pipeline, the PassBuilder will call these
  372. /// callbacks for each encountered pass name that it does not know. This
  373. /// includes both simple pass names as well as names of sub-pipelines. In
  374. /// the latter case, the InnerPipeline is not empty.
  375. PB.registerPipelineParsingCallback(
  376. [this](StringRef Name, PassManagerT &PM,
  377. ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
  378. /// Handle parsing of the names of analysis utilities such as
  379. /// require<test-analysis> and invalidate<test-analysis> for our
  380. /// analysis mock handle
  381. if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", Name, PM))
  382. return true;
  383. /// Parse the name of our pass mock handle
  384. if (Name == "test-transform") {
  385. PM.addPass(PassHandle.getPass());
  386. return true;
  387. }
  388. return false;
  389. });
  390. /// Register builtin analyses and cross-register the analysis proxies
  391. PB.registerModuleAnalyses(AM);
  392. PB.registerCGSCCAnalyses(CGAM);
  393. PB.registerFunctionAnalyses(FAM);
  394. PB.registerLoopAnalyses(LAM);
  395. PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
  396. }
  397. };
  398. using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
  399. using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
  400. using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>;
  401. using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
  402. /// Test parsing of the name of our mock pass for all IRUnits.
  403. ///
  404. /// The pass should by default run our mock analysis and then preserve it.
  405. TEST_F(ModuleCallbacksTest, Passes) {
  406. EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
  407. EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
  408. .WillOnce(Invoke(getAnalysisResult));
  409. StringRef PipelineText = "test-transform";
  410. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  411. << "Pipeline was: " << PipelineText;
  412. PM.run(*M, AM);
  413. }
  414. TEST_F(ModuleCallbacksTest, InstrumentedPasses) {
  415. EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
  416. EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
  417. .WillOnce(Invoke(getAnalysisResult));
  418. CallbacksHandle.registerPassInstrumentation();
  419. // Non-mock instrumentation not specifically mentioned below can be ignored.
  420. CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
  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, runBeforePass(HasNameRegex("MockPassHandle"),
  425. HasName("<string>")))
  426. .InSequence(PISequence);
  427. EXPECT_CALL(CallbacksHandle,
  428. runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"),
  429. HasName("<string>")))
  430. .InSequence(PISequence);
  431. EXPECT_CALL(
  432. CallbacksHandle,
  433. runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>")))
  434. .InSequence(PISequence);
  435. EXPECT_CALL(CallbacksHandle,
  436. runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>")))
  437. .InSequence(PISequence);
  438. StringRef PipelineText = "test-transform";
  439. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  440. << "Pipeline was: " << PipelineText;
  441. PM.run(*M, AM);
  442. }
  443. TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) {
  444. CallbacksHandle.registerPassInstrumentation();
  445. // Non-mock instrumentation run here can safely be ignored.
  446. CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
  447. // Skip the pass by returning false.
  448. EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
  449. HasName("<string>")))
  450. .WillOnce(Return(false));
  451. EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0);
  452. EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0);
  453. // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
  454. // as well.
  455. EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
  456. .Times(0);
  457. EXPECT_CALL(CallbacksHandle,
  458. runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
  459. .Times(0);
  460. EXPECT_CALL(CallbacksHandle,
  461. runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
  462. .Times(0);
  463. StringRef PipelineText = "test-transform";
  464. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  465. << "Pipeline was: " << PipelineText;
  466. PM.run(*M, AM);
  467. }
  468. TEST_F(FunctionCallbacksTest, Passes) {
  469. EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
  470. EXPECT_CALL(PassHandle, run(HasName("foo"), _))
  471. .WillOnce(Invoke(getAnalysisResult));
  472. StringRef PipelineText = "test-transform";
  473. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  474. << "Pipeline was: " << PipelineText;
  475. PM.run(*M, AM);
  476. }
  477. TEST_F(FunctionCallbacksTest, InstrumentedPasses) {
  478. CallbacksHandle.registerPassInstrumentation();
  479. // Non-mock instrumentation not specifically mentioned below can be ignored.
  480. CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
  481. CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
  482. EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
  483. EXPECT_CALL(PassHandle, run(HasName("foo"), _))
  484. .WillOnce(Invoke(getAnalysisResult));
  485. // PassInstrumentation calls should happen in-sequence, in the same order
  486. // as passes/analyses are scheduled.
  487. ::testing::Sequence PISequence;
  488. EXPECT_CALL(CallbacksHandle,
  489. runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
  490. .InSequence(PISequence);
  491. EXPECT_CALL(
  492. CallbacksHandle,
  493. runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
  494. .InSequence(PISequence);
  495. EXPECT_CALL(
  496. CallbacksHandle,
  497. runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo")))
  498. .InSequence(PISequence);
  499. EXPECT_CALL(CallbacksHandle,
  500. runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo")))
  501. .InSequence(PISequence);
  502. // Our mock pass does not invalidate IR.
  503. EXPECT_CALL(CallbacksHandle,
  504. runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
  505. .Times(0);
  506. StringRef PipelineText = "test-transform";
  507. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  508. << "Pipeline was: " << PipelineText;
  509. PM.run(*M, AM);
  510. }
  511. TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) {
  512. CallbacksHandle.registerPassInstrumentation();
  513. // Non-mock instrumentation run here can safely be ignored.
  514. CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
  515. CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
  516. // Skip the pass by returning false.
  517. EXPECT_CALL(CallbacksHandle,
  518. runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
  519. .WillOnce(Return(false));
  520. EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
  521. EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0);
  522. // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
  523. // as well.
  524. EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
  525. .Times(0);
  526. EXPECT_CALL(CallbacksHandle,
  527. runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
  528. .Times(0);
  529. EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
  530. .Times(0);
  531. EXPECT_CALL(CallbacksHandle,
  532. runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
  533. .Times(0);
  534. EXPECT_CALL(CallbacksHandle,
  535. runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
  536. .Times(0);
  537. StringRef PipelineText = "test-transform";
  538. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  539. << "Pipeline was: " << PipelineText;
  540. PM.run(*M, AM);
  541. }
  542. TEST_F(LoopCallbacksTest, Passes) {
  543. EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
  544. EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
  545. .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
  546. StringRef PipelineText = "test-transform";
  547. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  548. << "Pipeline was: " << PipelineText;
  549. PM.run(*M, AM);
  550. }
  551. TEST_F(LoopCallbacksTest, InstrumentedPasses) {
  552. CallbacksHandle.registerPassInstrumentation();
  553. // Non-mock instrumentation not specifically mentioned below can be ignored.
  554. CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
  555. CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
  556. CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
  557. EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
  558. EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
  559. .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
  560. // PassInstrumentation calls should happen in-sequence, in the same order
  561. // as passes/analyses are scheduled.
  562. ::testing::Sequence PISequence;
  563. EXPECT_CALL(CallbacksHandle,
  564. runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
  565. .InSequence(PISequence);
  566. EXPECT_CALL(
  567. CallbacksHandle,
  568. runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
  569. .InSequence(PISequence);
  570. EXPECT_CALL(
  571. CallbacksHandle,
  572. runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
  573. .InSequence(PISequence);
  574. EXPECT_CALL(CallbacksHandle,
  575. runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
  576. .InSequence(PISequence);
  577. // Our mock pass does not invalidate IR.
  578. EXPECT_CALL(CallbacksHandle,
  579. runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
  580. .Times(0);
  581. StringRef PipelineText = "test-transform";
  582. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  583. << "Pipeline was: " << PipelineText;
  584. PM.run(*M, AM);
  585. }
  586. TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
  587. CallbacksHandle.registerPassInstrumentation();
  588. // Non-mock instrumentation not specifically mentioned below can be ignored.
  589. CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
  590. CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
  591. CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
  592. EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
  593. EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
  594. .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateLoop)),
  595. WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
  596. // PassInstrumentation calls should happen in-sequence, in the same order
  597. // as passes/analyses are scheduled.
  598. ::testing::Sequence PISequence;
  599. EXPECT_CALL(CallbacksHandle,
  600. runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
  601. .InSequence(PISequence);
  602. EXPECT_CALL(
  603. CallbacksHandle,
  604. runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
  605. .InSequence(PISequence);
  606. EXPECT_CALL(
  607. CallbacksHandle,
  608. runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
  609. .InSequence(PISequence);
  610. EXPECT_CALL(CallbacksHandle,
  611. runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
  612. .InSequence(PISequence);
  613. EXPECT_CALL(CallbacksHandle,
  614. runAfterPassInvalidated(HasNameRegex("^PassManager")))
  615. .InSequence(PISequence);
  616. // Our mock pass invalidates IR, thus normal runAfterPass is never called.
  617. EXPECT_CALL(CallbacksHandle,
  618. runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
  619. .Times(0);
  620. StringRef PipelineText = "test-transform";
  621. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  622. << "Pipeline was: " << PipelineText;
  623. PM.run(*M, AM);
  624. }
  625. TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) {
  626. CallbacksHandle.registerPassInstrumentation();
  627. // Non-mock instrumentation run here can safely be ignored.
  628. CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
  629. CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
  630. CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
  631. // Skip the pass by returning false.
  632. EXPECT_CALL(CallbacksHandle,
  633. runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
  634. .WillOnce(Return(false));
  635. EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
  636. EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0);
  637. // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
  638. // as well.
  639. EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
  640. .Times(0);
  641. EXPECT_CALL(CallbacksHandle,
  642. runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
  643. .Times(0);
  644. EXPECT_CALL(CallbacksHandle,
  645. runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
  646. .Times(0);
  647. EXPECT_CALL(CallbacksHandle,
  648. runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
  649. .Times(0);
  650. StringRef PipelineText = "test-transform";
  651. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  652. << "Pipeline was: " << PipelineText;
  653. PM.run(*M, AM);
  654. }
  655. TEST_F(CGSCCCallbacksTest, Passes) {
  656. EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
  657. EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
  658. .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
  659. StringRef PipelineText = "test-transform";
  660. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  661. << "Pipeline was: " << PipelineText;
  662. PM.run(*M, AM);
  663. }
  664. TEST_F(CGSCCCallbacksTest, InstrumentedPasses) {
  665. CallbacksHandle.registerPassInstrumentation();
  666. // Non-mock instrumentation not specifically mentioned below can be ignored.
  667. CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
  668. CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
  669. CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
  670. EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
  671. EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
  672. .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
  673. // PassInstrumentation calls should happen in-sequence, in the same order
  674. // as passes/analyses are scheduled.
  675. ::testing::Sequence PISequence;
  676. EXPECT_CALL(CallbacksHandle,
  677. runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
  678. .InSequence(PISequence);
  679. EXPECT_CALL(
  680. CallbacksHandle,
  681. runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
  682. .InSequence(PISequence);
  683. EXPECT_CALL(
  684. CallbacksHandle,
  685. runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
  686. .InSequence(PISequence);
  687. EXPECT_CALL(CallbacksHandle,
  688. runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
  689. .InSequence(PISequence);
  690. // Our mock pass does not invalidate IR.
  691. EXPECT_CALL(CallbacksHandle,
  692. runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
  693. .Times(0);
  694. StringRef PipelineText = "test-transform";
  695. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  696. << "Pipeline was: " << PipelineText;
  697. PM.run(*M, AM);
  698. }
  699. TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
  700. CallbacksHandle.registerPassInstrumentation();
  701. // Non-mock instrumentation not specifically mentioned below can be ignored.
  702. CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
  703. CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
  704. CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
  705. EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
  706. EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
  707. .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateSCC)),
  708. WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
  709. // PassInstrumentation calls should happen in-sequence, in the same order
  710. // as passes/analyses are scheduled.
  711. ::testing::Sequence PISequence;
  712. EXPECT_CALL(CallbacksHandle,
  713. runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
  714. .InSequence(PISequence);
  715. EXPECT_CALL(
  716. CallbacksHandle,
  717. runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
  718. .InSequence(PISequence);
  719. EXPECT_CALL(
  720. CallbacksHandle,
  721. runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
  722. .InSequence(PISequence);
  723. EXPECT_CALL(CallbacksHandle,
  724. runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
  725. .InSequence(PISequence);
  726. EXPECT_CALL(CallbacksHandle,
  727. runAfterPassInvalidated(HasNameRegex("^PassManager")))
  728. .InSequence(PISequence);
  729. // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
  730. EXPECT_CALL(CallbacksHandle,
  731. runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
  732. .Times(0);
  733. StringRef PipelineText = "test-transform";
  734. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  735. << "Pipeline was: " << PipelineText;
  736. PM.run(*M, AM);
  737. }
  738. TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) {
  739. CallbacksHandle.registerPassInstrumentation();
  740. // Non-mock instrumentation run here can safely be ignored.
  741. CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
  742. CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
  743. CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
  744. // Skip the pass by returning false.
  745. EXPECT_CALL(CallbacksHandle,
  746. runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
  747. .WillOnce(Return(false));
  748. // neither Analysis nor Pass are called.
  749. EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0);
  750. EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0);
  751. // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
  752. // as well.
  753. EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
  754. .Times(0);
  755. EXPECT_CALL(CallbacksHandle,
  756. runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
  757. .Times(0);
  758. EXPECT_CALL(CallbacksHandle,
  759. runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
  760. .Times(0);
  761. EXPECT_CALL(CallbacksHandle,
  762. runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _))
  763. .Times(0);
  764. StringRef PipelineText = "test-transform";
  765. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  766. << "Pipeline was: " << PipelineText;
  767. PM.run(*M, AM);
  768. }
  769. /// Test parsing of the names of analysis utilities for our mock analysis
  770. /// for all IRUnits.
  771. ///
  772. /// We first require<>, then invalidate<> it, expecting the analysis to be run
  773. /// once and subsequently invalidated.
  774. TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
  775. EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
  776. EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
  777. StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
  778. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  779. << "Pipeline was: " << PipelineText;
  780. PM.run(*M, AM);
  781. }
  782. TEST_F(CGSCCCallbacksTest, PassUtilities) {
  783. EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
  784. EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
  785. StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
  786. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  787. << "Pipeline was: " << PipelineText;
  788. PM.run(*M, AM);
  789. }
  790. TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
  791. EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
  792. EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
  793. StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
  794. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  795. << "Pipeline was: " << PipelineText;
  796. PM.run(*M, AM);
  797. }
  798. TEST_F(LoopCallbacksTest, PassUtilities) {
  799. EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
  800. EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
  801. StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>";
  802. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  803. << "Pipeline was: " << PipelineText;
  804. PM.run(*M, AM);
  805. }
  806. /// Test parsing of the top-level pipeline.
  807. ///
  808. /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline
  809. /// from PassBuilder if it encounters an unknown pipeline entry at the top level
  810. /// (i.e., the first entry on the pipeline).
  811. /// This test parses a pipeline named 'another-pipeline', whose only elements
  812. /// may be the test-transform pass or the analysis utilities
  813. TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
  814. PB.registerParseTopLevelPipelineCallback([this](
  815. ModulePassManager &MPM, ArrayRef<PassBuilder::PipelineElement> Pipeline,
  816. bool VerifyEachPass, bool DebugLogging) {
  817. auto &FirstName = Pipeline.front().Name;
  818. auto &InnerPipeline = Pipeline.front().InnerPipeline;
  819. if (FirstName == "another-pipeline") {
  820. for (auto &E : InnerPipeline) {
  821. if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", E.Name, PM))
  822. continue;
  823. if (E.Name == "test-transform") {
  824. PM.addPass(PassHandle.getPass());
  825. continue;
  826. }
  827. return false;
  828. }
  829. }
  830. return true;
  831. });
  832. EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
  833. EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
  834. .WillOnce(Invoke(getAnalysisResult));
  835. EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
  836. StringRef PipelineText =
  837. "another-pipeline(test-transform,invalidate<test-analysis>)";
  838. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
  839. << "Pipeline was: " << PipelineText;
  840. PM.run(*M, AM);
  841. /// Test the negative case
  842. PipelineText = "another-pipeline(instcombine)";
  843. ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed())
  844. << "Pipeline was: " << PipelineText;
  845. }
  846. } // end anonymous namespace