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