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