[lit] Remove unnecessary tracking of test_index
[llvm-complete.git] / unittests / IR / LegacyPassManagerTest.cpp
blob6c0c251aff9f181f8ead928d0de75d4479d70d7a
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.
13 //===----------------------------------------------------------------------===//
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"
34 using namespace llvm;
36 namespace llvm {
37 void initializeModuleNDMPass(PassRegistry&);
38 void initializeFPassPass(PassRegistry&);
39 void initializeCGPassPass(PassRegistry&);
40 void initializeLPassPass(PassRegistry&);
41 void initializeBPassPass(PassRegistry&);
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;
55 void getAnalysisUsage(AnalysisUsage &AU) const override {
56 AU.setPreservesAll();
59 char ModuleNDNM::ID=0;
60 char ModuleNDNM::run=0;
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;
72 char ModuleNDM::ID=0;
73 char ModuleNDM::run=0;
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;
85 char ModuleNDM2::ID=0;
86 char ModuleNDM2::run=0;
88 struct ModuleDNM : public ModulePass {
89 public:
90 static char run;
91 static char ID;
92 ModuleDNM() : ModulePass(ID) {
93 initializeModuleNDMPass(*PassRegistry::getPassRegistry());
95 bool runOnModule(Module &M) override {
96 run++;
97 return false;
99 void getAnalysisUsage(AnalysisUsage &AU) const override {
100 AU.addRequired<ModuleNDM>();
101 AU.setPreservesAll();
104 char ModuleDNM::ID=0;
105 char ModuleDNM::run=0;
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++;
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);
129 PassTestBase() : P(ID), allocated(0) {
130 initialized = false;
131 finalized = false;
132 runc = 0;
135 void releaseMemory() override {
136 EXPECT_GT(runc, 0);
137 EXPECT_GT(allocated, 0);
138 allocated--;
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;
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;
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;
166 struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> {
167 public:
168 CGPass() {
169 initializeCGPassPass(*PassRegistry::getPassRegistry());
171 bool runOnSCC(CallGraphSCC &SCMM) override {
172 run();
173 return false;
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;
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);
197 static void finishedOK(int run, int finalized) {
198 PassTestBase<LoopPass>::finishedOK(run);
199 EXPECT_EQ(run, initcount);
200 EXPECT_EQ(finalized, fincount);
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;
209 bool runOnLoop(Loop *L, LPPassManager &LPM) override {
210 run();
211 return false;
213 bool doFinalization() override {
214 fincount++;
215 finalized = true;
216 return false;
219 int LPass::initcount=0;
220 int LPass::fincount=0;
222 struct BPass : public PassTestBase<BasicBlockPass> {
223 private:
224 static int inited;
225 static int fin;
226 public:
227 static void finishedOK(int run, int N) {
228 PassTestBase<BasicBlockPass>::finishedOK(run);
229 EXPECT_EQ(inited, N);
230 EXPECT_EQ(fin, N);
232 BPass() {
233 inited = 0;
234 fin = 0;
236 bool doInitialization(Module &M) override {
237 EXPECT_FALSE(initialized);
238 initialized = true;
239 return false;
241 bool doInitialization(Function &F) override {
242 inited++;
243 return false;
245 bool runOnBasicBlock(BasicBlock &BB) override {
246 run();
247 return false;
249 bool doFinalization(Function &F) override {
250 fin++;
251 return false;
253 bool doFinalization(Module &M) override {
254 EXPECT_FALSE(finalized);
255 finalized = true;
256 EXPECT_EQ(0, allocated);
257 return false;
260 int BPass::inited=0;
261 int BPass::fin=0;
263 struct OnTheFlyTest: public ModulePass {
264 public:
265 static char ID;
266 OnTheFlyTest() : ModulePass(ID) {
267 initializeFPassPass(*PassRegistry::getPassRegistry());
269 bool runOnModule(Module &M) override {
270 for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) {
271 Function &F = *I;
273 SCOPED_TRACE("Running on the fly function pass");
274 getAnalysis<FPass>(F);
277 return false;
279 void getAnalysisUsage(AnalysisUsage &AU) const override {
280 AU.addRequired<FPass>();
283 char OnTheFlyTest::ID=0;
285 TEST(PassManager, RunOnce) {
286 LLVMContext Context;
287 Module M("test-once", Context);
288 struct ModuleNDNM *mNDNM = new ModuleNDNM();
289 struct ModuleDNM *mDNM = new ModuleDNM();
290 struct ModuleNDM *mNDM = new ModuleNDM();
291 struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
293 mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
295 legacy::PassManager Passes;
296 Passes.add(mNDM2);
297 Passes.add(mNDM);
298 Passes.add(mNDNM);
299 Passes.add(mDNM);
301 Passes.run(M);
302 // each pass must be run exactly once, since nothing invalidates them
303 EXPECT_EQ(1, mNDM->run);
304 EXPECT_EQ(1, mNDNM->run);
305 EXPECT_EQ(1, mDNM->run);
306 EXPECT_EQ(1, mNDM2->run);
309 TEST(PassManager, ReRun) {
310 LLVMContext Context;
311 Module M("test-rerun", Context);
312 struct ModuleNDNM *mNDNM = new ModuleNDNM();
313 struct ModuleDNM *mDNM = new ModuleDNM();
314 struct ModuleNDM *mNDM = new ModuleNDM();
315 struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
317 mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
319 legacy::PassManager Passes;
320 Passes.add(mNDM);
321 Passes.add(mNDNM);
322 Passes.add(mNDM2);// invalidates mNDM needed by mDNM
323 Passes.add(mDNM);
325 Passes.run(M);
326 // Some passes must be rerun because a pass that modified the
327 // module/function was run in between
328 EXPECT_EQ(2, mNDM->run);
329 EXPECT_EQ(1, mNDNM->run);
330 EXPECT_EQ(1, mNDM2->run);
331 EXPECT_EQ(1, mDNM->run);
334 Module *makeLLVMModule(LLVMContext &Context);
336 template<typename T>
337 void MemoryTestHelper(int run) {
338 LLVMContext Context;
339 std::unique_ptr<Module> M(makeLLVMModule(Context));
340 T *P = new T();
341 legacy::PassManager Passes;
342 Passes.add(P);
343 Passes.run(*M);
344 T::finishedOK(run);
347 template<typename T>
348 void MemoryTestHelper(int run, int N) {
349 LLVMContext Context;
350 Module *M = makeLLVMModule(Context);
351 T *P = new T();
352 legacy::PassManager Passes;
353 Passes.add(P);
354 Passes.run(*M);
355 T::finishedOK(run, N);
356 delete M;
359 TEST(PassManager, Memory) {
360 // SCC#1: test1->test2->test3->test1
361 // SCC#2: test4
362 // SCC#3: indirect call node
364 SCOPED_TRACE("Callgraph pass");
365 MemoryTestHelper<CGPass>(3);
369 SCOPED_TRACE("Function pass");
370 MemoryTestHelper<FPass>(4);// 4 functions
374 SCOPED_TRACE("Loop pass");
375 MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function
378 SCOPED_TRACE("Basic block pass");
379 MemoryTestHelper<BPass>(7, 4); //9 basic blocks
384 TEST(PassManager, MemoryOnTheFly) {
385 LLVMContext Context;
386 Module *M = makeLLVMModule(Context);
388 SCOPED_TRACE("Running OnTheFlyTest");
389 struct OnTheFlyTest *O = new OnTheFlyTest();
390 legacy::PassManager Passes;
391 Passes.add(O);
392 Passes.run(*M);
394 FPass::finishedOK(4);
396 delete M;
399 // Skips or runs optional passes.
400 struct CustomOptPassGate : public OptPassGate {
401 bool Skip;
402 CustomOptPassGate(bool Skip) : Skip(Skip) { }
403 bool shouldRunPass(const Pass *P, StringRef IRDescription) {
404 if (P->getPassKind() == PT_Module)
405 return !Skip;
406 return OptPassGate::shouldRunPass(P, IRDescription);
408 bool isEnabled() const { return true; }
411 // Optional module pass.
412 struct ModuleOpt: public ModulePass {
413 char run = 0;
414 static char ID;
415 ModuleOpt() : ModulePass(ID) { }
416 bool runOnModule(Module &M) override {
417 if (!skipModule(M))
418 run++;
419 return false;
422 char ModuleOpt::ID=0;
424 TEST(PassManager, CustomOptPassGate) {
425 LLVMContext Context0;
426 LLVMContext Context1;
427 LLVMContext Context2;
428 CustomOptPassGate SkipOptionalPasses(true);
429 CustomOptPassGate RunOptionalPasses(false);
431 Module M0("custom-opt-bisect", Context0);
432 Module M1("custom-opt-bisect", Context1);
433 Module M2("custom-opt-bisect2", Context2);
434 struct ModuleOpt *mOpt0 = new ModuleOpt();
435 struct ModuleOpt *mOpt1 = new ModuleOpt();
436 struct ModuleOpt *mOpt2 = new ModuleOpt();
438 mOpt0->run = mOpt1->run = mOpt2->run = 0;
440 legacy::PassManager Passes0;
441 legacy::PassManager Passes1;
442 legacy::PassManager Passes2;
444 Passes0.add(mOpt0);
445 Passes1.add(mOpt1);
446 Passes2.add(mOpt2);
448 Context1.setOptPassGate(SkipOptionalPasses);
449 Context2.setOptPassGate(RunOptionalPasses);
451 Passes0.run(M0);
452 Passes1.run(M1);
453 Passes2.run(M2);
455 // By default optional passes are run.
456 EXPECT_EQ(1, mOpt0->run);
458 // The first context skips optional passes.
459 EXPECT_EQ(0, mOpt1->run);
461 // The second context runs optional passes.
462 EXPECT_EQ(1, mOpt2->run);
465 Module *makeLLVMModule(LLVMContext &Context) {
466 // Module Construction
467 Module *mod = new Module("test-mem", Context);
468 mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
469 "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
470 "a:0:64-s:64:64-f80:128:128");
471 mod->setTargetTriple("x86_64-unknown-linux-gnu");
473 // Type Definitions
474 std::vector<Type*>FuncTy_0_args;
475 FunctionType *FuncTy_0 = FunctionType::get(
476 /*Result=*/IntegerType::get(Context, 32),
477 /*Params=*/FuncTy_0_args,
478 /*isVarArg=*/false);
480 std::vector<Type*>FuncTy_2_args;
481 FuncTy_2_args.push_back(IntegerType::get(Context, 1));
482 FunctionType *FuncTy_2 = FunctionType::get(
483 /*Result=*/Type::getVoidTy(Context),
484 /*Params=*/FuncTy_2_args,
485 /*isVarArg=*/false);
487 // Function Declarations
489 Function* func_test1 = Function::Create(
490 /*Type=*/FuncTy_0,
491 /*Linkage=*/GlobalValue::ExternalLinkage,
492 /*Name=*/"test1", mod);
493 func_test1->setCallingConv(CallingConv::C);
494 AttributeList func_test1_PAL;
495 func_test1->setAttributes(func_test1_PAL);
497 Function* func_test2 = Function::Create(
498 /*Type=*/FuncTy_0,
499 /*Linkage=*/GlobalValue::ExternalLinkage,
500 /*Name=*/"test2", mod);
501 func_test2->setCallingConv(CallingConv::C);
502 AttributeList func_test2_PAL;
503 func_test2->setAttributes(func_test2_PAL);
505 Function* func_test3 = Function::Create(
506 /*Type=*/FuncTy_0,
507 /*Linkage=*/GlobalValue::ExternalLinkage,
508 /*Name=*/"test3", mod);
509 func_test3->setCallingConv(CallingConv::C);
510 AttributeList func_test3_PAL;
511 func_test3->setAttributes(func_test3_PAL);
513 Function* func_test4 = Function::Create(
514 /*Type=*/FuncTy_2,
515 /*Linkage=*/GlobalValue::ExternalLinkage,
516 /*Name=*/"test4", mod);
517 func_test4->setCallingConv(CallingConv::C);
518 AttributeList func_test4_PAL;
519 func_test4->setAttributes(func_test4_PAL);
521 // Global Variable Declarations
524 // Constant Definitions
526 // Global Variable Definitions
528 // Function Definitions
530 // Function: test1 (func_test1)
533 BasicBlock *label_entry =
534 BasicBlock::Create(Context, "entry", func_test1, nullptr);
536 // Block entry (label_entry)
537 CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry);
538 int32_3->setCallingConv(CallingConv::C);
539 int32_3->setTailCall(false);
540 AttributeList int32_3_PAL;
541 int32_3->setAttributes(int32_3_PAL);
543 ReturnInst::Create(Context, int32_3, label_entry);
546 // Function: test2 (func_test2)
549 BasicBlock *label_entry_5 =
550 BasicBlock::Create(Context, "entry", func_test2, nullptr);
552 // Block entry (label_entry_5)
553 CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5);
554 int32_6->setCallingConv(CallingConv::C);
555 int32_6->setTailCall(false);
556 AttributeList int32_6_PAL;
557 int32_6->setAttributes(int32_6_PAL);
559 ReturnInst::Create(Context, int32_6, label_entry_5);
562 // Function: test3 (func_test3)
565 BasicBlock *label_entry_8 =
566 BasicBlock::Create(Context, "entry", func_test3, nullptr);
568 // Block entry (label_entry_8)
569 CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8);
570 int32_9->setCallingConv(CallingConv::C);
571 int32_9->setTailCall(false);
572 AttributeList int32_9_PAL;
573 int32_9->setAttributes(int32_9_PAL);
575 ReturnInst::Create(Context, int32_9, label_entry_8);
578 // Function: test4 (func_test4)
580 Function::arg_iterator args = func_test4->arg_begin();
581 Value *int1_f = &*args++;
582 int1_f->setName("f");
584 BasicBlock *label_entry_11 =
585 BasicBlock::Create(Context, "entry", func_test4, nullptr);
586 BasicBlock *label_bb =
587 BasicBlock::Create(Context, "bb", func_test4, nullptr);
588 BasicBlock *label_bb1 =
589 BasicBlock::Create(Context, "bb1", func_test4, nullptr);
590 BasicBlock *label_return =
591 BasicBlock::Create(Context, "return", func_test4, nullptr);
593 // Block entry (label_entry_11)
594 BranchInst::Create(label_bb, label_entry_11);
596 // Block bb (label_bb)
597 BranchInst::Create(label_bb, label_bb1, int1_f, label_bb);
599 // Block bb1 (label_bb1)
600 BranchInst::Create(label_bb1, label_return, int1_f, label_bb1);
602 // Block return (label_return)
603 ReturnInst::Create(Context, label_return);
605 return mod;
611 INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false)
612 INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false)
613 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
614 INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false)
615 INITIALIZE_PASS(FPass, "fp","fp", false, false)
616 INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false)
617 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
618 INITIALIZE_PASS_END(LPass, "lp","lp", false, false)
619 INITIALIZE_PASS(BPass, "bp","bp", false, false)