1 //===- llvm/unittest/IR/PassManager.cpp - PassManager 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/Assembly/Parser.h" 11 #include "llvm/IR/Function.h" 12 #include "llvm/IR/LLVMContext.h" 13 #include "llvm/IR/Module.h" 14 #include "llvm/IR/PassManager.h" 15 #include "llvm/Support/SourceMgr.h" 16 #include "gtest/gtest.h" 17 18 using namespace llvm; 19 20 namespace { 21 22 class TestAnalysisPass { 23 public: 24 typedef Function IRUnitT; 25 26 struct Result { 27 Result(int Count) : InstructionCount(Count) {} 28 bool invalidate(Function *) { return true; } 29 int InstructionCount; 30 }; 31 32 /// \brief Returns an opaque, unique ID for this pass type. 33 static void *ID() { return (void *)&PassID; } 34 35 /// \brief Run the analysis pass over the function and return a result. 36 Result run(Function *F) { 37 int Count = 0; 38 for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI) 39 for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; 40 ++II) 41 ++Count; 42 return Result(Count); 43 } 44 45 private: 46 /// \brief Private static data to provide unique ID. 47 static char PassID; 48 }; 49 50 char TestAnalysisPass::PassID; 51 52 struct TestModulePass { 53 TestModulePass(int &RunCount) : RunCount(RunCount) {} 54 55 bool run(Module *M) { 56 ++RunCount; 57 return true; 58 } 59 60 int &RunCount; 61 }; 62 63 struct TestFunctionPass { 64 TestFunctionPass(AnalysisManager &AM, int &RunCount, int &AnalyzedInstrCount) 65 : AM(AM), RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount) { 66 } 67 68 bool run(Function *F) { 69 ++RunCount; 70 71 const TestAnalysisPass::Result &AR = AM.getResult<TestAnalysisPass>(F); 72 AnalyzedInstrCount += AR.InstructionCount; 73 74 return true; 75 } 76 77 AnalysisManager &AM; 78 int &RunCount; 79 int &AnalyzedInstrCount; 80 }; 81 82 Module *parseIR(const char *IR) { 83 LLVMContext &C = getGlobalContext(); 84 SMDiagnostic Err; 85 return ParseAssemblyString(IR, 0, Err, C); 86 } 87 88 class PassManagerTest : public ::testing::Test { 89 protected: 90 OwningPtr<Module> M; 91 92 public: 93 PassManagerTest() 94 : M(parseIR("define void @f() {\n" 95 "entry:\n" 96 " call void @g()\n" 97 " call void @h()\n" 98 " ret void\n" 99 "}\n" 100 "define void @g() {\n" 101 " ret void\n" 102 "}\n" 103 "define void @h() {\n" 104 " ret void\n" 105 "}\n")) {} 106 }; 107 108 TEST_F(PassManagerTest, Basic) { 109 AnalysisManager AM(M.get()); 110 AM.registerAnalysisPass(TestAnalysisPass()); 111 112 ModulePassManager MPM(M.get(), &AM); 113 FunctionPassManager FPM(&AM); 114 115 // Count the runs over a module. 116 int ModulePassRunCount = 0; 117 MPM.addPass(TestModulePass(ModulePassRunCount)); 118 119 // Count the runs over a Function. 120 int FunctionPassRunCount = 0; 121 int AnalyzedInstrCount = 0; 122 FPM.addPass(TestFunctionPass(AM, FunctionPassRunCount, AnalyzedInstrCount)); 123 MPM.addPass(FPM); 124 125 MPM.run(); 126 EXPECT_EQ(1, ModulePassRunCount); 127 EXPECT_EQ(3, FunctionPassRunCount); 128 EXPECT_EQ(5, AnalyzedInstrCount); 129 } 130 131 } 132