1 //===- llvm/unittest/IR/LegacyPassManager.cpp - Legacy PassManager 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 // This unit test exercises the legacy pass manager infrastructure. We use the 10 // old names as well to ensure that the source-level compatibility is preserved 11 // where possible. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/IR/LegacyPassManager.h" 16 #include "llvm/Analysis/CallGraphSCCPass.h" 17 #include "llvm/Analysis/LoopInfo.h" 18 #include "llvm/Analysis/LoopPass.h" 19 #include "llvm/IR/BasicBlock.h" 20 #include "llvm/IR/CallingConv.h" 21 #include "llvm/IR/DataLayout.h" 22 #include "llvm/IR/DerivedTypes.h" 23 #include "llvm/IR/Function.h" 24 #include "llvm/IR/GlobalVariable.h" 25 #include "llvm/IR/Instructions.h" 26 #include "llvm/IR/LLVMContext.h" 27 #include "llvm/IR/Module.h" 28 #include "llvm/IR/OptBisect.h" 29 #include "llvm/InitializePasses.h" 30 #include "llvm/Support/MathExtras.h" 31 #include "llvm/Support/raw_ostream.h" 32 #include "llvm/Transforms/Utils/CallGraphUpdater.h" 33 #include "gtest/gtest.h" 34 35 using namespace llvm; 36 37 namespace llvm { 38 void initializeModuleNDMPass(PassRegistry&); 39 void initializeFPassPass(PassRegistry&); 40 void initializeCGPassPass(PassRegistry&); 41 void initializeLPassPass(PassRegistry&); 42 43 namespace { 44 // ND = no deps 45 // NM = no modifications 46 struct ModuleNDNM: public ModulePass { 47 public: 48 static char run; 49 static char ID; 50 ModuleNDNM() : ModulePass(ID) { } 51 bool runOnModule(Module &M) override { 52 run++; 53 return false; 54 } 55 void getAnalysisUsage(AnalysisUsage &AU) const override { 56 AU.setPreservesAll(); 57 } 58 }; 59 char ModuleNDNM::ID=0; 60 char ModuleNDNM::run=0; 61 62 struct ModuleNDM : public ModulePass { 63 public: 64 static char run; 65 static char ID; 66 ModuleNDM() : ModulePass(ID) {} 67 bool runOnModule(Module &M) override { 68 run++; 69 return true; 70 } 71 }; 72 char ModuleNDM::ID=0; 73 char ModuleNDM::run=0; 74 75 struct ModuleNDM2 : public ModulePass { 76 public: 77 static char run; 78 static char ID; 79 ModuleNDM2() : ModulePass(ID) {} 80 bool runOnModule(Module &M) override { 81 run++; 82 return true; 83 } 84 }; 85 char ModuleNDM2::ID=0; 86 char ModuleNDM2::run=0; 87 88 struct ModuleDNM : public ModulePass { 89 public: 90 static char run; 91 static char ID; 92 ModuleDNM() : ModulePass(ID) { 93 initializeModuleNDMPass(*PassRegistry::getPassRegistry()); 94 } 95 bool runOnModule(Module &M) override { 96 run++; 97 return false; 98 } 99 void getAnalysisUsage(AnalysisUsage &AU) const override { 100 AU.addRequired<ModuleNDM>(); 101 AU.setPreservesAll(); 102 } 103 }; 104 char ModuleDNM::ID=0; 105 char ModuleDNM::run=0; 106 107 template<typename P> 108 struct PassTestBase : public P { 109 protected: 110 static int runc; 111 static bool initialized; 112 static bool finalized; 113 int allocated; 114 void run() { 115 EXPECT_TRUE(initialized); 116 EXPECT_FALSE(finalized); 117 EXPECT_EQ(0, allocated); 118 allocated++; 119 runc++; 120 } 121 public: 122 static char ID; 123 static void finishedOK(int run) { 124 EXPECT_GT(runc, 0); 125 EXPECT_TRUE(initialized); 126 EXPECT_TRUE(finalized); 127 EXPECT_EQ(run, runc); 128 } 129 PassTestBase() : P(ID), allocated(0) { 130 initialized = false; 131 finalized = false; 132 runc = 0; 133 } 134 135 void releaseMemory() override { 136 EXPECT_GT(runc, 0); 137 EXPECT_GT(allocated, 0); 138 allocated--; 139 } 140 }; 141 template<typename P> char PassTestBase<P>::ID; 142 template<typename P> int PassTestBase<P>::runc; 143 template<typename P> bool PassTestBase<P>::initialized; 144 template<typename P> bool PassTestBase<P>::finalized; 145 146 template<typename T, typename P> 147 struct PassTest : public PassTestBase<P> { 148 public: 149 #ifndef _MSC_VER // MSVC complains that Pass is not base class. 150 using llvm::Pass::doInitialization; 151 using llvm::Pass::doFinalization; 152 #endif 153 bool doInitialization(T &t) override { 154 EXPECT_FALSE(PassTestBase<P>::initialized); 155 PassTestBase<P>::initialized = true; 156 return false; 157 } 158 bool doFinalization(T &t) override { 159 EXPECT_FALSE(PassTestBase<P>::finalized); 160 PassTestBase<P>::finalized = true; 161 EXPECT_EQ(0, PassTestBase<P>::allocated); 162 return false; 163 } 164 }; 165 166 struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> { 167 public: 168 CGPass() { 169 initializeCGPassPass(*PassRegistry::getPassRegistry()); 170 } 171 bool runOnSCC(CallGraphSCC &SCMM) override { 172 run(); 173 return false; 174 } 175 }; 176 177 struct FPass : public PassTest<Module, FunctionPass> { 178 public: 179 bool runOnFunction(Function &F) override { 180 // FIXME: PR4112 181 // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); 182 run(); 183 return false; 184 } 185 }; 186 187 struct LPass : public PassTestBase<LoopPass> { 188 private: 189 static int initcount; 190 static int fincount; 191 public: 192 LPass() { 193 initializeLPassPass(*PassRegistry::getPassRegistry()); 194 initcount = 0; fincount=0; 195 EXPECT_FALSE(initialized); 196 } 197 static void finishedOK(int run, int finalized) { 198 PassTestBase<LoopPass>::finishedOK(run); 199 EXPECT_EQ(run, initcount); 200 EXPECT_EQ(finalized, fincount); 201 } 202 using llvm::Pass::doInitialization; 203 using llvm::Pass::doFinalization; 204 bool doInitialization(Loop* L, LPPassManager &LPM) override { 205 initialized = true; 206 initcount++; 207 return false; 208 } 209 bool runOnLoop(Loop *L, LPPassManager &LPM) override { 210 run(); 211 return false; 212 } 213 bool doFinalization() override { 214 fincount++; 215 finalized = true; 216 return false; 217 } 218 }; 219 int LPass::initcount=0; 220 int LPass::fincount=0; 221 222 struct OnTheFlyTest: public ModulePass { 223 public: 224 static char ID; 225 OnTheFlyTest() : ModulePass(ID) { 226 initializeFPassPass(*PassRegistry::getPassRegistry()); 227 } 228 bool runOnModule(Module &M) override { 229 for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) { 230 Function &F = *I; 231 { 232 SCOPED_TRACE("Running on the fly function pass"); 233 getAnalysis<FPass>(F); 234 } 235 } 236 return false; 237 } 238 void getAnalysisUsage(AnalysisUsage &AU) const override { 239 AU.addRequired<FPass>(); 240 } 241 }; 242 char OnTheFlyTest::ID=0; 243 244 TEST(PassManager, RunOnce) { 245 LLVMContext Context; 246 Module M("test-once", Context); 247 struct ModuleNDNM *mNDNM = new ModuleNDNM(); 248 struct ModuleDNM *mDNM = new ModuleDNM(); 249 struct ModuleNDM *mNDM = new ModuleNDM(); 250 struct ModuleNDM2 *mNDM2 = new ModuleNDM2(); 251 252 mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; 253 254 legacy::PassManager Passes; 255 Passes.add(mNDM2); 256 Passes.add(mNDM); 257 Passes.add(mNDNM); 258 Passes.add(mDNM); 259 260 Passes.run(M); 261 // each pass must be run exactly once, since nothing invalidates them 262 EXPECT_EQ(1, mNDM->run); 263 EXPECT_EQ(1, mNDNM->run); 264 EXPECT_EQ(1, mDNM->run); 265 EXPECT_EQ(1, mNDM2->run); 266 } 267 268 TEST(PassManager, ReRun) { 269 LLVMContext Context; 270 Module M("test-rerun", Context); 271 struct ModuleNDNM *mNDNM = new ModuleNDNM(); 272 struct ModuleDNM *mDNM = new ModuleDNM(); 273 struct ModuleNDM *mNDM = new ModuleNDM(); 274 struct ModuleNDM2 *mNDM2 = new ModuleNDM2(); 275 276 mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; 277 278 legacy::PassManager Passes; 279 Passes.add(mNDM); 280 Passes.add(mNDNM); 281 Passes.add(mNDM2);// invalidates mNDM needed by mDNM 282 Passes.add(mDNM); 283 284 Passes.run(M); 285 // Some passes must be rerun because a pass that modified the 286 // module/function was run in between 287 EXPECT_EQ(2, mNDM->run); 288 EXPECT_EQ(1, mNDNM->run); 289 EXPECT_EQ(1, mNDM2->run); 290 EXPECT_EQ(1, mDNM->run); 291 } 292 293 Module *makeLLVMModule(LLVMContext &Context); 294 295 template<typename T> 296 void MemoryTestHelper(int run) { 297 LLVMContext Context; 298 std::unique_ptr<Module> M(makeLLVMModule(Context)); 299 T *P = new T(); 300 legacy::PassManager Passes; 301 Passes.add(P); 302 Passes.run(*M); 303 T::finishedOK(run); 304 } 305 306 template<typename T> 307 void MemoryTestHelper(int run, int N) { 308 LLVMContext Context; 309 Module *M = makeLLVMModule(Context); 310 T *P = new T(); 311 legacy::PassManager Passes; 312 Passes.add(P); 313 Passes.run(*M); 314 T::finishedOK(run, N); 315 delete M; 316 } 317 318 TEST(PassManager, Memory) { 319 // SCC#1: test1->test2->test3->test1 320 // SCC#2: test4 321 // SCC#3: indirect call node 322 { 323 SCOPED_TRACE("Callgraph pass"); 324 MemoryTestHelper<CGPass>(3); 325 } 326 327 { 328 SCOPED_TRACE("Function pass"); 329 MemoryTestHelper<FPass>(4);// 4 functions 330 } 331 332 { 333 SCOPED_TRACE("Loop pass"); 334 MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function 335 } 336 337 } 338 339 TEST(PassManager, MemoryOnTheFly) { 340 LLVMContext Context; 341 Module *M = makeLLVMModule(Context); 342 { 343 SCOPED_TRACE("Running OnTheFlyTest"); 344 struct OnTheFlyTest *O = new OnTheFlyTest(); 345 legacy::PassManager Passes; 346 Passes.add(O); 347 Passes.run(*M); 348 349 FPass::finishedOK(4); 350 } 351 delete M; 352 } 353 354 // Skips or runs optional passes. 355 struct CustomOptPassGate : public OptPassGate { 356 bool Skip; 357 CustomOptPassGate(bool Skip) : Skip(Skip) { } 358 bool shouldRunPass(const Pass *P, StringRef IRDescription) { 359 if (P->getPassKind() == PT_Module) 360 return !Skip; 361 return OptPassGate::shouldRunPass(P, IRDescription); 362 } 363 bool isEnabled() const { return true; } 364 }; 365 366 // Optional module pass. 367 struct ModuleOpt: public ModulePass { 368 char run = 0; 369 static char ID; 370 ModuleOpt() : ModulePass(ID) { } 371 bool runOnModule(Module &M) override { 372 if (!skipModule(M)) 373 run++; 374 return false; 375 } 376 }; 377 char ModuleOpt::ID=0; 378 379 TEST(PassManager, CustomOptPassGate) { 380 LLVMContext Context0; 381 LLVMContext Context1; 382 LLVMContext Context2; 383 CustomOptPassGate SkipOptionalPasses(true); 384 CustomOptPassGate RunOptionalPasses(false); 385 386 Module M0("custom-opt-bisect", Context0); 387 Module M1("custom-opt-bisect", Context1); 388 Module M2("custom-opt-bisect2", Context2); 389 struct ModuleOpt *mOpt0 = new ModuleOpt(); 390 struct ModuleOpt *mOpt1 = new ModuleOpt(); 391 struct ModuleOpt *mOpt2 = new ModuleOpt(); 392 393 mOpt0->run = mOpt1->run = mOpt2->run = 0; 394 395 legacy::PassManager Passes0; 396 legacy::PassManager Passes1; 397 legacy::PassManager Passes2; 398 399 Passes0.add(mOpt0); 400 Passes1.add(mOpt1); 401 Passes2.add(mOpt2); 402 403 Context1.setOptPassGate(SkipOptionalPasses); 404 Context2.setOptPassGate(RunOptionalPasses); 405 406 Passes0.run(M0); 407 Passes1.run(M1); 408 Passes2.run(M2); 409 410 // By default optional passes are run. 411 EXPECT_EQ(1, mOpt0->run); 412 413 // The first context skips optional passes. 414 EXPECT_EQ(0, mOpt1->run); 415 416 // The second context runs optional passes. 417 EXPECT_EQ(1, mOpt2->run); 418 } 419 420 Module *makeLLVMModule(LLVMContext &Context) { 421 // Module Construction 422 Module *mod = new Module("test-mem", Context); 423 mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" 424 "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" 425 "a:0:64-s:64:64-f80:128:128"); 426 mod->setTargetTriple("x86_64-unknown-linux-gnu"); 427 428 // Type Definitions 429 std::vector<Type*>FuncTy_0_args; 430 FunctionType *FuncTy_0 = FunctionType::get( 431 /*Result=*/IntegerType::get(Context, 32), 432 /*Params=*/FuncTy_0_args, 433 /*isVarArg=*/false); 434 435 std::vector<Type*>FuncTy_2_args; 436 FuncTy_2_args.push_back(IntegerType::get(Context, 1)); 437 FunctionType *FuncTy_2 = FunctionType::get( 438 /*Result=*/Type::getVoidTy(Context), 439 /*Params=*/FuncTy_2_args, 440 /*isVarArg=*/false); 441 442 // Function Declarations 443 444 Function* func_test1 = Function::Create( 445 /*Type=*/FuncTy_0, 446 /*Linkage=*/GlobalValue::ExternalLinkage, 447 /*Name=*/"test1", mod); 448 func_test1->setCallingConv(CallingConv::C); 449 AttributeList func_test1_PAL; 450 func_test1->setAttributes(func_test1_PAL); 451 452 Function* func_test2 = Function::Create( 453 /*Type=*/FuncTy_0, 454 /*Linkage=*/GlobalValue::ExternalLinkage, 455 /*Name=*/"test2", mod); 456 func_test2->setCallingConv(CallingConv::C); 457 AttributeList func_test2_PAL; 458 func_test2->setAttributes(func_test2_PAL); 459 460 Function* func_test3 = Function::Create( 461 /*Type=*/FuncTy_0, 462 /*Linkage=*/GlobalValue::InternalLinkage, 463 /*Name=*/"test3", mod); 464 func_test3->setCallingConv(CallingConv::C); 465 AttributeList func_test3_PAL; 466 func_test3->setAttributes(func_test3_PAL); 467 468 Function* func_test4 = Function::Create( 469 /*Type=*/FuncTy_2, 470 /*Linkage=*/GlobalValue::ExternalLinkage, 471 /*Name=*/"test4", mod); 472 func_test4->setCallingConv(CallingConv::C); 473 AttributeList func_test4_PAL; 474 func_test4->setAttributes(func_test4_PAL); 475 476 // Global Variable Declarations 477 478 479 // Constant Definitions 480 481 // Global Variable Definitions 482 483 // Function Definitions 484 485 // Function: test1 (func_test1) 486 { 487 488 BasicBlock *label_entry = 489 BasicBlock::Create(Context, "entry", func_test1, nullptr); 490 491 // Block entry (label_entry) 492 CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry); 493 int32_3->setCallingConv(CallingConv::C); 494 int32_3->setTailCall(false); 495 AttributeList int32_3_PAL; 496 int32_3->setAttributes(int32_3_PAL); 497 498 ReturnInst::Create(Context, int32_3, label_entry); 499 } 500 501 // Function: test2 (func_test2) 502 { 503 504 BasicBlock *label_entry_5 = 505 BasicBlock::Create(Context, "entry", func_test2, nullptr); 506 507 // Block entry (label_entry_5) 508 CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5); 509 int32_6->setCallingConv(CallingConv::C); 510 int32_6->setTailCall(false); 511 AttributeList int32_6_PAL; 512 int32_6->setAttributes(int32_6_PAL); 513 514 ReturnInst::Create(Context, int32_6, label_entry_5); 515 } 516 517 // Function: test3 (func_test3) 518 { 519 520 BasicBlock *label_entry_8 = 521 BasicBlock::Create(Context, "entry", func_test3, nullptr); 522 523 // Block entry (label_entry_8) 524 CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8); 525 int32_9->setCallingConv(CallingConv::C); 526 int32_9->setTailCall(false); 527 AttributeList int32_9_PAL; 528 int32_9->setAttributes(int32_9_PAL); 529 530 ReturnInst::Create(Context, int32_9, label_entry_8); 531 } 532 533 // Function: test4 (func_test4) 534 { 535 Function::arg_iterator args = func_test4->arg_begin(); 536 Value *int1_f = &*args++; 537 int1_f->setName("f"); 538 539 BasicBlock *label_entry_11 = 540 BasicBlock::Create(Context, "entry", func_test4, nullptr); 541 BasicBlock *label_bb = 542 BasicBlock::Create(Context, "bb", func_test4, nullptr); 543 BasicBlock *label_bb1 = 544 BasicBlock::Create(Context, "bb1", func_test4, nullptr); 545 BasicBlock *label_return = 546 BasicBlock::Create(Context, "return", func_test4, nullptr); 547 548 // Block entry (label_entry_11) 549 auto *AI = new AllocaInst(func_test3->getType(), 0, "func3ptr", 550 label_entry_11); 551 new StoreInst(func_test3, AI, label_entry_11); 552 BranchInst::Create(label_bb, label_entry_11); 553 554 // Block bb (label_bb) 555 BranchInst::Create(label_bb, label_bb1, int1_f, label_bb); 556 557 // Block bb1 (label_bb1) 558 BranchInst::Create(label_bb1, label_return, int1_f, label_bb1); 559 560 // Block return (label_return) 561 ReturnInst::Create(Context, label_return); 562 } 563 return mod; 564 } 565 566 /// Split a simple function which contains only a call and a return into two 567 /// such that the first calls the second and the second whoever was called 568 /// initially. 569 Function *splitSimpleFunction(Function &F) { 570 LLVMContext &Context = F.getContext(); 571 Function *SF = Function::Create(F.getFunctionType(), F.getLinkage(), 572 F.getName() + "b", F.getParent()); 573 F.setName(F.getName() + "a"); 574 BasicBlock *Entry = BasicBlock::Create(Context, "entry", SF, nullptr); 575 CallInst &CI = cast<CallInst>(F.getEntryBlock().front()); 576 CI.clone()->insertBefore(ReturnInst::Create(Context, Entry)); 577 CI.setCalledFunction(SF); 578 return SF; 579 } 580 581 struct CGModifierPass : public CGPass { 582 unsigned NumSCCs = 0; 583 unsigned NumFns = 0; 584 unsigned NumFnDecls = 0; 585 unsigned SetupWorked = 0; 586 unsigned NumExtCalledBefore = 0; 587 unsigned NumExtCalledAfter = 0; 588 589 CallGraphUpdater CGU; 590 591 bool runOnSCC(CallGraphSCC &SCMM) override { 592 ++NumSCCs; 593 for (CallGraphNode *N : SCMM) { 594 if (N->getFunction()){ 595 ++NumFns; 596 NumFnDecls += N->getFunction()->isDeclaration(); 597 } 598 } 599 CGPass::run(); 600 601 CallGraph &CG = const_cast<CallGraph &>(SCMM.getCallGraph()); 602 CallGraphNode *ExtCallingNode = CG.getExternalCallingNode(); 603 NumExtCalledBefore = ExtCallingNode->size(); 604 605 if (SCMM.size() <= 1) 606 return false; 607 608 CallGraphNode *N = *(SCMM.begin()); 609 Function *F = N->getFunction(); 610 Module *M = F->getParent(); 611 Function *Test1F = M->getFunction("test1"); 612 Function *Test2aF = M->getFunction("test2a"); 613 Function *Test2bF = M->getFunction("test2b"); 614 Function *Test3F = M->getFunction("test3"); 615 616 auto InSCC = [&](Function *Fn) { 617 return llvm::any_of(SCMM, [Fn](CallGraphNode *CGN) { 618 return CGN->getFunction() == Fn; 619 }); 620 }; 621 622 if (!Test1F || !Test2aF || !Test2bF || !Test3F || !InSCC(Test1F) || 623 !InSCC(Test2aF) || !InSCC(Test2bF) || !InSCC(Test3F)) 624 return false; 625 626 CallInst *CI = dyn_cast<CallInst>(&Test1F->getEntryBlock().front()); 627 if (!CI || CI->getCalledFunction() != Test2aF) 628 return false; 629 630 SetupWorked += 1; 631 632 // Create a replica of test3 and just move the blocks there. 633 Function *Test3FRepl = Function::Create( 634 /*Type=*/Test3F->getFunctionType(), 635 /*Linkage=*/GlobalValue::InternalLinkage, 636 /*Name=*/"test3repl", Test3F->getParent()); 637 while (!Test3F->empty()) { 638 BasicBlock &BB = Test3F->front(); 639 BB.removeFromParent(); 640 BB.insertInto(Test3FRepl); 641 } 642 643 CGU.initialize(CG, SCMM); 644 645 // Replace test3 with the replica. This is legal as it is actually 646 // internal and the "capturing use" is not really capturing anything. 647 CGU.replaceFunctionWith(*Test3F, *Test3FRepl); 648 Test3F->replaceAllUsesWith(Test3FRepl); 649 650 // Rewrite the call in test1 to point to the replica of 3 not test2. 651 CI->setCalledFunction(Test3FRepl); 652 653 // Delete test2a and test2b and reanalyze 1 as we changed calls inside. 654 CGU.removeFunction(*Test2aF); 655 CGU.removeFunction(*Test2bF); 656 CGU.reanalyzeFunction(*Test1F); 657 658 return true; 659 } 660 661 bool doFinalization(CallGraph &CG) override { 662 CGU.finalize(); 663 // We removed test2 and replaced the internal test3. 664 NumExtCalledAfter = CG.getExternalCallingNode()->size(); 665 return true; 666 } 667 }; 668 669 TEST(PassManager, CallGraphUpdater0) { 670 // SCC#1: test1->test2a->test2b->test3->test1 671 // SCC#2: test4 672 // SCC#3: test3 (the empty function declaration as we replaced it with 673 // test3repl when we visited SCC#1) 674 // SCC#4: test2a->test2b (the empty function declarations as we deleted 675 // these functions when we visited SCC#1) 676 // SCC#5: indirect call node 677 678 LLVMContext Context; 679 std::unique_ptr<Module> M(makeLLVMModule(Context)); 680 ASSERT_EQ(M->getFunctionList().size(), 4U); 681 Function *F = M->getFunction("test2"); 682 Function *SF = splitSimpleFunction(*F); 683 CallInst::Create(F, "", &SF->getEntryBlock()); 684 ASSERT_EQ(M->getFunctionList().size(), 5U); 685 CGModifierPass *P = new CGModifierPass(); 686 legacy::PassManager Passes; 687 Passes.add(P); 688 Passes.run(*M); 689 ASSERT_EQ(P->SetupWorked, 1U); 690 ASSERT_EQ(P->NumSCCs, 5U); 691 ASSERT_EQ(P->NumFns, 8U); 692 ASSERT_EQ(P->NumFnDecls, 3U); 693 ASSERT_EQ(M->getFunctionList().size(), 3U); 694 ASSERT_EQ(P->NumExtCalledBefore, /* test1, 2a, 2b, 3, 4 */ 5U); 695 ASSERT_EQ(P->NumExtCalledAfter, /* test1, 3repl, 4 */ 3U); 696 } 697 } 698 } 699 700 INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false) 701 INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false) 702 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) 703 INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false) 704 INITIALIZE_PASS(FPass, "fp","fp", false, false) 705 INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false) 706 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) 707 INITIALIZE_PASS_END(LPass, "lp","lp", false, false) 708