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/Pass.h" 30 #include "llvm/Support/MathExtras.h" 31 #include "llvm/Support/raw_ostream.h" 32 #include "gtest/gtest.h" 33 34 using namespace llvm; 35 36 namespace llvm { 37 void initializeModuleNDMPass(PassRegistry&); 38 void initializeFPassPass(PassRegistry&); 39 void initializeCGPassPass(PassRegistry&); 40 void initializeLPassPass(PassRegistry&); 41 42 namespace { 43 // ND = no deps 44 // NM = no modifications 45 struct ModuleNDNM: public ModulePass { 46 public: 47 static char run; 48 static char ID; 49 ModuleNDNM() : ModulePass(ID) { } 50 bool runOnModule(Module &M) override { 51 run++; 52 return false; 53 } 54 void getAnalysisUsage(AnalysisUsage &AU) const override { 55 AU.setPreservesAll(); 56 } 57 }; 58 char ModuleNDNM::ID=0; 59 char ModuleNDNM::run=0; 60 61 struct ModuleNDM : public ModulePass { 62 public: 63 static char run; 64 static char ID; 65 ModuleNDM() : ModulePass(ID) {} 66 bool runOnModule(Module &M) override { 67 run++; 68 return true; 69 } 70 }; 71 char ModuleNDM::ID=0; 72 char ModuleNDM::run=0; 73 74 struct ModuleNDM2 : public ModulePass { 75 public: 76 static char run; 77 static char ID; 78 ModuleNDM2() : ModulePass(ID) {} 79 bool runOnModule(Module &M) override { 80 run++; 81 return true; 82 } 83 }; 84 char ModuleNDM2::ID=0; 85 char ModuleNDM2::run=0; 86 87 struct ModuleDNM : public ModulePass { 88 public: 89 static char run; 90 static char ID; 91 ModuleDNM() : ModulePass(ID) { 92 initializeModuleNDMPass(*PassRegistry::getPassRegistry()); 93 } 94 bool runOnModule(Module &M) override { 95 run++; 96 return false; 97 } 98 void getAnalysisUsage(AnalysisUsage &AU) const override { 99 AU.addRequired<ModuleNDM>(); 100 AU.setPreservesAll(); 101 } 102 }; 103 char ModuleDNM::ID=0; 104 char ModuleDNM::run=0; 105 106 template<typename P> 107 struct PassTestBase : public P { 108 protected: 109 static int runc; 110 static bool initialized; 111 static bool finalized; 112 int allocated; 113 void run() { 114 EXPECT_TRUE(initialized); 115 EXPECT_FALSE(finalized); 116 EXPECT_EQ(0, allocated); 117 allocated++; 118 runc++; 119 } 120 public: 121 static char ID; 122 static void finishedOK(int run) { 123 EXPECT_GT(runc, 0); 124 EXPECT_TRUE(initialized); 125 EXPECT_TRUE(finalized); 126 EXPECT_EQ(run, runc); 127 } 128 PassTestBase() : P(ID), allocated(0) { 129 initialized = false; 130 finalized = false; 131 runc = 0; 132 } 133 134 void releaseMemory() override { 135 EXPECT_GT(runc, 0); 136 EXPECT_GT(allocated, 0); 137 allocated--; 138 } 139 }; 140 template<typename P> char PassTestBase<P>::ID; 141 template<typename P> int PassTestBase<P>::runc; 142 template<typename P> bool PassTestBase<P>::initialized; 143 template<typename P> bool PassTestBase<P>::finalized; 144 145 template<typename T, typename P> 146 struct PassTest : public PassTestBase<P> { 147 public: 148 #ifndef _MSC_VER // MSVC complains that Pass is not base class. 149 using llvm::Pass::doInitialization; 150 using llvm::Pass::doFinalization; 151 #endif 152 bool doInitialization(T &t) override { 153 EXPECT_FALSE(PassTestBase<P>::initialized); 154 PassTestBase<P>::initialized = true; 155 return false; 156 } 157 bool doFinalization(T &t) override { 158 EXPECT_FALSE(PassTestBase<P>::finalized); 159 PassTestBase<P>::finalized = true; 160 EXPECT_EQ(0, PassTestBase<P>::allocated); 161 return false; 162 } 163 }; 164 165 struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> { 166 public: 167 CGPass() { 168 initializeCGPassPass(*PassRegistry::getPassRegistry()); 169 } 170 bool runOnSCC(CallGraphSCC &SCMM) override { 171 run(); 172 return false; 173 } 174 }; 175 176 struct FPass : public PassTest<Module, FunctionPass> { 177 public: 178 bool runOnFunction(Function &F) override { 179 // FIXME: PR4112 180 // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); 181 run(); 182 return false; 183 } 184 }; 185 186 struct LPass : public PassTestBase<LoopPass> { 187 private: 188 static int initcount; 189 static int fincount; 190 public: 191 LPass() { 192 initializeLPassPass(*PassRegistry::getPassRegistry()); 193 initcount = 0; fincount=0; 194 EXPECT_FALSE(initialized); 195 } 196 static void finishedOK(int run, int finalized) { 197 PassTestBase<LoopPass>::finishedOK(run); 198 EXPECT_EQ(run, initcount); 199 EXPECT_EQ(finalized, fincount); 200 } 201 using llvm::Pass::doInitialization; 202 using llvm::Pass::doFinalization; 203 bool doInitialization(Loop* L, LPPassManager &LPM) override { 204 initialized = true; 205 initcount++; 206 return false; 207 } 208 bool runOnLoop(Loop *L, LPPassManager &LPM) override { 209 run(); 210 return false; 211 } 212 bool doFinalization() override { 213 fincount++; 214 finalized = true; 215 return false; 216 } 217 }; 218 int LPass::initcount=0; 219 int LPass::fincount=0; 220 221 struct OnTheFlyTest: public ModulePass { 222 public: 223 static char ID; 224 OnTheFlyTest() : ModulePass(ID) { 225 initializeFPassPass(*PassRegistry::getPassRegistry()); 226 } 227 bool runOnModule(Module &M) override { 228 for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) { 229 Function &F = *I; 230 { 231 SCOPED_TRACE("Running on the fly function pass"); 232 getAnalysis<FPass>(F); 233 } 234 } 235 return false; 236 } 237 void getAnalysisUsage(AnalysisUsage &AU) const override { 238 AU.addRequired<FPass>(); 239 } 240 }; 241 char OnTheFlyTest::ID=0; 242 243 TEST(PassManager, RunOnce) { 244 LLVMContext Context; 245 Module M("test-once", Context); 246 struct ModuleNDNM *mNDNM = new ModuleNDNM(); 247 struct ModuleDNM *mDNM = new ModuleDNM(); 248 struct ModuleNDM *mNDM = new ModuleNDM(); 249 struct ModuleNDM2 *mNDM2 = new ModuleNDM2(); 250 251 mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; 252 253 legacy::PassManager Passes; 254 Passes.add(mNDM2); 255 Passes.add(mNDM); 256 Passes.add(mNDNM); 257 Passes.add(mDNM); 258 259 Passes.run(M); 260 // each pass must be run exactly once, since nothing invalidates them 261 EXPECT_EQ(1, mNDM->run); 262 EXPECT_EQ(1, mNDNM->run); 263 EXPECT_EQ(1, mDNM->run); 264 EXPECT_EQ(1, mNDM2->run); 265 } 266 267 TEST(PassManager, ReRun) { 268 LLVMContext Context; 269 Module M("test-rerun", Context); 270 struct ModuleNDNM *mNDNM = new ModuleNDNM(); 271 struct ModuleDNM *mDNM = new ModuleDNM(); 272 struct ModuleNDM *mNDM = new ModuleNDM(); 273 struct ModuleNDM2 *mNDM2 = new ModuleNDM2(); 274 275 mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; 276 277 legacy::PassManager Passes; 278 Passes.add(mNDM); 279 Passes.add(mNDNM); 280 Passes.add(mNDM2);// invalidates mNDM needed by mDNM 281 Passes.add(mDNM); 282 283 Passes.run(M); 284 // Some passes must be rerun because a pass that modified the 285 // module/function was run in between 286 EXPECT_EQ(2, mNDM->run); 287 EXPECT_EQ(1, mNDNM->run); 288 EXPECT_EQ(1, mNDM2->run); 289 EXPECT_EQ(1, mDNM->run); 290 } 291 292 Module *makeLLVMModule(LLVMContext &Context); 293 294 template<typename T> 295 void MemoryTestHelper(int run) { 296 LLVMContext Context; 297 std::unique_ptr<Module> M(makeLLVMModule(Context)); 298 T *P = new T(); 299 legacy::PassManager Passes; 300 Passes.add(P); 301 Passes.run(*M); 302 T::finishedOK(run); 303 } 304 305 template<typename T> 306 void MemoryTestHelper(int run, int N) { 307 LLVMContext Context; 308 Module *M = makeLLVMModule(Context); 309 T *P = new T(); 310 legacy::PassManager Passes; 311 Passes.add(P); 312 Passes.run(*M); 313 T::finishedOK(run, N); 314 delete M; 315 } 316 317 TEST(PassManager, Memory) { 318 // SCC#1: test1->test2->test3->test1 319 // SCC#2: test4 320 // SCC#3: indirect call node 321 { 322 SCOPED_TRACE("Callgraph pass"); 323 MemoryTestHelper<CGPass>(3); 324 } 325 326 { 327 SCOPED_TRACE("Function pass"); 328 MemoryTestHelper<FPass>(4);// 4 functions 329 } 330 331 { 332 SCOPED_TRACE("Loop pass"); 333 MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function 334 } 335 336 } 337 338 TEST(PassManager, MemoryOnTheFly) { 339 LLVMContext Context; 340 Module *M = makeLLVMModule(Context); 341 { 342 SCOPED_TRACE("Running OnTheFlyTest"); 343 struct OnTheFlyTest *O = new OnTheFlyTest(); 344 legacy::PassManager Passes; 345 Passes.add(O); 346 Passes.run(*M); 347 348 FPass::finishedOK(4); 349 } 350 delete M; 351 } 352 353 // Skips or runs optional passes. 354 struct CustomOptPassGate : public OptPassGate { 355 bool Skip; 356 CustomOptPassGate(bool Skip) : Skip(Skip) { } 357 bool shouldRunPass(const Pass *P, StringRef IRDescription) { 358 if (P->getPassKind() == PT_Module) 359 return !Skip; 360 return OptPassGate::shouldRunPass(P, IRDescription); 361 } 362 bool isEnabled() const { return true; } 363 }; 364 365 // Optional module pass. 366 struct ModuleOpt: public ModulePass { 367 char run = 0; 368 static char ID; 369 ModuleOpt() : ModulePass(ID) { } 370 bool runOnModule(Module &M) override { 371 if (!skipModule(M)) 372 run++; 373 return false; 374 } 375 }; 376 char ModuleOpt::ID=0; 377 378 TEST(PassManager, CustomOptPassGate) { 379 LLVMContext Context0; 380 LLVMContext Context1; 381 LLVMContext Context2; 382 CustomOptPassGate SkipOptionalPasses(true); 383 CustomOptPassGate RunOptionalPasses(false); 384 385 Module M0("custom-opt-bisect", Context0); 386 Module M1("custom-opt-bisect", Context1); 387 Module M2("custom-opt-bisect2", Context2); 388 struct ModuleOpt *mOpt0 = new ModuleOpt(); 389 struct ModuleOpt *mOpt1 = new ModuleOpt(); 390 struct ModuleOpt *mOpt2 = new ModuleOpt(); 391 392 mOpt0->run = mOpt1->run = mOpt2->run = 0; 393 394 legacy::PassManager Passes0; 395 legacy::PassManager Passes1; 396 legacy::PassManager Passes2; 397 398 Passes0.add(mOpt0); 399 Passes1.add(mOpt1); 400 Passes2.add(mOpt2); 401 402 Context1.setOptPassGate(SkipOptionalPasses); 403 Context2.setOptPassGate(RunOptionalPasses); 404 405 Passes0.run(M0); 406 Passes1.run(M1); 407 Passes2.run(M2); 408 409 // By default optional passes are run. 410 EXPECT_EQ(1, mOpt0->run); 411 412 // The first context skips optional passes. 413 EXPECT_EQ(0, mOpt1->run); 414 415 // The second context runs optional passes. 416 EXPECT_EQ(1, mOpt2->run); 417 } 418 419 Module *makeLLVMModule(LLVMContext &Context) { 420 // Module Construction 421 Module *mod = new Module("test-mem", Context); 422 mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" 423 "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" 424 "a:0:64-s:64:64-f80:128:128"); 425 mod->setTargetTriple("x86_64-unknown-linux-gnu"); 426 427 // Type Definitions 428 std::vector<Type*>FuncTy_0_args; 429 FunctionType *FuncTy_0 = FunctionType::get( 430 /*Result=*/IntegerType::get(Context, 32), 431 /*Params=*/FuncTy_0_args, 432 /*isVarArg=*/false); 433 434 std::vector<Type*>FuncTy_2_args; 435 FuncTy_2_args.push_back(IntegerType::get(Context, 1)); 436 FunctionType *FuncTy_2 = FunctionType::get( 437 /*Result=*/Type::getVoidTy(Context), 438 /*Params=*/FuncTy_2_args, 439 /*isVarArg=*/false); 440 441 // Function Declarations 442 443 Function* func_test1 = Function::Create( 444 /*Type=*/FuncTy_0, 445 /*Linkage=*/GlobalValue::ExternalLinkage, 446 /*Name=*/"test1", mod); 447 func_test1->setCallingConv(CallingConv::C); 448 AttributeList func_test1_PAL; 449 func_test1->setAttributes(func_test1_PAL); 450 451 Function* func_test2 = Function::Create( 452 /*Type=*/FuncTy_0, 453 /*Linkage=*/GlobalValue::ExternalLinkage, 454 /*Name=*/"test2", mod); 455 func_test2->setCallingConv(CallingConv::C); 456 AttributeList func_test2_PAL; 457 func_test2->setAttributes(func_test2_PAL); 458 459 Function* func_test3 = Function::Create( 460 /*Type=*/FuncTy_0, 461 /*Linkage=*/GlobalValue::ExternalLinkage, 462 /*Name=*/"test3", mod); 463 func_test3->setCallingConv(CallingConv::C); 464 AttributeList func_test3_PAL; 465 func_test3->setAttributes(func_test3_PAL); 466 467 Function* func_test4 = Function::Create( 468 /*Type=*/FuncTy_2, 469 /*Linkage=*/GlobalValue::ExternalLinkage, 470 /*Name=*/"test4", mod); 471 func_test4->setCallingConv(CallingConv::C); 472 AttributeList func_test4_PAL; 473 func_test4->setAttributes(func_test4_PAL); 474 475 // Global Variable Declarations 476 477 478 // Constant Definitions 479 480 // Global Variable Definitions 481 482 // Function Definitions 483 484 // Function: test1 (func_test1) 485 { 486 487 BasicBlock *label_entry = 488 BasicBlock::Create(Context, "entry", func_test1, nullptr); 489 490 // Block entry (label_entry) 491 CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry); 492 int32_3->setCallingConv(CallingConv::C); 493 int32_3->setTailCall(false); 494 AttributeList int32_3_PAL; 495 int32_3->setAttributes(int32_3_PAL); 496 497 ReturnInst::Create(Context, int32_3, label_entry); 498 } 499 500 // Function: test2 (func_test2) 501 { 502 503 BasicBlock *label_entry_5 = 504 BasicBlock::Create(Context, "entry", func_test2, nullptr); 505 506 // Block entry (label_entry_5) 507 CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5); 508 int32_6->setCallingConv(CallingConv::C); 509 int32_6->setTailCall(false); 510 AttributeList int32_6_PAL; 511 int32_6->setAttributes(int32_6_PAL); 512 513 ReturnInst::Create(Context, int32_6, label_entry_5); 514 } 515 516 // Function: test3 (func_test3) 517 { 518 519 BasicBlock *label_entry_8 = 520 BasicBlock::Create(Context, "entry", func_test3, nullptr); 521 522 // Block entry (label_entry_8) 523 CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8); 524 int32_9->setCallingConv(CallingConv::C); 525 int32_9->setTailCall(false); 526 AttributeList int32_9_PAL; 527 int32_9->setAttributes(int32_9_PAL); 528 529 ReturnInst::Create(Context, int32_9, label_entry_8); 530 } 531 532 // Function: test4 (func_test4) 533 { 534 Function::arg_iterator args = func_test4->arg_begin(); 535 Value *int1_f = &*args++; 536 int1_f->setName("f"); 537 538 BasicBlock *label_entry_11 = 539 BasicBlock::Create(Context, "entry", func_test4, nullptr); 540 BasicBlock *label_bb = 541 BasicBlock::Create(Context, "bb", func_test4, nullptr); 542 BasicBlock *label_bb1 = 543 BasicBlock::Create(Context, "bb1", func_test4, nullptr); 544 BasicBlock *label_return = 545 BasicBlock::Create(Context, "return", func_test4, nullptr); 546 547 // Block entry (label_entry_11) 548 BranchInst::Create(label_bb, label_entry_11); 549 550 // Block bb (label_bb) 551 BranchInst::Create(label_bb, label_bb1, int1_f, label_bb); 552 553 // Block bb1 (label_bb1) 554 BranchInst::Create(label_bb1, label_return, int1_f, label_bb1); 555 556 // Block return (label_return) 557 ReturnInst::Create(Context, label_return); 558 } 559 return mod; 560 } 561 562 } 563 } 564 565 INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false) 566 INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false) 567 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) 568 INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false) 569 INITIALIZE_PASS(FPass, "fp","fp", false, false) 570 INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false) 571 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) 572 INITIALIZE_PASS_END(LPass, "lp","lp", false, false) 573