Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / unittests / IR / LegacyPassManagerTest.cpp
blob6a4cc4d7a98297846e89961fbddedadb61a34395
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/CallGraph.h"
17 #include "llvm/Analysis/CallGraphSCCPass.h"
18 #include "llvm/Analysis/LoopInfo.h"
19 #include "llvm/Analysis/LoopPass.h"
20 #include "llvm/AsmParser/Parser.h"
21 #include "llvm/IR/AbstractCallSite.h"
22 #include "llvm/IR/BasicBlock.h"
23 #include "llvm/IR/CallingConv.h"
24 #include "llvm/IR/DataLayout.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/IR/GlobalVariable.h"
28 #include "llvm/IR/Instructions.h"
29 #include "llvm/IR/LLVMContext.h"
30 #include "llvm/IR/Module.h"
31 #include "llvm/IR/OptBisect.h"
32 #include "llvm/InitializePasses.h"
33 #include "llvm/Support/MathExtras.h"
34 #include "llvm/Support/SourceMgr.h"
35 #include "llvm/Support/raw_ostream.h"
36 #include "llvm/Transforms/Utils/CallGraphUpdater.h"
37 #include "gtest/gtest.h"
39 using namespace llvm;
41 namespace llvm {
42 void initializeModuleNDMPass(PassRegistry&);
43 void initializeFPassPass(PassRegistry&);
44 void initializeCGPassPass(PassRegistry&);
45 void initializeLPassPass(PassRegistry&);
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;
54 ModuleNDNM() : ModulePass(ID) { }
55 bool runOnModule(Module &M) override {
56 run++;
57 return false;
59 void getAnalysisUsage(AnalysisUsage &AU) const override {
60 AU.setPreservesAll();
63 char ModuleNDNM::ID=0;
64 char ModuleNDNM::run=0;
66 struct ModuleNDM : public ModulePass {
67 public:
68 static char run;
69 static char ID;
70 ModuleNDM() : ModulePass(ID) {}
71 bool runOnModule(Module &M) override {
72 run++;
73 return true;
76 char ModuleNDM::ID=0;
77 char ModuleNDM::run=0;
79 struct ModuleNDM2 : public ModulePass {
80 public:
81 static char run;
82 static char ID;
83 ModuleNDM2() : ModulePass(ID) {}
84 bool runOnModule(Module &M) override {
85 run++;
86 return true;
89 char ModuleNDM2::ID=0;
90 char ModuleNDM2::run=0;
92 struct ModuleDNM : public ModulePass {
93 public:
94 static char run;
95 static char ID;
96 ModuleDNM() : ModulePass(ID) {
97 initializeModuleNDMPass(*PassRegistry::getPassRegistry());
99 bool runOnModule(Module &M) override {
100 run++;
101 return false;
103 void getAnalysisUsage(AnalysisUsage &AU) const override {
104 AU.addRequired<ModuleNDM>();
105 AU.setPreservesAll();
108 char ModuleDNM::ID=0;
109 char ModuleDNM::run=0;
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;
118 void run() {
119 EXPECT_TRUE(initialized);
120 EXPECT_FALSE(finalized);
121 EXPECT_EQ(0, allocated);
122 allocated++;
123 runc++;
125 public:
126 static char ID;
127 static void finishedOK(int run) {
128 EXPECT_GT(runc, 0);
129 EXPECT_TRUE(initialized);
130 EXPECT_TRUE(finalized);
131 EXPECT_EQ(run, runc);
133 PassTestBase() : P(ID), allocated(0) {
134 initialized = false;
135 finalized = false;
136 runc = 0;
139 void releaseMemory() override {
140 EXPECT_GT(runc, 0);
141 EXPECT_GT(allocated, 0);
142 allocated--;
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;
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
157 bool doInitialization(T &t) override {
158 EXPECT_FALSE(PassTestBase<P>::initialized);
159 PassTestBase<P>::initialized = true;
160 return false;
162 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;
170 struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> {
171 public:
172 CGPass() {
173 initializeCGPassPass(*PassRegistry::getPassRegistry());
175 bool runOnSCC(CallGraphSCC &SCMM) override {
176 run();
177 return false;
181 struct FPass : public PassTest<Module, FunctionPass> {
182 public:
183 bool runOnFunction(Function &F) override {
184 // FIXME: PR4112
185 // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
186 run();
187 return false;
191 struct LPass : public PassTestBase<LoopPass> {
192 private:
193 static int initcount;
194 static int fincount;
195 public:
196 LPass() {
197 initializeLPassPass(*PassRegistry::getPassRegistry());
198 initcount = 0; fincount=0;
199 EXPECT_FALSE(initialized);
201 static void finishedOK(int run, int finalized) {
202 PassTestBase<LoopPass>::finishedOK(run);
203 EXPECT_EQ(run, initcount);
204 EXPECT_EQ(finalized, fincount);
206 using llvm::Pass::doInitialization;
207 using llvm::Pass::doFinalization;
208 bool doInitialization(Loop* L, LPPassManager &LPM) override {
209 initialized = true;
210 initcount++;
211 return false;
213 bool runOnLoop(Loop *L, LPPassManager &LPM) override {
214 run();
215 return false;
217 bool doFinalization() override {
218 fincount++;
219 finalized = true;
220 return false;
223 int LPass::initcount=0;
224 int LPass::fincount=0;
226 struct OnTheFlyTest: public ModulePass {
227 public:
228 static char ID;
229 OnTheFlyTest() : ModulePass(ID) {
230 initializeFPassPass(*PassRegistry::getPassRegistry());
232 bool runOnModule(Module &M) override {
233 for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) {
234 Function &F = *I;
236 SCOPED_TRACE("Running on the fly function pass");
237 getAnalysis<FPass>(F);
240 return false;
242 void getAnalysisUsage(AnalysisUsage &AU) const override {
243 AU.addRequired<FPass>();
246 char OnTheFlyTest::ID=0;
248 TEST(PassManager, RunOnce) {
249 LLVMContext Context;
250 Module M("test-once", Context);
251 struct ModuleNDNM *mNDNM = new ModuleNDNM();
252 struct ModuleDNM *mDNM = new ModuleDNM();
253 struct ModuleNDM *mNDM = new ModuleNDM();
254 struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
256 mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
258 legacy::PassManager Passes;
259 Passes.add(mNDM2);
260 Passes.add(mNDM);
261 Passes.add(mNDNM);
262 Passes.add(mDNM);
264 Passes.run(M);
265 // each pass must be run exactly once, since nothing invalidates them
266 EXPECT_EQ(1, mNDM->run);
267 EXPECT_EQ(1, mNDNM->run);
268 EXPECT_EQ(1, mDNM->run);
269 EXPECT_EQ(1, mNDM2->run);
272 TEST(PassManager, ReRun) {
273 LLVMContext Context;
274 Module M("test-rerun", Context);
275 struct ModuleNDNM *mNDNM = new ModuleNDNM();
276 struct ModuleDNM *mDNM = new ModuleDNM();
277 struct ModuleNDM *mNDM = new ModuleNDM();
278 struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
280 mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
282 legacy::PassManager Passes;
283 Passes.add(mNDM);
284 Passes.add(mNDNM);
285 Passes.add(mNDM2);// invalidates mNDM needed by mDNM
286 Passes.add(mDNM);
288 Passes.run(M);
289 // Some passes must be rerun because a pass that modified the
290 // module/function was run in between
291 EXPECT_EQ(2, mNDM->run);
292 EXPECT_EQ(1, mNDNM->run);
293 EXPECT_EQ(1, mNDM2->run);
294 EXPECT_EQ(1, mDNM->run);
297 Module *makeLLVMModule(LLVMContext &Context);
299 template<typename T>
300 void MemoryTestHelper(int run) {
301 LLVMContext Context;
302 std::unique_ptr<Module> M(makeLLVMModule(Context));
303 T *P = new T();
304 legacy::PassManager Passes;
305 Passes.add(P);
306 Passes.run(*M);
307 T::finishedOK(run);
310 template<typename T>
311 void MemoryTestHelper(int run, int N) {
312 LLVMContext Context;
313 Module *M = makeLLVMModule(Context);
314 T *P = new T();
315 legacy::PassManager Passes;
316 Passes.add(P);
317 Passes.run(*M);
318 T::finishedOK(run, N);
319 delete M;
322 TEST(PassManager, Memory) {
323 // SCC#1: test1->test2->test3->test1
324 // SCC#2: test4
325 // SCC#3: indirect call node
327 SCOPED_TRACE("Callgraph pass");
328 MemoryTestHelper<CGPass>(3);
332 SCOPED_TRACE("Function pass");
333 MemoryTestHelper<FPass>(4);// 4 functions
337 SCOPED_TRACE("Loop pass");
338 MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function
343 TEST(PassManager, MemoryOnTheFly) {
344 LLVMContext Context;
345 Module *M = makeLLVMModule(Context);
347 SCOPED_TRACE("Running OnTheFlyTest");
348 struct OnTheFlyTest *O = new OnTheFlyTest();
349 legacy::PassManager Passes;
350 Passes.add(O);
351 Passes.run(*M);
353 FPass::finishedOK(4);
355 delete M;
358 // Skips or runs optional passes.
359 struct CustomOptPassGate : public OptPassGate {
360 bool Skip;
361 CustomOptPassGate(bool Skip) : Skip(Skip) { }
362 bool shouldRunPass(const StringRef PassName, StringRef IRDescription) override {
363 return !Skip;
365 bool isEnabled() const override { return true; }
368 // Optional module pass.
369 struct ModuleOpt: public ModulePass {
370 char run = 0;
371 static char ID;
372 ModuleOpt() : ModulePass(ID) { }
373 bool runOnModule(Module &M) override {
374 if (!skipModule(M))
375 run++;
376 return false;
379 char ModuleOpt::ID=0;
381 TEST(PassManager, CustomOptPassGate) {
382 LLVMContext Context0;
383 LLVMContext Context1;
384 LLVMContext Context2;
385 CustomOptPassGate SkipOptionalPasses(true);
386 CustomOptPassGate RunOptionalPasses(false);
388 Module M0("custom-opt-bisect", Context0);
389 Module M1("custom-opt-bisect", Context1);
390 Module M2("custom-opt-bisect2", Context2);
391 struct ModuleOpt *mOpt0 = new ModuleOpt();
392 struct ModuleOpt *mOpt1 = new ModuleOpt();
393 struct ModuleOpt *mOpt2 = new ModuleOpt();
395 mOpt0->run = mOpt1->run = mOpt2->run = 0;
397 legacy::PassManager Passes0;
398 legacy::PassManager Passes1;
399 legacy::PassManager Passes2;
401 Passes0.add(mOpt0);
402 Passes1.add(mOpt1);
403 Passes2.add(mOpt2);
405 Context1.setOptPassGate(SkipOptionalPasses);
406 Context2.setOptPassGate(RunOptionalPasses);
408 Passes0.run(M0);
409 Passes1.run(M1);
410 Passes2.run(M2);
412 // By default optional passes are run.
413 EXPECT_EQ(1, mOpt0->run);
415 // The first context skips optional passes.
416 EXPECT_EQ(0, mOpt1->run);
418 // The second context runs optional passes.
419 EXPECT_EQ(1, mOpt2->run);
422 Module *makeLLVMModule(LLVMContext &Context) {
423 // Module Construction
424 Module *mod = new Module("test-mem", Context);
425 mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
426 "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
427 "a:0:64-s:64:64-f80:128:128");
428 mod->setTargetTriple("x86_64-unknown-linux-gnu");
430 // Type Definitions
431 std::vector<Type*>FuncTy_0_args;
432 FunctionType *FuncTy_0 = FunctionType::get(
433 /*Result=*/IntegerType::get(Context, 32),
434 /*Params=*/FuncTy_0_args,
435 /*isVarArg=*/false);
437 std::vector<Type*>FuncTy_2_args;
438 FuncTy_2_args.push_back(IntegerType::get(Context, 1));
439 FunctionType *FuncTy_2 = FunctionType::get(
440 /*Result=*/Type::getVoidTy(Context),
441 /*Params=*/FuncTy_2_args,
442 /*isVarArg=*/false);
444 // Function Declarations
446 Function* func_test1 = Function::Create(
447 /*Type=*/FuncTy_0,
448 /*Linkage=*/GlobalValue::ExternalLinkage,
449 /*Name=*/"test1", mod);
450 func_test1->setCallingConv(CallingConv::C);
451 AttributeList func_test1_PAL;
452 func_test1->setAttributes(func_test1_PAL);
454 Function* func_test2 = Function::Create(
455 /*Type=*/FuncTy_0,
456 /*Linkage=*/GlobalValue::ExternalLinkage,
457 /*Name=*/"test2", mod);
458 func_test2->setCallingConv(CallingConv::C);
459 AttributeList func_test2_PAL;
460 func_test2->setAttributes(func_test2_PAL);
462 Function* func_test3 = Function::Create(
463 /*Type=*/FuncTy_0,
464 /*Linkage=*/GlobalValue::InternalLinkage,
465 /*Name=*/"test3", mod);
466 func_test3->setCallingConv(CallingConv::C);
467 AttributeList func_test3_PAL;
468 func_test3->setAttributes(func_test3_PAL);
470 Function* func_test4 = Function::Create(
471 /*Type=*/FuncTy_2,
472 /*Linkage=*/GlobalValue::ExternalLinkage,
473 /*Name=*/"test4", mod);
474 func_test4->setCallingConv(CallingConv::C);
475 AttributeList func_test4_PAL;
476 func_test4->setAttributes(func_test4_PAL);
478 // Global Variable Declarations
481 // Constant Definitions
483 // Global Variable Definitions
485 // Function Definitions
487 // Function: test1 (func_test1)
490 BasicBlock *label_entry =
491 BasicBlock::Create(Context, "entry", func_test1, nullptr);
493 // Block entry (label_entry)
494 CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry);
495 int32_3->setCallingConv(CallingConv::C);
496 int32_3->setTailCall(false);
497 AttributeList int32_3_PAL;
498 int32_3->setAttributes(int32_3_PAL);
500 ReturnInst::Create(Context, int32_3, label_entry);
503 // Function: test2 (func_test2)
506 BasicBlock *label_entry_5 =
507 BasicBlock::Create(Context, "entry", func_test2, nullptr);
509 // Block entry (label_entry_5)
510 CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5);
511 int32_6->setCallingConv(CallingConv::C);
512 int32_6->setTailCall(false);
513 AttributeList int32_6_PAL;
514 int32_6->setAttributes(int32_6_PAL);
516 ReturnInst::Create(Context, int32_6, label_entry_5);
519 // Function: test3 (func_test3)
522 BasicBlock *label_entry_8 =
523 BasicBlock::Create(Context, "entry", func_test3, nullptr);
525 // Block entry (label_entry_8)
526 CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8);
527 int32_9->setCallingConv(CallingConv::C);
528 int32_9->setTailCall(false);
529 AttributeList int32_9_PAL;
530 int32_9->setAttributes(int32_9_PAL);
532 ReturnInst::Create(Context, int32_9, label_entry_8);
535 // Function: test4 (func_test4)
537 Function::arg_iterator args = func_test4->arg_begin();
538 Value *int1_f = &*args++;
539 int1_f->setName("f");
541 BasicBlock *label_entry_11 =
542 BasicBlock::Create(Context, "entry", func_test4, nullptr);
543 BasicBlock *label_bb =
544 BasicBlock::Create(Context, "bb", func_test4, nullptr);
545 BasicBlock *label_bb1 =
546 BasicBlock::Create(Context, "bb1", func_test4, nullptr);
547 BasicBlock *label_return =
548 BasicBlock::Create(Context, "return", func_test4, nullptr);
550 // Block entry (label_entry_11)
551 auto *AI = new AllocaInst(func_test3->getType(), 0, "func3ptr",
552 label_entry_11);
553 new StoreInst(func_test3, AI, label_entry_11);
554 BranchInst::Create(label_bb, label_entry_11);
556 // Block bb (label_bb)
557 BranchInst::Create(label_bb, label_bb1, int1_f, label_bb);
559 // Block bb1 (label_bb1)
560 BranchInst::Create(label_bb1, label_return, int1_f, label_bb1);
562 // Block return (label_return)
563 ReturnInst::Create(Context, label_return);
565 return mod;
568 // Test for call graph SCC pass that replaces all callback call instructions
569 // with clones and updates CallGraph by calling CallGraph::replaceCallEdge()
570 // method. Test is expected to complete successfully after running pass on
571 // all SCCs in the test module.
572 struct CallbackCallsModifierPass : public CGPass {
573 bool runOnSCC(CallGraphSCC &SCC) override {
574 CGPass::run();
576 CallGraph &CG = const_cast<CallGraph &>(SCC.getCallGraph());
578 bool Changed = false;
579 for (CallGraphNode *CGN : SCC) {
580 Function *F = CGN->getFunction();
581 if (!F || F->isDeclaration())
582 continue;
584 SmallVector<CallBase *, 4u> Calls;
585 for (Use &U : F->uses()) {
586 AbstractCallSite ACS(&U);
587 if (!ACS || !ACS.isCallbackCall() || !ACS.isCallee(&U))
588 continue;
589 Calls.push_back(cast<CallBase>(ACS.getInstruction()));
591 if (Calls.empty())
592 continue;
594 for (CallBase *OldCB : Calls) {
595 CallGraphNode *CallerCGN = CG[OldCB->getParent()->getParent()];
596 assert(any_of(*CallerCGN,
597 [CGN](const CallGraphNode::CallRecord &CallRecord) {
598 return CallRecord.second == CGN;
599 }) &&
600 "function is not a callee");
602 CallBase *NewCB = cast<CallBase>(OldCB->clone());
604 NewCB->insertBefore(OldCB);
605 NewCB->takeName(OldCB);
607 CallerCGN->replaceCallEdge(*OldCB, *NewCB, CG[F]);
609 OldCB->replaceAllUsesWith(NewCB);
610 OldCB->eraseFromParent();
612 Changed = true;
614 return Changed;
618 TEST(PassManager, CallbackCallsModifier0) {
619 LLVMContext Context;
621 const char *IR = "define void @foo() {\n"
622 " call void @broker(void (i8*)* @callback0, i8* null)\n"
623 " call void @broker(void (i8*)* @callback1, i8* null)\n"
624 " ret void\n"
625 "}\n"
626 "\n"
627 "declare !callback !0 void @broker(void (i8*)*, i8*)\n"
628 "\n"
629 "define internal void @callback0(i8* %arg) {\n"
630 " ret void\n"
631 "}\n"
632 "\n"
633 "define internal void @callback1(i8* %arg) {\n"
634 " ret void\n"
635 "}\n"
636 "\n"
637 "!0 = !{!1}\n"
638 "!1 = !{i64 0, i64 1, i1 false}";
640 SMDiagnostic Err;
641 std::unique_ptr<Module> M = parseAssemblyString(IR, Err, Context);
642 if (!M)
643 Err.print("LegacyPassManagerTest", errs());
645 CallbackCallsModifierPass *P = new CallbackCallsModifierPass();
646 legacy::PassManager Passes;
647 Passes.add(P);
648 Passes.run(*M);
653 INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false)
654 INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false)
655 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
656 INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false)
657 INITIALIZE_PASS(FPass, "fp","fp", false, false)
658 INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false)
659 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
660 INITIALIZE_PASS_END(LPass, "lp","lp", false, false)