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