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 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> 24 25 using namespace llvm; 26 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::_; 37 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; 53 54 DerivedT *Handle; 55 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!"); 59 } 60 61 public: 62 class Result { 63 friend MockAnalysisHandleBase; 64 65 DerivedT *Handle; 66 67 Result(DerivedT &Handle) : Handle(&Handle) {} 68 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); 74 } 75 }; 76 77 Result run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) { 78 return Handle->run(IR, AM, ExtraArgs...); 79 } 80 }; 81 82 Analysis getAnalysis() { return Analysis(static_cast<DerivedT &>(*this)); } 83 typename Analysis::Result getResult() { 84 return typename Analysis::Result(static_cast<DerivedT &>(*this)); 85 } 86 static StringRef getName() { return llvm::getTypeName<DerivedT>(); } 87 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>>(); 96 } 97 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)); 107 } 108 }; 109 110 /// A CRTP base for pass mock handles 111 /// 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; 120 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; 128 129 DerivedT *Handle; 130 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!"); 134 } 135 136 public: 137 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, 138 ExtraArgTs... ExtraArgs) { 139 return Handle->run(IR, AM, ExtraArgs...); 140 } 141 }; 142 143 static StringRef getName() { return llvm::getTypeName<DerivedT>(); } 144 145 Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); } 146 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())); 155 } 156 }; 157 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()); 173 } 174 MockPassHandle() { setDefaults(); } 175 }; 176 177 template <> 178 struct MockPassHandle<Function> 179 : MockPassHandleBase<MockPassHandle<Function>, Function> { 180 MOCK_METHOD2(run, PreservedAnalyses(Function &, FunctionAnalysisManager &)); 181 182 MockPassHandle() { setDefaults(); } 183 }; 184 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)); 193 194 static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &, 195 LazyCallGraph &, CGSCCUpdateResult &UR) { 196 UR.InvalidatedSCCs.insert(&C); 197 } 198 199 MockPassHandle() { setDefaults(); } 200 }; 201 202 template <> 203 struct MockPassHandle<Module> 204 : MockPassHandleBase<MockPassHandle<Module>, Module> { 205 MOCK_METHOD2(run, PreservedAnalyses(Module &, ModuleAnalysisManager &)); 206 207 MockPassHandle() { setDefaults(); } 208 }; 209 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 &> { 219 220 MOCK_METHOD3_T(run, typename Analysis::Result(Loop &, LoopAnalysisManager &, 221 LoopStandardAnalysisResults &)); 222 223 MOCK_METHOD3_T(invalidate, bool(Loop &, const PreservedAnalyses &, 224 LoopAnalysisManager::Invalidator &)); 225 226 MockAnalysisHandle<Loop>() { this->setDefaults(); } 227 }; 228 229 template <> 230 struct MockAnalysisHandle<Function> 231 : MockAnalysisHandleBase<MockAnalysisHandle<Function>, Function> { 232 MOCK_METHOD2(run, Analysis::Result(Function &, FunctionAnalysisManager &)); 233 234 MOCK_METHOD3(invalidate, bool(Function &, const PreservedAnalyses &, 235 FunctionAnalysisManager::Invalidator &)); 236 237 MockAnalysisHandle<Function>() { setDefaults(); } 238 }; 239 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 &)); 247 248 MOCK_METHOD3(invalidate, bool(LazyCallGraph::SCC &, const PreservedAnalyses &, 249 CGSCCAnalysisManager::Invalidator &)); 250 251 MockAnalysisHandle<LazyCallGraph::SCC>() { setDefaults(); } 252 }; 253 254 template <> 255 struct MockAnalysisHandle<Module> 256 : MockAnalysisHandleBase<MockAnalysisHandle<Module>, Module> { 257 MOCK_METHOD2(run, Analysis::Result(Module &, ModuleAnalysisManager &)); 258 259 MOCK_METHOD3(invalidate, bool(Module &, const PreservedAnalyses &, 260 ModuleAnalysisManager::Invalidator &)); 261 262 MockAnalysisHandle<Module>() { setDefaults(); } 263 }; 264 265 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { 266 SMDiagnostic Err; 267 return parseAssemblyString(IR, Err, C); 268 } 269 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 std::string(IR.getName()); 274 } 275 276 template <> std::string getName(const StringRef &name) { 277 return std::string(name); 278 } 279 280 template <> std::string getName(const llvm::Any &WrappedIR) { 281 if (any_isa<const Module *>(WrappedIR)) 282 return any_cast<const Module *>(WrappedIR)->getName().str(); 283 if (any_isa<const Function *>(WrappedIR)) 284 return any_cast<const Function *>(WrappedIR)->getName().str(); 285 if (any_isa<const Loop *>(WrappedIR)) 286 return any_cast<const Loop *>(WrappedIR)->getName().str(); 287 if (any_isa<const LazyCallGraph::SCC *>(WrappedIR)) 288 return any_cast<const LazyCallGraph::SCC *>(WrappedIR)->getName(); 289 return "<UNKNOWN>"; 290 } 291 /// Define a custom matcher for objects which support a 'getName' method. 292 /// 293 /// LLVM often has IR objects or analysis objects which expose a name 294 /// and in tests it is convenient to match these by name for readability. 295 /// Usually, this name is either a StringRef or a plain std::string. This 296 /// matcher supports any type exposing a getName() method of this form whose 297 /// return value is compatible with an std::ostream. For StringRef, this uses 298 /// the shift operator defined above. 299 /// 300 /// It should be used as: 301 /// 302 /// HasName("my_function") 303 /// 304 /// No namespace or other qualification is required. 305 MATCHER_P(HasName, Name, "") { 306 *result_listener << "has name '" << getName(arg) << "'"; 307 return Name == getName(arg); 308 } 309 310 MATCHER_P(HasNameRegex, Name, "") { 311 *result_listener << "has name '" << getName(arg) << "'"; 312 llvm::Regex r(Name); 313 return r.match(getName(arg)); 314 } 315 316 struct MockPassInstrumentationCallbacks { 317 PassInstrumentationCallbacks Callbacks; 318 319 MockPassInstrumentationCallbacks() { 320 ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true)); 321 } 322 MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any)); 323 MOCK_METHOD2(runBeforeNonSkippedPass, void(StringRef PassID, llvm::Any)); 324 MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any)); 325 MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID)); 326 MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any)); 327 MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any)); 328 329 void registerPassInstrumentation() { 330 Callbacks.registerBeforePassCallback([this](StringRef P, llvm::Any IR) { 331 return this->runBeforePass(P, IR); 332 }); 333 Callbacks.registerBeforeNonSkippedPassCallback( 334 [this](StringRef P, llvm::Any IR) { 335 this->runBeforeNonSkippedPass(P, IR); 336 }); 337 Callbacks.registerAfterPassCallback( 338 [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); }); 339 Callbacks.registerAfterPassInvalidatedCallback( 340 [this](StringRef P) { this->runAfterPassInvalidated(P); }); 341 Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) { 342 return this->runBeforeAnalysis(P, IR); 343 }); 344 Callbacks.registerAfterAnalysisCallback( 345 [this](StringRef P, llvm::Any IR) { this->runAfterAnalysis(P, IR); }); 346 } 347 348 void ignoreNonMockPassInstrumentation(StringRef IRName) { 349 // Generic EXPECT_CALLs are needed to match instrumentation on unimportant 350 // parts of a pipeline that we do not care about (e.g. various passes added 351 // by default by PassBuilder - Verifier pass etc). 352 // Make sure to avoid ignoring Mock passes/analysis, we definitely want 353 // to check these explicitly. 354 EXPECT_CALL(*this, 355 runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName))) 356 .Times(AnyNumber()); 357 EXPECT_CALL(*this, runBeforeNonSkippedPass(Not(HasNameRegex("Mock")), 358 HasName(IRName))) 359 .Times(AnyNumber()); 360 EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName))) 361 .Times(AnyNumber()); 362 EXPECT_CALL(*this, 363 runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName))) 364 .Times(AnyNumber()); 365 EXPECT_CALL(*this, 366 runAfterAnalysis(Not(HasNameRegex("Mock")), HasName(IRName))) 367 .Times(AnyNumber()); 368 } 369 }; 370 371 template <typename PassManagerT> class PassBuilderCallbacksTest; 372 373 /// This test fixture is shared between all the actual tests below and 374 /// takes care of setting up appropriate defaults. 375 /// 376 /// The template specialization serves to extract the IRUnit and AM types from 377 /// the given PassManagerT. 378 template <typename TestIRUnitT, typename... ExtraPassArgTs, 379 typename... ExtraAnalysisArgTs> 380 class PassBuilderCallbacksTest<PassManager< 381 TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>, 382 ExtraPassArgTs...>> : public testing::Test { 383 protected: 384 using IRUnitT = TestIRUnitT; 385 using AnalysisManagerT = AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>; 386 using PassManagerT = 387 PassManager<TestIRUnitT, AnalysisManagerT, ExtraPassArgTs...>; 388 using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis; 389 390 LLVMContext Context; 391 std::unique_ptr<Module> M; 392 393 MockPassInstrumentationCallbacks CallbacksHandle; 394 395 PassBuilder PB; 396 ModulePassManager PM; 397 LoopAnalysisManager LAM; 398 FunctionAnalysisManager FAM; 399 CGSCCAnalysisManager CGAM; 400 ModuleAnalysisManager AM; 401 402 MockPassHandle<IRUnitT> PassHandle; 403 MockAnalysisHandle<IRUnitT> AnalysisHandle; 404 405 static PreservedAnalyses getAnalysisResult(IRUnitT &U, AnalysisManagerT &AM, 406 ExtraAnalysisArgTs &&... Args) { 407 (void)AM.template getResult<AnalysisT>( 408 U, std::forward<ExtraAnalysisArgTs>(Args)...); 409 return PreservedAnalyses::all(); 410 } 411 412 PassBuilderCallbacksTest() 413 : M(parseIR(Context, 414 "declare void @bar()\n" 415 "define void @foo(i32 %n) {\n" 416 "entry:\n" 417 " br label %loop\n" 418 "loop:\n" 419 " %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n" 420 " %iv.next = add i32 %iv, 1\n" 421 " tail call void @bar()\n" 422 " %cmp = icmp eq i32 %iv, %n\n" 423 " br i1 %cmp, label %exit, label %loop\n" 424 "exit:\n" 425 " ret void\n" 426 "}\n")), 427 CallbacksHandle(), 428 PB(nullptr, PipelineTuningOptions(), None, &CallbacksHandle.Callbacks), 429 PM(true), LAM(true), FAM(true), CGAM(true), AM(true) { 430 431 EXPECT_TRUE(&CallbacksHandle.Callbacks == 432 PB.getPassInstrumentationCallbacks()); 433 434 /// Register a callback for analysis registration. 435 /// 436 /// The callback is a function taking a reference to an AnalyisManager 437 /// object. When called, the callee gets to register its own analyses with 438 /// this PassBuilder instance. 439 PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT &AM) { 440 // Register our mock analysis 441 AM.registerPass([this] { return AnalysisHandle.getAnalysis(); }); 442 }); 443 444 /// Register a callback for pipeline parsing. 445 /// 446 /// During parsing of a textual pipeline, the PassBuilder will call these 447 /// callbacks for each encountered pass name that it does not know. This 448 /// includes both simple pass names as well as names of sub-pipelines. In 449 /// the latter case, the InnerPipeline is not empty. 450 PB.registerPipelineParsingCallback( 451 [this](StringRef Name, PassManagerT &PM, 452 ArrayRef<PassBuilder::PipelineElement> InnerPipeline) { 453 /// Handle parsing of the names of analysis utilities such as 454 /// require<test-analysis> and invalidate<test-analysis> for our 455 /// analysis mock handle 456 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", Name, PM)) 457 return true; 458 459 /// Parse the name of our pass mock handle 460 if (Name == "test-transform") { 461 PM.addPass(PassHandle.getPass()); 462 return true; 463 } 464 return false; 465 }); 466 467 /// Register builtin analyses and cross-register the analysis proxies 468 PB.registerModuleAnalyses(AM); 469 PB.registerCGSCCAnalyses(CGAM); 470 PB.registerFunctionAnalyses(FAM); 471 PB.registerLoopAnalyses(LAM); 472 PB.crossRegisterProxies(LAM, FAM, CGAM, AM); 473 } 474 }; 475 476 using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>; 477 using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>; 478 using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>; 479 using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>; 480 481 /// Test parsing of the name of our mock pass for all IRUnits. 482 /// 483 /// The pass should by default run our mock analysis and then preserve it. 484 TEST_F(ModuleCallbacksTest, Passes) { 485 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)); 486 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)) 487 .WillOnce(Invoke(getAnalysisResult)); 488 489 StringRef PipelineText = "test-transform"; 490 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 491 << "Pipeline was: " << PipelineText; 492 493 PM.run(*M, AM); 494 } 495 496 TEST_F(ModuleCallbacksTest, InstrumentedPasses) { 497 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)); 498 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)) 499 .WillOnce(Invoke(getAnalysisResult)); 500 501 CallbacksHandle.registerPassInstrumentation(); 502 // Non-mock instrumentation not specifically mentioned below can be ignored. 503 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); 504 505 // PassInstrumentation calls should happen in-sequence, in the same order 506 // as passes/analyses are scheduled. 507 ::testing::Sequence PISequence; 508 EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), 509 HasName("<string>"))) 510 .InSequence(PISequence); 511 EXPECT_CALL(CallbacksHandle, 512 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), 513 HasName("<string>"))) 514 .InSequence(PISequence); 515 EXPECT_CALL(CallbacksHandle, 516 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), 517 HasName("<string>"))) 518 .InSequence(PISequence); 519 EXPECT_CALL( 520 CallbacksHandle, 521 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("<string>"))) 522 .InSequence(PISequence); 523 EXPECT_CALL(CallbacksHandle, 524 runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>"))) 525 .InSequence(PISequence); 526 527 StringRef PipelineText = "test-transform"; 528 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 529 << "Pipeline was: " << PipelineText; 530 531 PM.run(*M, AM); 532 } 533 534 TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) { 535 CallbacksHandle.registerPassInstrumentation(); 536 // Non-mock instrumentation run here can safely be ignored. 537 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); 538 539 // Skip all passes by returning false. Pass managers and adaptor passes are 540 // also passes that observed by the callbacks. 541 EXPECT_CALL(CallbacksHandle, runBeforePass(_, _)) 542 .WillRepeatedly(Return(false)); 543 544 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0); 545 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0); 546 547 // As the pass is skipped there is no nonskippedpass/afterPass, 548 // beforeAnalysis/afterAnalysis as well. 549 EXPECT_CALL(CallbacksHandle, 550 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _)) 551 .Times(0); 552 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) 553 .Times(0); 554 EXPECT_CALL(CallbacksHandle, 555 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) 556 .Times(0); 557 EXPECT_CALL(CallbacksHandle, 558 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _)) 559 .Times(0); 560 561 // Order is important here. `Adaptor` expectations should be checked first 562 // because the its argument contains 'PassManager' (for example: 563 // ModuleToFunctionPassAdaptor{{.*}}PassManager{{.*}}). Check 564 // `runBeforeNonSkippedPass` and `runAfterPass` to show that they are not 565 // skipped. 566 // 567 // Pass managers are not ignored. 568 // 5 = (1) ModulePassManager + (2) FunctionPassMangers + (1) LoopPassManager + 569 // (1) CGSCCPassManager 570 EXPECT_CALL(CallbacksHandle, 571 runBeforeNonSkippedPass(HasNameRegex("PassManager"), _)) 572 .Times(5); 573 EXPECT_CALL( 574 CallbacksHandle, 575 runBeforeNonSkippedPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _)) 576 .Times(1); 577 EXPECT_CALL(CallbacksHandle, 578 runBeforeNonSkippedPass( 579 HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _)) 580 .Times(1); 581 EXPECT_CALL( 582 CallbacksHandle, 583 runBeforeNonSkippedPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _)) 584 .Times(1); 585 EXPECT_CALL( 586 CallbacksHandle, 587 runBeforeNonSkippedPass(HasNameRegex("FunctionToLoopPassAdaptor"), _)) 588 .Times(1); 589 590 // The `runAfterPass` checks are the same as these of 591 // `runBeforeNonSkippedPass`. 592 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("PassManager"), _)) 593 .Times(5); 594 EXPECT_CALL(CallbacksHandle, 595 runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _)) 596 .Times(1); 597 EXPECT_CALL( 598 CallbacksHandle, 599 runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _)) 600 .Times(1); 601 EXPECT_CALL(CallbacksHandle, 602 runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _)) 603 .Times(1); 604 EXPECT_CALL(CallbacksHandle, 605 runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _)) 606 .Times(1); 607 608 // Ignore analyses introduced by adaptor passes. 609 EXPECT_CALL(CallbacksHandle, 610 runBeforeAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _)) 611 .Times(AnyNumber()); 612 EXPECT_CALL(CallbacksHandle, 613 runAfterAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _)) 614 .Times(AnyNumber()); 615 616 // Register Funtion and Loop version of "test-transform" for testing 617 PB.registerPipelineParsingCallback( 618 [](StringRef Name, FunctionPassManager &FPM, 619 ArrayRef<PassBuilder::PipelineElement>) { 620 if (Name == "test-transform") { 621 FPM.addPass(MockPassHandle<Function>().getPass()); 622 return true; 623 } 624 return false; 625 }); 626 PB.registerPipelineParsingCallback( 627 [](StringRef Name, LoopPassManager &LPM, 628 ArrayRef<PassBuilder::PipelineElement>) { 629 if (Name == "test-transform") { 630 LPM.addPass(MockPassHandle<Loop>().getPass()); 631 return true; 632 } 633 return false; 634 }); 635 636 StringRef PipelineText = "test-transform,function(test-transform),cgscc(" 637 "function(loop(test-transform)))"; 638 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 639 << "Pipeline was: " << PipelineText; 640 641 PM.run(*M, AM); 642 } 643 644 TEST_F(FunctionCallbacksTest, Passes) { 645 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)); 646 EXPECT_CALL(PassHandle, run(HasName("foo"), _)) 647 .WillOnce(Invoke(getAnalysisResult)); 648 649 StringRef PipelineText = "test-transform"; 650 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 651 << "Pipeline was: " << PipelineText; 652 PM.run(*M, AM); 653 } 654 655 TEST_F(FunctionCallbacksTest, InstrumentedPasses) { 656 CallbacksHandle.registerPassInstrumentation(); 657 // Non-mock instrumentation not specifically mentioned below can be ignored. 658 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); 659 CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); 660 661 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)); 662 EXPECT_CALL(PassHandle, run(HasName("foo"), _)) 663 .WillOnce(Invoke(getAnalysisResult)); 664 665 // PassInstrumentation calls should happen in-sequence, in the same order 666 // as passes/analyses are scheduled. 667 ::testing::Sequence PISequence; 668 EXPECT_CALL(CallbacksHandle, 669 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo"))) 670 .InSequence(PISequence); 671 EXPECT_CALL( 672 CallbacksHandle, 673 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("foo"))) 674 .InSequence(PISequence); 675 EXPECT_CALL( 676 CallbacksHandle, 677 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo"))) 678 .InSequence(PISequence); 679 EXPECT_CALL( 680 CallbacksHandle, 681 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo"))) 682 .InSequence(PISequence); 683 EXPECT_CALL(CallbacksHandle, 684 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo"))) 685 .InSequence(PISequence); 686 687 // Our mock pass does not invalidate IR. 688 EXPECT_CALL(CallbacksHandle, 689 runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) 690 .Times(0); 691 692 StringRef PipelineText = "test-transform"; 693 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 694 << "Pipeline was: " << PipelineText; 695 PM.run(*M, AM); 696 } 697 698 TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) { 699 CallbacksHandle.registerPassInstrumentation(); 700 // Non-mock instrumentation run here can safely be ignored. 701 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); 702 CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); 703 704 // Skip the pass by returning false. 705 EXPECT_CALL(CallbacksHandle, 706 runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo"))) 707 .WillOnce(Return(false)); 708 709 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0); 710 EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0); 711 712 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis 713 // as well. 714 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) 715 .Times(0); 716 EXPECT_CALL(CallbacksHandle, 717 runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) 718 .Times(0); 719 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) 720 .Times(0); 721 EXPECT_CALL(CallbacksHandle, 722 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) 723 .Times(0); 724 EXPECT_CALL(CallbacksHandle, 725 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _)) 726 .Times(0); 727 728 StringRef PipelineText = "test-transform"; 729 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 730 << "Pipeline was: " << PipelineText; 731 PM.run(*M, AM); 732 } 733 734 TEST_F(LoopCallbacksTest, Passes) { 735 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)); 736 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)) 737 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult))); 738 739 StringRef PipelineText = "test-transform"; 740 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 741 << "Pipeline was: " << PipelineText; 742 PM.run(*M, AM); 743 } 744 745 TEST_F(LoopCallbacksTest, InstrumentedPasses) { 746 CallbacksHandle.registerPassInstrumentation(); 747 // Non-mock instrumentation not specifically mentioned below can be ignored. 748 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); 749 CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); 750 CallbacksHandle.ignoreNonMockPassInstrumentation("loop"); 751 752 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)); 753 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)) 754 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult))); 755 756 // PassInstrumentation calls should happen in-sequence, in the same order 757 // as passes/analyses are scheduled. 758 ::testing::Sequence PISequence; 759 EXPECT_CALL(CallbacksHandle, 760 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop"))) 761 .InSequence(PISequence); 762 EXPECT_CALL( 763 CallbacksHandle, 764 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop"))) 765 .InSequence(PISequence); 766 EXPECT_CALL( 767 CallbacksHandle, 768 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop"))) 769 .InSequence(PISequence); 770 EXPECT_CALL( 771 CallbacksHandle, 772 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop"))) 773 .InSequence(PISequence); 774 EXPECT_CALL(CallbacksHandle, 775 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"))) 776 .InSequence(PISequence); 777 778 // Our mock pass does not invalidate IR. 779 EXPECT_CALL(CallbacksHandle, 780 runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) 781 .Times(0); 782 783 StringRef PipelineText = "test-transform"; 784 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 785 << "Pipeline was: " << PipelineText; 786 PM.run(*M, AM); 787 } 788 789 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) { 790 CallbacksHandle.registerPassInstrumentation(); 791 // Non-mock instrumentation not specifically mentioned below can be ignored. 792 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); 793 CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); 794 CallbacksHandle.ignoreNonMockPassInstrumentation("loop"); 795 796 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)); 797 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)) 798 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateLoop)), 799 WithArgs<0, 1, 2>(Invoke(getAnalysisResult)))); 800 801 // PassInstrumentation calls should happen in-sequence, in the same order 802 // as passes/analyses are scheduled. 803 ::testing::Sequence PISequence; 804 EXPECT_CALL(CallbacksHandle, 805 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop"))) 806 .InSequence(PISequence); 807 EXPECT_CALL( 808 CallbacksHandle, 809 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("loop"))) 810 .InSequence(PISequence); 811 EXPECT_CALL( 812 CallbacksHandle, 813 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop"))) 814 .InSequence(PISequence); 815 EXPECT_CALL( 816 CallbacksHandle, 817 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop"))) 818 .InSequence(PISequence); 819 EXPECT_CALL(CallbacksHandle, 820 runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) 821 .InSequence(PISequence); 822 EXPECT_CALL(CallbacksHandle, 823 runAfterPassInvalidated(HasNameRegex("^PassManager"))) 824 .InSequence(PISequence); 825 826 // Our mock pass invalidates IR, thus normal runAfterPass is never called. 827 EXPECT_CALL(CallbacksHandle, 828 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"))) 829 .Times(0); 830 831 StringRef PipelineText = "test-transform"; 832 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 833 << "Pipeline was: " << PipelineText; 834 PM.run(*M, AM); 835 } 836 837 TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) { 838 CallbacksHandle.registerPassInstrumentation(); 839 // Non-mock instrumentation run here can safely be ignored. 840 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); 841 CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); 842 CallbacksHandle.ignoreNonMockPassInstrumentation("loop"); 843 844 // Skip the pass by returning false. 845 EXPECT_CALL(CallbacksHandle, 846 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop"))) 847 .WillOnce(Return(false)); 848 849 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0); 850 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0); 851 852 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis 853 // as well. 854 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) 855 .Times(0); 856 EXPECT_CALL(CallbacksHandle, 857 runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) 858 .Times(0); 859 EXPECT_CALL(CallbacksHandle, 860 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) 861 .Times(0); 862 EXPECT_CALL(CallbacksHandle, 863 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _)) 864 .Times(0); 865 866 StringRef PipelineText = "test-transform"; 867 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 868 << "Pipeline was: " << PipelineText; 869 PM.run(*M, AM); 870 } 871 872 TEST_F(CGSCCCallbacksTest, Passes) { 873 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)); 874 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)) 875 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult))); 876 877 StringRef PipelineText = "test-transform"; 878 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 879 << "Pipeline was: " << PipelineText; 880 PM.run(*M, AM); 881 } 882 883 TEST_F(CGSCCCallbacksTest, InstrumentedPasses) { 884 CallbacksHandle.registerPassInstrumentation(); 885 // Non-mock instrumentation not specifically mentioned below can be ignored. 886 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); 887 CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); 888 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)"); 889 890 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)); 891 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)) 892 .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult))); 893 894 // PassInstrumentation calls should happen in-sequence, in the same order 895 // as passes/analyses are scheduled. 896 ::testing::Sequence PISequence; 897 EXPECT_CALL(CallbacksHandle, 898 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) 899 .InSequence(PISequence); 900 EXPECT_CALL( 901 CallbacksHandle, 902 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) 903 .InSequence(PISequence); 904 EXPECT_CALL( 905 CallbacksHandle, 906 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)"))) 907 .InSequence(PISequence); 908 EXPECT_CALL( 909 CallbacksHandle, 910 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)"))) 911 .InSequence(PISequence); 912 EXPECT_CALL(CallbacksHandle, 913 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) 914 .InSequence(PISequence); 915 916 // Our mock pass does not invalidate IR. 917 EXPECT_CALL(CallbacksHandle, 918 runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) 919 .Times(0); 920 921 StringRef PipelineText = "test-transform"; 922 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 923 << "Pipeline was: " << PipelineText; 924 PM.run(*M, AM); 925 } 926 927 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) { 928 CallbacksHandle.registerPassInstrumentation(); 929 // Non-mock instrumentation not specifically mentioned below can be ignored. 930 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); 931 CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); 932 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)"); 933 934 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)); 935 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)) 936 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateSCC)), 937 WithArgs<0, 1, 2>(Invoke(getAnalysisResult)))); 938 939 // PassInstrumentation calls should happen in-sequence, in the same order 940 // as passes/analyses are scheduled. 941 ::testing::Sequence PISequence; 942 EXPECT_CALL(CallbacksHandle, 943 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) 944 .InSequence(PISequence); 945 EXPECT_CALL( 946 CallbacksHandle, 947 runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) 948 .InSequence(PISequence); 949 EXPECT_CALL( 950 CallbacksHandle, 951 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)"))) 952 .InSequence(PISequence); 953 EXPECT_CALL( 954 CallbacksHandle, 955 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)"))) 956 .InSequence(PISequence); 957 EXPECT_CALL(CallbacksHandle, 958 runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) 959 .InSequence(PISequence); 960 EXPECT_CALL(CallbacksHandle, 961 runAfterPassInvalidated(HasNameRegex("^PassManager"))) 962 .InSequence(PISequence); 963 964 // Our mock pass does invalidate IR, thus normal runAfterPass is never called. 965 EXPECT_CALL(CallbacksHandle, 966 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) 967 .Times(0); 968 969 StringRef PipelineText = "test-transform"; 970 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 971 << "Pipeline was: " << PipelineText; 972 PM.run(*M, AM); 973 } 974 975 TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) { 976 CallbacksHandle.registerPassInstrumentation(); 977 // Non-mock instrumentation run here can safely be ignored. 978 CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); 979 CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); 980 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)"); 981 982 // Skip the pass by returning false. 983 EXPECT_CALL(CallbacksHandle, 984 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) 985 .WillOnce(Return(false)); 986 987 // neither Analysis nor Pass are called. 988 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0); 989 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0); 990 991 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis 992 // as well. 993 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) 994 .Times(0); 995 EXPECT_CALL(CallbacksHandle, 996 runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) 997 .Times(0); 998 EXPECT_CALL(CallbacksHandle, 999 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) 1000 .Times(0); 1001 EXPECT_CALL(CallbacksHandle, 1002 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _)) 1003 .Times(0); 1004 1005 StringRef PipelineText = "test-transform"; 1006 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 1007 << "Pipeline was: " << PipelineText; 1008 PM.run(*M, AM); 1009 } 1010 1011 /// Test parsing of the names of analysis utilities for our mock analysis 1012 /// for all IRUnits. 1013 /// 1014 /// We first require<>, then invalidate<> it, expecting the analysis to be run 1015 /// once and subsequently invalidated. 1016 TEST_F(ModuleCallbacksTest, AnalysisUtilities) { 1017 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)); 1018 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _)); 1019 1020 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>"; 1021 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 1022 << "Pipeline was: " << PipelineText; 1023 PM.run(*M, AM); 1024 } 1025 1026 TEST_F(CGSCCCallbacksTest, PassUtilities) { 1027 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)); 1028 EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _)); 1029 1030 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>"; 1031 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 1032 << "Pipeline was: " << PipelineText; 1033 PM.run(*M, AM); 1034 } 1035 1036 TEST_F(FunctionCallbacksTest, AnalysisUtilities) { 1037 EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)); 1038 EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _)); 1039 1040 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>"; 1041 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 1042 << "Pipeline was: " << PipelineText; 1043 PM.run(*M, AM); 1044 } 1045 1046 TEST_F(LoopCallbacksTest, PassUtilities) { 1047 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)); 1048 EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _)); 1049 1050 StringRef PipelineText = "require<test-analysis>,invalidate<test-analysis>"; 1051 1052 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 1053 << "Pipeline was: " << PipelineText; 1054 PM.run(*M, AM); 1055 } 1056 1057 /// Test parsing of the top-level pipeline. 1058 /// 1059 /// The ParseTopLevelPipeline callback takes over parsing of the entire pipeline 1060 /// from PassBuilder if it encounters an unknown pipeline entry at the top level 1061 /// (i.e., the first entry on the pipeline). 1062 /// This test parses a pipeline named 'another-pipeline', whose only elements 1063 /// may be the test-transform pass or the analysis utilities 1064 TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) { 1065 PB.registerParseTopLevelPipelineCallback([this]( 1066 ModulePassManager &MPM, ArrayRef<PassBuilder::PipelineElement> Pipeline, 1067 bool VerifyEachPass, bool DebugLogging) { 1068 auto &FirstName = Pipeline.front().Name; 1069 auto &InnerPipeline = Pipeline.front().InnerPipeline; 1070 if (FirstName == "another-pipeline") { 1071 for (auto &E : InnerPipeline) { 1072 if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis", E.Name, PM)) 1073 continue; 1074 1075 if (E.Name == "test-transform") { 1076 PM.addPass(PassHandle.getPass()); 1077 continue; 1078 } 1079 return false; 1080 } 1081 } 1082 return true; 1083 }); 1084 1085 EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)); 1086 EXPECT_CALL(PassHandle, run(HasName("<string>"), _)) 1087 .WillOnce(Invoke(getAnalysisResult)); 1088 EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _)); 1089 1090 StringRef PipelineText = 1091 "another-pipeline(test-transform,invalidate<test-analysis>)"; 1092 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) 1093 << "Pipeline was: " << PipelineText; 1094 PM.run(*M, AM); 1095 1096 /// Test the negative case 1097 PipelineText = "another-pipeline(instcombine)"; 1098 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed()) 1099 << "Pipeline was: " << PipelineText; 1100 } 1101 } // end anonymous namespace 1102