1 //===- llvm/unittest/IR/LegacyPassManager.cpp - Legacy PassManager tests --===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This unit test exercises the legacy pass manager infrastructure. We use the 11 // old names as well to ensure that the source-level compatibility is preserved 12 // where possible. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "llvm/IR/LegacyPassManager.h" 17 #include "llvm/Analysis/CallGraphSCCPass.h" 18 #include "llvm/Analysis/LoopInfo.h" 19 #include "llvm/Analysis/LoopPass.h" 20 #include "llvm/IR/BasicBlock.h" 21 #include "llvm/IR/CallingConv.h" 22 #include "llvm/IR/Constants.h" 23 #include "llvm/IR/DataLayout.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/IR/Function.h" 26 #include "llvm/IR/GlobalVariable.h" 27 #include "llvm/IR/IRPrintingPasses.h" 28 #include "llvm/IR/InlineAsm.h" 29 #include "llvm/IR/Instructions.h" 30 #include "llvm/IR/LLVMContext.h" 31 #include "llvm/IR/Module.h" 32 #include "llvm/IR/Verifier.h" 33 #include "llvm/Pass.h" 34 #include "llvm/Support/MathExtras.h" 35 #include "llvm/Support/raw_ostream.h" 36 #include "gtest/gtest.h" 37 38 using namespace llvm; 39 40 namespace llvm { 41 void initializeModuleNDMPass(PassRegistry&); 42 void initializeFPassPass(PassRegistry&); 43 void initializeCGPassPass(PassRegistry&); 44 void initializeLPassPass(PassRegistry&); 45 void initializeBPassPass(PassRegistry&); 46 47 namespace { 48 // ND = no deps 49 // NM = no modifications 50 struct ModuleNDNM: public ModulePass { 51 public: 52 static char run; 53 static char ID; ModuleNDNMllvm::__anonef00cd880111::ModuleNDNM54 ModuleNDNM() : ModulePass(ID) { } runOnModulellvm::__anonef00cd880111::ModuleNDNM55 bool runOnModule(Module &M) override { 56 run++; 57 return false; 58 } getAnalysisUsagellvm::__anonef00cd880111::ModuleNDNM59 void getAnalysisUsage(AnalysisUsage &AU) const override { 60 AU.setPreservesAll(); 61 } 62 }; 63 char ModuleNDNM::ID=0; 64 char ModuleNDNM::run=0; 65 66 struct ModuleNDM : public ModulePass { 67 public: 68 static char run; 69 static char ID; ModuleNDMllvm::__anonef00cd880111::ModuleNDM70 ModuleNDM() : ModulePass(ID) {} runOnModulellvm::__anonef00cd880111::ModuleNDM71 bool runOnModule(Module &M) override { 72 run++; 73 return true; 74 } 75 }; 76 char ModuleNDM::ID=0; 77 char ModuleNDM::run=0; 78 79 struct ModuleNDM2 : public ModulePass { 80 public: 81 static char run; 82 static char ID; ModuleNDM2llvm::__anonef00cd880111::ModuleNDM283 ModuleNDM2() : ModulePass(ID) {} runOnModulellvm::__anonef00cd880111::ModuleNDM284 bool runOnModule(Module &M) override { 85 run++; 86 return true; 87 } 88 }; 89 char ModuleNDM2::ID=0; 90 char ModuleNDM2::run=0; 91 92 struct ModuleDNM : public ModulePass { 93 public: 94 static char run; 95 static char ID; ModuleDNMllvm::__anonef00cd880111::ModuleDNM96 ModuleDNM() : ModulePass(ID) { 97 initializeModuleNDMPass(*PassRegistry::getPassRegistry()); 98 } runOnModulellvm::__anonef00cd880111::ModuleDNM99 bool runOnModule(Module &M) override { 100 run++; 101 return false; 102 } getAnalysisUsagellvm::__anonef00cd880111::ModuleDNM103 void getAnalysisUsage(AnalysisUsage &AU) const override { 104 AU.addRequired<ModuleNDM>(); 105 AU.setPreservesAll(); 106 } 107 }; 108 char ModuleDNM::ID=0; 109 char ModuleDNM::run=0; 110 111 template<typename P> 112 struct PassTestBase : public P { 113 protected: 114 static int runc; 115 static bool initialized; 116 static bool finalized; 117 int allocated; runllvm::__anonef00cd880111::PassTestBase118 void run() { 119 EXPECT_TRUE(initialized); 120 EXPECT_FALSE(finalized); 121 EXPECT_EQ(0, allocated); 122 allocated++; 123 runc++; 124 } 125 public: 126 static char ID; finishedOKllvm::__anonef00cd880111::PassTestBase127 static void finishedOK(int run) { 128 EXPECT_GT(runc, 0); 129 EXPECT_TRUE(initialized); 130 EXPECT_TRUE(finalized); 131 EXPECT_EQ(run, runc); 132 } PassTestBasellvm::__anonef00cd880111::PassTestBase133 PassTestBase() : P(ID), allocated(0) { 134 initialized = false; 135 finalized = false; 136 runc = 0; 137 } 138 releaseMemoryllvm::__anonef00cd880111::PassTestBase139 void releaseMemory() override { 140 EXPECT_GT(runc, 0); 141 EXPECT_GT(allocated, 0); 142 allocated--; 143 } 144 }; 145 template<typename P> char PassTestBase<P>::ID; 146 template<typename P> int PassTestBase<P>::runc; 147 template<typename P> bool PassTestBase<P>::initialized; 148 template<typename P> bool PassTestBase<P>::finalized; 149 150 template<typename T, typename P> 151 struct PassTest : public PassTestBase<P> { 152 public: 153 #ifndef _MSC_VER // MSVC complains that Pass is not base class. 154 using llvm::Pass::doInitialization; 155 using llvm::Pass::doFinalization; 156 #endif doInitializationllvm::__anonef00cd880111::PassTest157 bool doInitialization(T &t) override { 158 EXPECT_FALSE(PassTestBase<P>::initialized); 159 PassTestBase<P>::initialized = true; 160 return false; 161 } doFinalizationllvm::__anonef00cd880111::PassTest162 bool doFinalization(T &t) override { 163 EXPECT_FALSE(PassTestBase<P>::finalized); 164 PassTestBase<P>::finalized = true; 165 EXPECT_EQ(0, PassTestBase<P>::allocated); 166 return false; 167 } 168 }; 169 170 struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> { 171 public: CGPassllvm::__anonef00cd880111::CGPass172 CGPass() { 173 initializeCGPassPass(*PassRegistry::getPassRegistry()); 174 } runOnSCCllvm::__anonef00cd880111::CGPass175 bool runOnSCC(CallGraphSCC &SCMM) override { 176 run(); 177 return false; 178 } 179 }; 180 181 struct FPass : public PassTest<Module, FunctionPass> { 182 public: runOnFunctionllvm::__anonef00cd880111::FPass183 bool runOnFunction(Function &F) override { 184 // FIXME: PR4112 185 // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); 186 run(); 187 return false; 188 } 189 }; 190 191 struct LPass : public PassTestBase<LoopPass> { 192 private: 193 static int initcount; 194 static int fincount; 195 public: LPassllvm::__anonef00cd880111::LPass196 LPass() { 197 initializeLPassPass(*PassRegistry::getPassRegistry()); 198 initcount = 0; fincount=0; 199 EXPECT_FALSE(initialized); 200 } finishedOKllvm::__anonef00cd880111::LPass201 static void finishedOK(int run, int finalized) { 202 PassTestBase<LoopPass>::finishedOK(run); 203 EXPECT_EQ(run, initcount); 204 EXPECT_EQ(finalized, fincount); 205 } 206 using llvm::Pass::doInitialization; 207 using llvm::Pass::doFinalization; doInitializationllvm::__anonef00cd880111::LPass208 bool doInitialization(Loop* L, LPPassManager &LPM) override { 209 initialized = true; 210 initcount++; 211 return false; 212 } runOnLoopllvm::__anonef00cd880111::LPass213 bool runOnLoop(Loop *L, LPPassManager &LPM) override { 214 run(); 215 return false; 216 } doFinalizationllvm::__anonef00cd880111::LPass217 bool doFinalization() override { 218 fincount++; 219 finalized = true; 220 return false; 221 } 222 }; 223 int LPass::initcount=0; 224 int LPass::fincount=0; 225 226 struct BPass : public PassTestBase<BasicBlockPass> { 227 private: 228 static int inited; 229 static int fin; 230 public: finishedOKllvm::__anonef00cd880111::BPass231 static void finishedOK(int run, int N) { 232 PassTestBase<BasicBlockPass>::finishedOK(run); 233 EXPECT_EQ(inited, N); 234 EXPECT_EQ(fin, N); 235 } BPassllvm::__anonef00cd880111::BPass236 BPass() { 237 inited = 0; 238 fin = 0; 239 } doInitializationllvm::__anonef00cd880111::BPass240 bool doInitialization(Module &M) override { 241 EXPECT_FALSE(initialized); 242 initialized = true; 243 return false; 244 } doInitializationllvm::__anonef00cd880111::BPass245 bool doInitialization(Function &F) override { 246 inited++; 247 return false; 248 } runOnBasicBlockllvm::__anonef00cd880111::BPass249 bool runOnBasicBlock(BasicBlock &BB) override { 250 run(); 251 return false; 252 } doFinalizationllvm::__anonef00cd880111::BPass253 bool doFinalization(Function &F) override { 254 fin++; 255 return false; 256 } doFinalizationllvm::__anonef00cd880111::BPass257 bool doFinalization(Module &M) override { 258 EXPECT_FALSE(finalized); 259 finalized = true; 260 EXPECT_EQ(0, allocated); 261 return false; 262 } 263 }; 264 int BPass::inited=0; 265 int BPass::fin=0; 266 267 struct OnTheFlyTest: public ModulePass { 268 public: 269 static char ID; OnTheFlyTestllvm::__anonef00cd880111::OnTheFlyTest270 OnTheFlyTest() : ModulePass(ID) { 271 initializeFPassPass(*PassRegistry::getPassRegistry()); 272 } runOnModulellvm::__anonef00cd880111::OnTheFlyTest273 bool runOnModule(Module &M) override { 274 for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) { 275 Function &F = *I; 276 { 277 SCOPED_TRACE("Running on the fly function pass"); 278 getAnalysis<FPass>(F); 279 } 280 } 281 return false; 282 } getAnalysisUsagellvm::__anonef00cd880111::OnTheFlyTest283 void getAnalysisUsage(AnalysisUsage &AU) const override { 284 AU.addRequired<FPass>(); 285 } 286 }; 287 char OnTheFlyTest::ID=0; 288 TEST(PassManager,RunOnce)289 TEST(PassManager, RunOnce) { 290 LLVMContext Context; 291 Module M("test-once", Context); 292 struct ModuleNDNM *mNDNM = new ModuleNDNM(); 293 struct ModuleDNM *mDNM = new ModuleDNM(); 294 struct ModuleNDM *mNDM = new ModuleNDM(); 295 struct ModuleNDM2 *mNDM2 = new ModuleNDM2(); 296 297 mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; 298 299 legacy::PassManager Passes; 300 Passes.add(mNDM2); 301 Passes.add(mNDM); 302 Passes.add(mNDNM); 303 Passes.add(mDNM); 304 305 Passes.run(M); 306 // each pass must be run exactly once, since nothing invalidates them 307 EXPECT_EQ(1, mNDM->run); 308 EXPECT_EQ(1, mNDNM->run); 309 EXPECT_EQ(1, mDNM->run); 310 EXPECT_EQ(1, mNDM2->run); 311 } 312 TEST(PassManager,ReRun)313 TEST(PassManager, ReRun) { 314 LLVMContext Context; 315 Module M("test-rerun", Context); 316 struct ModuleNDNM *mNDNM = new ModuleNDNM(); 317 struct ModuleDNM *mDNM = new ModuleDNM(); 318 struct ModuleNDM *mNDM = new ModuleNDM(); 319 struct ModuleNDM2 *mNDM2 = new ModuleNDM2(); 320 321 mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; 322 323 legacy::PassManager Passes; 324 Passes.add(mNDM); 325 Passes.add(mNDNM); 326 Passes.add(mNDM2);// invalidates mNDM needed by mDNM 327 Passes.add(mDNM); 328 329 Passes.run(M); 330 // Some passes must be rerun because a pass that modified the 331 // module/function was run in between 332 EXPECT_EQ(2, mNDM->run); 333 EXPECT_EQ(1, mNDNM->run); 334 EXPECT_EQ(1, mNDM2->run); 335 EXPECT_EQ(1, mDNM->run); 336 } 337 338 Module *makeLLVMModule(LLVMContext &Context); 339 340 template<typename T> MemoryTestHelper(int run)341 void MemoryTestHelper(int run) { 342 LLVMContext Context; 343 std::unique_ptr<Module> M(makeLLVMModule(Context)); 344 T *P = new T(); 345 legacy::PassManager Passes; 346 Passes.add(P); 347 Passes.run(*M); 348 T::finishedOK(run); 349 } 350 351 template<typename T> MemoryTestHelper(int run,int N)352 void MemoryTestHelper(int run, int N) { 353 LLVMContext Context; 354 Module *M = makeLLVMModule(Context); 355 T *P = new T(); 356 legacy::PassManager Passes; 357 Passes.add(P); 358 Passes.run(*M); 359 T::finishedOK(run, N); 360 delete M; 361 } 362 TEST(PassManager,Memory)363 TEST(PassManager, Memory) { 364 // SCC#1: test1->test2->test3->test1 365 // SCC#2: test4 366 // SCC#3: indirect call node 367 { 368 SCOPED_TRACE("Callgraph pass"); 369 MemoryTestHelper<CGPass>(3); 370 } 371 372 { 373 SCOPED_TRACE("Function pass"); 374 MemoryTestHelper<FPass>(4);// 4 functions 375 } 376 377 { 378 SCOPED_TRACE("Loop pass"); 379 MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function 380 } 381 { 382 SCOPED_TRACE("Basic block pass"); 383 MemoryTestHelper<BPass>(7, 4); //9 basic blocks 384 } 385 386 } 387 TEST(PassManager,MemoryOnTheFly)388 TEST(PassManager, MemoryOnTheFly) { 389 LLVMContext Context; 390 Module *M = makeLLVMModule(Context); 391 { 392 SCOPED_TRACE("Running OnTheFlyTest"); 393 struct OnTheFlyTest *O = new OnTheFlyTest(); 394 legacy::PassManager Passes; 395 Passes.add(O); 396 Passes.run(*M); 397 398 FPass::finishedOK(4); 399 } 400 delete M; 401 } 402 makeLLVMModule(LLVMContext & Context)403 Module *makeLLVMModule(LLVMContext &Context) { 404 // Module Construction 405 Module *mod = new Module("test-mem", Context); 406 mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" 407 "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" 408 "a:0:64-s:64:64-f80:128:128"); 409 mod->setTargetTriple("x86_64-unknown-linux-gnu"); 410 411 // Type Definitions 412 std::vector<Type*>FuncTy_0_args; 413 FunctionType *FuncTy_0 = FunctionType::get( 414 /*Result=*/IntegerType::get(Context, 32), 415 /*Params=*/FuncTy_0_args, 416 /*isVarArg=*/false); 417 418 std::vector<Type*>FuncTy_2_args; 419 FuncTy_2_args.push_back(IntegerType::get(Context, 1)); 420 FunctionType *FuncTy_2 = FunctionType::get( 421 /*Result=*/Type::getVoidTy(Context), 422 /*Params=*/FuncTy_2_args, 423 /*isVarArg=*/false); 424 425 // Function Declarations 426 427 Function* func_test1 = Function::Create( 428 /*Type=*/FuncTy_0, 429 /*Linkage=*/GlobalValue::ExternalLinkage, 430 /*Name=*/"test1", mod); 431 func_test1->setCallingConv(CallingConv::C); 432 AttributeSet func_test1_PAL; 433 func_test1->setAttributes(func_test1_PAL); 434 435 Function* func_test2 = Function::Create( 436 /*Type=*/FuncTy_0, 437 /*Linkage=*/GlobalValue::ExternalLinkage, 438 /*Name=*/"test2", mod); 439 func_test2->setCallingConv(CallingConv::C); 440 AttributeSet func_test2_PAL; 441 func_test2->setAttributes(func_test2_PAL); 442 443 Function* func_test3 = Function::Create( 444 /*Type=*/FuncTy_0, 445 /*Linkage=*/GlobalValue::ExternalLinkage, 446 /*Name=*/"test3", mod); 447 func_test3->setCallingConv(CallingConv::C); 448 AttributeSet func_test3_PAL; 449 func_test3->setAttributes(func_test3_PAL); 450 451 Function* func_test4 = Function::Create( 452 /*Type=*/FuncTy_2, 453 /*Linkage=*/GlobalValue::ExternalLinkage, 454 /*Name=*/"test4", mod); 455 func_test4->setCallingConv(CallingConv::C); 456 AttributeSet func_test4_PAL; 457 func_test4->setAttributes(func_test4_PAL); 458 459 // Global Variable Declarations 460 461 462 // Constant Definitions 463 464 // Global Variable Definitions 465 466 // Function Definitions 467 468 // Function: test1 (func_test1) 469 { 470 471 BasicBlock *label_entry = 472 BasicBlock::Create(Context, "entry", func_test1, nullptr); 473 474 // Block entry (label_entry) 475 CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry); 476 int32_3->setCallingConv(CallingConv::C); 477 int32_3->setTailCall(false);AttributeSet int32_3_PAL; 478 int32_3->setAttributes(int32_3_PAL); 479 480 ReturnInst::Create(Context, int32_3, label_entry); 481 } 482 483 // Function: test2 (func_test2) 484 { 485 486 BasicBlock *label_entry_5 = 487 BasicBlock::Create(Context, "entry", func_test2, nullptr); 488 489 // Block entry (label_entry_5) 490 CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5); 491 int32_6->setCallingConv(CallingConv::C); 492 int32_6->setTailCall(false);AttributeSet int32_6_PAL; 493 int32_6->setAttributes(int32_6_PAL); 494 495 ReturnInst::Create(Context, int32_6, label_entry_5); 496 } 497 498 // Function: test3 (func_test3) 499 { 500 501 BasicBlock *label_entry_8 = 502 BasicBlock::Create(Context, "entry", func_test3, nullptr); 503 504 // Block entry (label_entry_8) 505 CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8); 506 int32_9->setCallingConv(CallingConv::C); 507 int32_9->setTailCall(false);AttributeSet int32_9_PAL; 508 int32_9->setAttributes(int32_9_PAL); 509 510 ReturnInst::Create(Context, int32_9, label_entry_8); 511 } 512 513 // Function: test4 (func_test4) 514 { 515 Function::arg_iterator args = func_test4->arg_begin(); 516 Value *int1_f = &*args++; 517 int1_f->setName("f"); 518 519 BasicBlock *label_entry_11 = 520 BasicBlock::Create(Context, "entry", func_test4, nullptr); 521 BasicBlock *label_bb = 522 BasicBlock::Create(Context, "bb", func_test4, nullptr); 523 BasicBlock *label_bb1 = 524 BasicBlock::Create(Context, "bb1", func_test4, nullptr); 525 BasicBlock *label_return = 526 BasicBlock::Create(Context, "return", func_test4, nullptr); 527 528 // Block entry (label_entry_11) 529 BranchInst::Create(label_bb, label_entry_11); 530 531 // Block bb (label_bb) 532 BranchInst::Create(label_bb, label_bb1, int1_f, label_bb); 533 534 // Block bb1 (label_bb1) 535 BranchInst::Create(label_bb1, label_return, int1_f, label_bb1); 536 537 // Block return (label_return) 538 ReturnInst::Create(Context, label_return); 539 } 540 return mod; 541 } 542 543 } 544 } 545 546 INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false) 547 INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false) 548 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) 549 INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false) 550 INITIALIZE_PASS(FPass, "fp","fp", false, false) 551 INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false) 552 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) 553 INITIALIZE_PASS_END(LPass, "lp","lp", false, false) 554 INITIALIZE_PASS(BPass, "bp","bp", false, false) 555