Hold the LLVMContext by reference rather than by pointer.
[oota-llvm.git] / unittests / VMCore / PassManagerTest.cpp
1 //===- llvm/unittest/VMCore/PassManager.cpp - Constants unit 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 #include "llvm/Module.h"
11 #include "llvm/LLVMContext.h"
12 #include "llvm/PassManager.h"
13 #include "llvm/Analysis/LoopInfo.h"
14 #include "llvm/Pass.h"
15 #include "llvm/Analysis/LoopPass.h"
16 #include "llvm/CallGraphSCCPass.h"
17 #include "llvm/Target/TargetData.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/DerivedTypes.h"
20 #include "llvm/Constants.h"
21 #include "llvm/GlobalVariable.h"
22 #include "llvm/Function.h"
23 #include "llvm/CallingConv.h"
24 #include "llvm/BasicBlock.h"
25 #include "llvm/Instructions.h"
26 #include "llvm/InlineAsm.h"
27 #include "llvm/Support/MathExtras.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include "llvm/PassManager.h"
30 #include "llvm/ADT/SmallVector.h"
31 #include "llvm/Analysis/Verifier.h"
32 #include "llvm/Assembly/PrintModulePass.h"
33 #include "gtest/gtest.h"
34
35 namespace llvm {
36   namespace {
37     // ND = no deps
38     // NM = no modifications
39     struct ModuleNDNM: public ModulePass {
40     public:
41       static char run;
42       static char ID;
43       ModuleNDNM() : ModulePass(&ID) {}
44       virtual bool runOnModule(Module &M) {
45         run++;
46         return false;
47       }
48       virtual void getAnalysisUsage(AnalysisUsage &AU) const {
49         AU.setPreservesAll();
50       }
51     };
52     char ModuleNDNM::ID=0;
53     char ModuleNDNM::run=0;
54
55     struct ModuleNDM : public ModulePass {
56     public:
57       static char run;
58       static char ID;
59       ModuleNDM() : ModulePass(&ID) {}
60       virtual bool runOnModule(Module &M) {
61         run++;
62         return true;
63       }
64     };
65     char ModuleNDM::ID=0;
66     char ModuleNDM::run=0;
67     RegisterPass<ModuleNDM> X("mndm","mndm",false,false);
68
69     struct ModuleNDM2 : public ModulePass {
70     public:
71       static char run;
72       static char ID;
73       ModuleNDM2() : ModulePass(&ID) {}
74       virtual bool runOnModule(Module &M) {
75         run++;
76         return true;
77       }
78     };
79     char ModuleNDM2::ID=0;
80     char ModuleNDM2::run=0;
81
82     struct ModuleDNM : public ModulePass {
83     public:
84       static char run;
85       static char ID;
86       ModuleDNM() : ModulePass(&ID) {}
87       virtual bool runOnModule(Module &M) {
88         EXPECT_TRUE(getAnalysisIfAvailable<TargetData>());
89         run++;
90         return false;
91       }
92       virtual void getAnalysisUsage(AnalysisUsage &AU) const {
93         AU.addRequired<ModuleNDM>();
94         AU.setPreservesAll();
95       }
96     };
97     char ModuleDNM::ID=0;
98     char ModuleDNM::run=0;
99
100     template<typename P>
101     struct PassTestBase : public P {
102     protected:
103       static int runc;
104       static bool initialized;
105       static bool finalized;
106       int allocated;
107       void run() {
108         EXPECT_EQ(true, initialized);
109         EXPECT_EQ(false, finalized);
110         EXPECT_EQ(0, allocated);
111         allocated++;
112         runc++;
113       }
114     public:
115       static char ID;
116       static void finishedOK(int run) {
117         EXPECT_GT(runc, 0);
118         EXPECT_EQ(true, initialized);
119         EXPECT_EQ(true, finalized);
120         EXPECT_EQ(run, runc);
121       }
122       PassTestBase() : P(&ID), allocated(0) {
123         initialized = false;
124         finalized = false;
125         runc = 0;
126       }
127
128       virtual void releaseMemory() {
129         EXPECT_GT(runc, 0);
130         EXPECT_GT(allocated, 0);
131         allocated--;
132       }
133     };
134     template<typename P> char PassTestBase<P>::ID;
135     template<typename P> int PassTestBase<P>::runc;
136     template<typename P> bool PassTestBase<P>::initialized;
137     template<typename P> bool PassTestBase<P>::finalized;
138
139     template<typename T, typename P>
140     struct PassTest : public PassTestBase<P> {
141     public:
142       virtual bool doInitialization(T &t) {
143         EXPECT_EQ(false, PassTestBase<P>::initialized);
144         PassTestBase<P>::initialized = true;
145         return false;
146       }
147       virtual bool doFinalization(T &t) {
148         EXPECT_EQ(false, PassTestBase<P>::finalized);
149         PassTestBase<P>::finalized = true;
150         EXPECT_EQ(0, PassTestBase<P>::allocated);
151         return false;
152       }
153     };
154
155     struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> {
156     public:
157       virtual bool runOnSCC(const std::vector<CallGraphNode*> &SCMM) {
158         EXPECT_TRUE(getAnalysisIfAvailable<TargetData>());
159         run();
160         return false;
161       }
162     };
163     RegisterPass<CGPass> X1("cgp","cgp");
164
165     struct FPass : public PassTest<Module, FunctionPass> {
166     public:
167       virtual bool runOnFunction(Function &F) {
168         // FIXME: PR4112
169         // EXPECT_TRUE(getAnalysisIfAvailable<TargetData>());
170         run();
171         return false;
172       }
173     };
174     RegisterPass<FPass> X2("fp","fp");
175
176     struct LPass : public PassTestBase<LoopPass> {
177     private:
178       static int initcount;
179       static int fincount;
180     public:
181       LPass() {
182         initcount = 0; fincount=0;
183         EXPECT_EQ(false, initialized);
184       }
185       static void finishedOK(int run, int finalized) {
186         PassTestBase<LoopPass>::finishedOK(run);
187         EXPECT_EQ(run, initcount);
188         EXPECT_EQ(finalized, fincount);
189       }
190       virtual bool doInitialization(Loop* L, LPPassManager &LPM) {
191         initialized = true;
192         initcount++;
193         return false;
194       }
195       virtual bool runOnLoop(Loop *L, LPPassManager &LPM) {
196         EXPECT_TRUE(getAnalysisIfAvailable<TargetData>());
197         run();
198         return false;
199       }
200       virtual bool doFinalization() {
201         fincount++;
202         finalized = true;
203         return false;
204       }
205     };
206     int LPass::initcount=0;
207     int LPass::fincount=0;
208     RegisterPass<LPass> X3("lp","lp");
209
210     struct BPass : public PassTestBase<BasicBlockPass> {
211     private:
212       static int inited;
213       static int fin;
214     public:
215       static void finishedOK(int run, int N) {
216         PassTestBase<BasicBlockPass>::finishedOK(run);
217         EXPECT_EQ(inited, N);
218         EXPECT_EQ(fin, N);
219       }
220       BPass() {
221         inited = 0;
222         fin = 0;
223       }
224       virtual bool doInitialization(Module &M) {
225         EXPECT_EQ(false, initialized);
226         initialized = true;
227         return false;
228       }
229       virtual bool doInitialization(Function &F) {
230         inited++;
231         return false;
232       }
233       virtual bool runOnBasicBlock(BasicBlock &BB) {
234         EXPECT_TRUE(getAnalysisIfAvailable<TargetData>());
235         run();
236         return false;
237       }
238       virtual bool doFinalization(Function &F) {
239         fin++;
240         return false;
241       }
242       virtual bool doFinalization(Module &M) {
243         EXPECT_EQ(false, finalized);
244         finalized = true;
245         EXPECT_EQ(0, allocated);
246         return false;
247       }
248     };
249     int BPass::inited=0;
250     int BPass::fin=0;
251     RegisterPass<BPass> X4("bp","bp");
252
253     struct OnTheFlyTest: public ModulePass {
254     public:
255       static char ID;
256       OnTheFlyTest() : ModulePass(&ID) {}
257       virtual bool runOnModule(Module &M) {
258         EXPECT_TRUE(getAnalysisIfAvailable<TargetData>());
259         for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) {
260           Function &F = *I;
261           {
262             SCOPED_TRACE("Running on the fly function pass");
263             getAnalysis<FPass>(F);
264           }
265         }
266         return false;
267       }
268       virtual void getAnalysisUsage(AnalysisUsage &AU) const {
269         AU.addRequired<FPass>();
270       }
271     };
272     char OnTheFlyTest::ID=0;
273
274     TEST(PassManager, RunOnce) {
275       Module M("test-once", *new LLVMContext());
276       struct ModuleNDNM *mNDNM = new ModuleNDNM();
277       struct ModuleDNM *mDNM = new ModuleDNM();
278       struct ModuleNDM *mNDM = new ModuleNDM();
279       struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
280
281       mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
282
283       PassManager Passes;
284       Passes.add(new TargetData(&M));
285       Passes.add(mNDM2);
286       Passes.add(mNDM);
287       Passes.add(mNDNM);
288       Passes.add(mDNM);
289
290       Passes.run(M);
291       // each pass must be run exactly once, since nothing invalidates them
292       EXPECT_EQ(1, mNDM->run);
293       EXPECT_EQ(1, mNDNM->run);
294       EXPECT_EQ(1, mDNM->run);
295       EXPECT_EQ(1, mNDM2->run);
296     }
297
298     TEST(PassManager, ReRun) {
299       Module M("test-rerun", *new LLVMContext());
300       struct ModuleNDNM *mNDNM = new ModuleNDNM();
301       struct ModuleDNM *mDNM = new ModuleDNM();
302       struct ModuleNDM *mNDM = new ModuleNDM();
303       struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
304
305       mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
306
307       PassManager Passes;
308       Passes.add(new TargetData(&M));
309       Passes.add(mNDM);
310       Passes.add(mNDNM);
311       Passes.add(mNDM2);// invalidates mNDM needed by mDNM
312       Passes.add(mDNM);
313
314       Passes.run(M);
315       // Some passes must be rerun because a pass that modified the
316       // module/function was run inbetween
317       EXPECT_EQ(2, mNDM->run);
318       EXPECT_EQ(1, mNDNM->run);
319       EXPECT_EQ(1, mNDM2->run);
320       EXPECT_EQ(1, mDNM->run);
321     }
322
323     Module* makeLLVMModule();
324
325     template<typename T>
326     void MemoryTestHelper(int run) {
327       Module *M = makeLLVMModule();
328       T *P = new T();
329       PassManager Passes;
330       Passes.add(new TargetData(M));
331       Passes.add(P);
332       Passes.run(*M);
333       T::finishedOK(run);
334     }
335
336     template<typename T>
337     void MemoryTestHelper(int run, int N) {
338       Module *M = makeLLVMModule();
339       T *P = new T();
340       PassManager Passes;
341       Passes.add(new TargetData(M));
342       Passes.add(P);
343       Passes.run(*M);
344       T::finishedOK(run, N);
345       delete M;
346     }
347
348     TEST(PassManager, Memory) {
349       // SCC#1: test1->test2->test3->test1
350       // SCC#2: test4
351       // SCC#3: indirect call node
352       {
353         SCOPED_TRACE("Callgraph pass");
354         MemoryTestHelper<CGPass>(3);
355       }
356
357       {
358         SCOPED_TRACE("Function pass");
359         MemoryTestHelper<FPass>(4);// 4 functions
360       }
361
362       {
363         SCOPED_TRACE("Loop pass");
364         MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function
365       }
366       {
367         SCOPED_TRACE("Basic block pass");
368         MemoryTestHelper<BPass>(7, 4); //9 basic blocks
369       }
370
371     }
372
373     TEST(PassManager, MemoryOnTheFly) {
374       Module *M = makeLLVMModule();
375       {
376         SCOPED_TRACE("Running OnTheFlyTest");
377         struct OnTheFlyTest *O = new OnTheFlyTest();
378         PassManager Passes;
379         Passes.add(new TargetData(M));
380         Passes.add(O);
381         Passes.run(*M);
382
383         FPass::finishedOK(4);
384       }
385       delete M;
386     }
387
388     Module* makeLLVMModule() {
389       // Module Construction
390       Module* mod = new Module("test-mem", *new LLVMContext());
391       mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
392                          "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
393                          "a0:0:64-s0:64:64-f80:128:128");
394       mod->setTargetTriple("x86_64-unknown-linux-gnu");
395
396       // Type Definitions
397       std::vector<const Type*>FuncTy_0_args;
398       FunctionType* FuncTy_0 = FunctionType::get(
399         /*Result=*/IntegerType::get(32),
400         /*Params=*/FuncTy_0_args,
401         /*isVarArg=*/false);
402
403       std::vector<const Type*>FuncTy_2_args;
404       FuncTy_2_args.push_back(IntegerType::get(1));
405       FunctionType* FuncTy_2 = FunctionType::get(
406         /*Result=*/Type::VoidTy,
407         /*Params=*/FuncTy_2_args,
408         /*isVarArg=*/false);
409
410
411       // Function Declarations
412
413       Function* func_test1 = Function::Create(
414         /*Type=*/FuncTy_0,
415         /*Linkage=*/GlobalValue::ExternalLinkage,
416         /*Name=*/"test1", mod);
417       func_test1->setCallingConv(CallingConv::C);
418       AttrListPtr func_test1_PAL;
419       func_test1->setAttributes(func_test1_PAL);
420
421       Function* func_test2 = Function::Create(
422         /*Type=*/FuncTy_0,
423         /*Linkage=*/GlobalValue::ExternalLinkage,
424         /*Name=*/"test2", mod);
425       func_test2->setCallingConv(CallingConv::C);
426       AttrListPtr func_test2_PAL;
427       func_test2->setAttributes(func_test2_PAL);
428
429       Function* func_test3 = Function::Create(
430         /*Type=*/FuncTy_0,
431         /*Linkage=*/GlobalValue::ExternalLinkage,
432         /*Name=*/"test3", mod);
433       func_test3->setCallingConv(CallingConv::C);
434       AttrListPtr func_test3_PAL;
435       func_test3->setAttributes(func_test3_PAL);
436
437       Function* func_test4 = Function::Create(
438         /*Type=*/FuncTy_2,
439         /*Linkage=*/GlobalValue::ExternalLinkage,
440         /*Name=*/"test4", mod);
441       func_test4->setCallingConv(CallingConv::C);
442       AttrListPtr func_test4_PAL;
443       func_test4->setAttributes(func_test4_PAL);
444
445       // Global Variable Declarations
446
447
448       // Constant Definitions
449
450       // Global Variable Definitions
451
452       // Function Definitions
453
454       // Function: test1 (func_test1)
455       {
456
457         BasicBlock* label_entry = BasicBlock::Create("entry",func_test1,0);
458
459         // Block entry (label_entry)
460         CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry);
461         int32_3->setCallingConv(CallingConv::C);
462         int32_3->setTailCall(false);AttrListPtr int32_3_PAL;
463         int32_3->setAttributes(int32_3_PAL);
464
465         ReturnInst::Create(int32_3, label_entry);
466
467       }
468
469       // Function: test2 (func_test2)
470       {
471
472         BasicBlock* label_entry_5 = BasicBlock::Create("entry",func_test2,0);
473
474         // Block entry (label_entry_5)
475         CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5);
476         int32_6->setCallingConv(CallingConv::C);
477         int32_6->setTailCall(false);AttrListPtr int32_6_PAL;
478         int32_6->setAttributes(int32_6_PAL);
479
480         ReturnInst::Create(int32_6, label_entry_5);
481
482       }
483
484       // Function: test3 (func_test3)
485       {
486
487         BasicBlock* label_entry_8 = BasicBlock::Create("entry",func_test3,0);
488
489         // Block entry (label_entry_8)
490         CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8);
491         int32_9->setCallingConv(CallingConv::C);
492         int32_9->setTailCall(false);AttrListPtr int32_9_PAL;
493         int32_9->setAttributes(int32_9_PAL);
494
495         ReturnInst::Create(int32_9, label_entry_8);
496
497       }
498
499       // Function: test4 (func_test4)
500       {
501         Function::arg_iterator args = func_test4->arg_begin();
502         Value* int1_f = args++;
503         int1_f->setName("f");
504
505         BasicBlock* label_entry_11 = BasicBlock::Create("entry",func_test4,0);
506         BasicBlock* label_bb = BasicBlock::Create("bb",func_test4,0);
507         BasicBlock* label_bb1 = BasicBlock::Create("bb1",func_test4,0);
508         BasicBlock* label_return = BasicBlock::Create("return",func_test4,0);
509
510         // Block entry (label_entry_11)
511         BranchInst::Create(label_bb, label_entry_11);
512
513         // Block bb (label_bb)
514         BranchInst::Create(label_bb, label_bb1, int1_f, label_bb);
515
516         // Block bb1 (label_bb1)
517         BranchInst::Create(label_bb1, label_return, int1_f, label_bb1);
518
519         // Block return (label_return)
520         ReturnInst::Create(label_return);
521
522       }
523       return mod;
524     }
525
526   }
527 }