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/AsmParser/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 TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> { 23 public: 24 struct Result { 25 Result(int Count) : InstructionCount(Count) {} 26 int InstructionCount; 27 }; 28 29 TestFunctionAnalysis(int &Runs) : Runs(Runs) {} 30 31 /// \brief Run the analysis pass over the function and return a result. 32 Result run(Function &F, FunctionAnalysisManager &AM) { 33 ++Runs; 34 int Count = 0; 35 for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) 36 for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; 37 ++II) 38 ++Count; 39 return Result(Count); 40 } 41 42 private: 43 friend AnalysisInfoMixin<TestFunctionAnalysis>; 44 static char PassID; 45 46 int &Runs; 47 }; 48 49 char TestFunctionAnalysis::PassID; 50 51 class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> { 52 public: 53 struct Result { 54 Result(int Count) : FunctionCount(Count) {} 55 int FunctionCount; 56 }; 57 58 TestModuleAnalysis(int &Runs) : Runs(Runs) {} 59 60 Result run(Module &M, ModuleAnalysisManager &AM) { 61 ++Runs; 62 int Count = 0; 63 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) 64 ++Count; 65 return Result(Count); 66 } 67 68 private: 69 friend AnalysisInfoMixin<TestModuleAnalysis>; 70 static char PassID; 71 72 int &Runs; 73 }; 74 75 char TestModuleAnalysis::PassID; 76 77 struct TestModulePass : PassInfoMixin<TestModulePass> { 78 TestModulePass(int &RunCount) : RunCount(RunCount) {} 79 80 PreservedAnalyses run(Module &M) { 81 ++RunCount; 82 return PreservedAnalyses::none(); 83 } 84 85 int &RunCount; 86 }; 87 88 struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> { 89 PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); } 90 }; 91 92 struct TestMinPreservingModulePass 93 : PassInfoMixin<TestMinPreservingModulePass> { 94 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { 95 PreservedAnalyses PA; 96 97 // Force running an analysis. 98 (void)AM.getResult<TestModuleAnalysis>(M); 99 100 PA.preserve<FunctionAnalysisManagerModuleProxy>(); 101 return PA; 102 } 103 }; 104 105 struct TestFunctionPass : PassInfoMixin<TestFunctionPass> { 106 TestFunctionPass(int &RunCount, int &AnalyzedInstrCount, 107 int &AnalyzedFunctionCount, 108 bool OnlyUseCachedResults = false) 109 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount), 110 AnalyzedFunctionCount(AnalyzedFunctionCount), 111 OnlyUseCachedResults(OnlyUseCachedResults) {} 112 113 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { 114 ++RunCount; 115 116 const ModuleAnalysisManager &MAM = 117 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); 118 if (TestModuleAnalysis::Result *TMA = 119 MAM.getCachedResult<TestModuleAnalysis>(*F.getParent())) 120 AnalyzedFunctionCount += TMA->FunctionCount; 121 122 if (OnlyUseCachedResults) { 123 // Hack to force the use of the cached interface. 124 if (TestFunctionAnalysis::Result *AR = 125 AM.getCachedResult<TestFunctionAnalysis>(F)) 126 AnalyzedInstrCount += AR->InstructionCount; 127 } else { 128 // Typical path just runs the analysis as needed. 129 TestFunctionAnalysis::Result &AR = AM.getResult<TestFunctionAnalysis>(F); 130 AnalyzedInstrCount += AR.InstructionCount; 131 } 132 133 return PreservedAnalyses::all(); 134 } 135 136 int &RunCount; 137 int &AnalyzedInstrCount; 138 int &AnalyzedFunctionCount; 139 bool OnlyUseCachedResults; 140 }; 141 142 // A test function pass that invalidates all function analyses for a function 143 // with a specific name. 144 struct TestInvalidationFunctionPass 145 : PassInfoMixin<TestInvalidationFunctionPass> { 146 TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {} 147 148 PreservedAnalyses run(Function &F) { 149 return F.getName() == Name ? PreservedAnalyses::none() 150 : PreservedAnalyses::all(); 151 } 152 153 StringRef Name; 154 }; 155 156 std::unique_ptr<Module> parseIR(const char *IR) { 157 LLVMContext &C = getGlobalContext(); 158 SMDiagnostic Err; 159 return parseAssemblyString(IR, Err, C); 160 } 161 162 class PassManagerTest : public ::testing::Test { 163 protected: 164 std::unique_ptr<Module> M; 165 166 public: 167 PassManagerTest() 168 : M(parseIR("define void @f() {\n" 169 "entry:\n" 170 " call void @g()\n" 171 " call void @h()\n" 172 " ret void\n" 173 "}\n" 174 "define void @g() {\n" 175 " ret void\n" 176 "}\n" 177 "define void @h() {\n" 178 " ret void\n" 179 "}\n")) {} 180 }; 181 182 TEST_F(PassManagerTest, BasicPreservedAnalyses) { 183 PreservedAnalyses PA1 = PreservedAnalyses(); 184 EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>()); 185 EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>()); 186 PreservedAnalyses PA2 = PreservedAnalyses::none(); 187 EXPECT_FALSE(PA2.preserved<TestFunctionAnalysis>()); 188 EXPECT_FALSE(PA2.preserved<TestModuleAnalysis>()); 189 PreservedAnalyses PA3 = PreservedAnalyses::all(); 190 EXPECT_TRUE(PA3.preserved<TestFunctionAnalysis>()); 191 EXPECT_TRUE(PA3.preserved<TestModuleAnalysis>()); 192 PreservedAnalyses PA4 = PA1; 193 EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>()); 194 EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); 195 PA4 = PA3; 196 EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>()); 197 EXPECT_TRUE(PA4.preserved<TestModuleAnalysis>()); 198 PA4 = std::move(PA2); 199 EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>()); 200 EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); 201 PA4.preserve<TestFunctionAnalysis>(); 202 EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>()); 203 EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); 204 PA1.preserve<TestModuleAnalysis>(); 205 EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>()); 206 EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>()); 207 PA1.preserve<TestFunctionAnalysis>(); 208 EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>()); 209 EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>()); 210 PA1.intersect(PA4); 211 EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>()); 212 EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>()); 213 } 214 215 TEST_F(PassManagerTest, Basic) { 216 FunctionAnalysisManager FAM; 217 int FunctionAnalysisRuns = 0; 218 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 219 220 ModuleAnalysisManager MAM; 221 int ModuleAnalysisRuns = 0; 222 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 223 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); 224 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); 225 226 ModulePassManager MPM; 227 228 // Count the runs over a Function. 229 int FunctionPassRunCount1 = 0; 230 int AnalyzedInstrCount1 = 0; 231 int AnalyzedFunctionCount1 = 0; 232 { 233 // Pointless scoped copy to test move assignment. 234 ModulePassManager NestedMPM; 235 FunctionPassManager FPM; 236 { 237 // Pointless scope to test move assignment. 238 FunctionPassManager NestedFPM; 239 NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1, AnalyzedInstrCount1, 240 AnalyzedFunctionCount1)); 241 FPM = std::move(NestedFPM); 242 } 243 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 244 MPM = std::move(NestedMPM); 245 } 246 247 // Count the runs over a module. 248 int ModulePassRunCount = 0; 249 MPM.addPass(TestModulePass(ModulePassRunCount)); 250 251 // Count the runs over a Function in a separate manager. 252 int FunctionPassRunCount2 = 0; 253 int AnalyzedInstrCount2 = 0; 254 int AnalyzedFunctionCount2 = 0; 255 { 256 FunctionPassManager FPM; 257 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2, 258 AnalyzedFunctionCount2)); 259 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 260 } 261 262 // A third function pass manager but with only preserving intervening passes 263 // and with a function pass that invalidates exactly one analysis. 264 MPM.addPass(TestPreservingModulePass()); 265 int FunctionPassRunCount3 = 0; 266 int AnalyzedInstrCount3 = 0; 267 int AnalyzedFunctionCount3 = 0; 268 { 269 FunctionPassManager FPM; 270 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3, 271 AnalyzedFunctionCount3)); 272 FPM.addPass(TestInvalidationFunctionPass("f")); 273 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 274 } 275 276 // A fourth function pass manager but with a minimal intervening passes. 277 MPM.addPass(TestMinPreservingModulePass()); 278 int FunctionPassRunCount4 = 0; 279 int AnalyzedInstrCount4 = 0; 280 int AnalyzedFunctionCount4 = 0; 281 { 282 FunctionPassManager FPM; 283 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4, 284 AnalyzedFunctionCount4)); 285 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 286 } 287 288 // A fifth function pass manager but which uses only cached results. 289 int FunctionPassRunCount5 = 0; 290 int AnalyzedInstrCount5 = 0; 291 int AnalyzedFunctionCount5 = 0; 292 { 293 FunctionPassManager FPM; 294 FPM.addPass(TestInvalidationFunctionPass("f")); 295 FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5, 296 AnalyzedFunctionCount5, 297 /*OnlyUseCachedResults=*/true)); 298 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 299 } 300 301 MPM.run(*M, MAM); 302 303 // Validate module pass counters. 304 EXPECT_EQ(1, ModulePassRunCount); 305 306 // Validate all function pass counter sets are the same. 307 EXPECT_EQ(3, FunctionPassRunCount1); 308 EXPECT_EQ(5, AnalyzedInstrCount1); 309 EXPECT_EQ(0, AnalyzedFunctionCount1); 310 EXPECT_EQ(3, FunctionPassRunCount2); 311 EXPECT_EQ(5, AnalyzedInstrCount2); 312 EXPECT_EQ(0, AnalyzedFunctionCount2); 313 EXPECT_EQ(3, FunctionPassRunCount3); 314 EXPECT_EQ(5, AnalyzedInstrCount3); 315 EXPECT_EQ(0, AnalyzedFunctionCount3); 316 EXPECT_EQ(3, FunctionPassRunCount4); 317 EXPECT_EQ(5, AnalyzedInstrCount4); 318 EXPECT_EQ(0, AnalyzedFunctionCount4); 319 EXPECT_EQ(3, FunctionPassRunCount5); 320 EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached. 321 EXPECT_EQ(0, AnalyzedFunctionCount5); 322 323 // Validate the analysis counters: 324 // first run over 3 functions, then module pass invalidates 325 // second run over 3 functions, nothing invalidates 326 // third run over 0 functions, but 1 function invalidated 327 // fourth run over 1 function 328 EXPECT_EQ(7, FunctionAnalysisRuns); 329 330 EXPECT_EQ(1, ModuleAnalysisRuns); 331 } 332 } 333