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/IR/PassManager.h" 11 #include "llvm/AsmParser/Parser.h" 12 #include "llvm/IR/Function.h" 13 #include "llvm/IR/LLVMContext.h" 14 #include "llvm/IR/Module.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 /// 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 AnalysisKey Key; 45 46 int &Runs; 47 }; 48 49 AnalysisKey TestFunctionAnalysis::Key; 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 AnalysisKey Key; 71 72 int &Runs; 73 }; 74 75 AnalysisKey TestModuleAnalysis::Key; 76 77 struct 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 88 struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> { 89 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) { 90 return PreservedAnalyses::all(); 91 } 92 }; 93 94 struct TestFunctionPass : PassInfoMixin<TestFunctionPass> { 95 TestFunctionPass(int &RunCount, int &AnalyzedInstrCount, 96 int &AnalyzedFunctionCount, 97 bool OnlyUseCachedResults = false) 98 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount), 99 AnalyzedFunctionCount(AnalyzedFunctionCount), 100 OnlyUseCachedResults(OnlyUseCachedResults) {} 101 102 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { 103 ++RunCount; 104 105 const ModuleAnalysisManager &MAM = 106 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); 107 if (TestModuleAnalysis::Result *TMA = 108 MAM.getCachedResult<TestModuleAnalysis>(*F.getParent())) 109 AnalyzedFunctionCount += TMA->FunctionCount; 110 111 if (OnlyUseCachedResults) { 112 // Hack to force the use of the cached interface. 113 if (TestFunctionAnalysis::Result *AR = 114 AM.getCachedResult<TestFunctionAnalysis>(F)) 115 AnalyzedInstrCount += AR->InstructionCount; 116 } else { 117 // Typical path just runs the analysis as needed. 118 TestFunctionAnalysis::Result &AR = AM.getResult<TestFunctionAnalysis>(F); 119 AnalyzedInstrCount += AR.InstructionCount; 120 } 121 122 return PreservedAnalyses::all(); 123 } 124 125 int &RunCount; 126 int &AnalyzedInstrCount; 127 int &AnalyzedFunctionCount; 128 bool OnlyUseCachedResults; 129 }; 130 131 // A test function pass that invalidates all function analyses for a function 132 // with a specific name. 133 struct TestInvalidationFunctionPass 134 : PassInfoMixin<TestInvalidationFunctionPass> { 135 TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {} 136 137 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { 138 return F.getName() == Name ? PreservedAnalyses::none() 139 : PreservedAnalyses::all(); 140 } 141 142 StringRef Name; 143 }; 144 145 std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) { 146 SMDiagnostic Err; 147 return parseAssemblyString(IR, Err, Context); 148 } 149 150 class PassManagerTest : public ::testing::Test { 151 protected: 152 LLVMContext Context; 153 std::unique_ptr<Module> M; 154 155 public: 156 PassManagerTest() 157 : M(parseIR(Context, "define void @f() {\n" 158 "entry:\n" 159 " call void @g()\n" 160 " call void @h()\n" 161 " ret void\n" 162 "}\n" 163 "define void @g() {\n" 164 " ret void\n" 165 "}\n" 166 "define void @h() {\n" 167 " ret void\n" 168 "}\n")) {} 169 }; 170 171 TEST(PreservedAnalysesTest, Basic) { 172 PreservedAnalyses PA1 = PreservedAnalyses(); 173 { 174 auto PAC = PA1.getChecker<TestFunctionAnalysis>(); 175 EXPECT_FALSE(PAC.preserved()); 176 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>()); 177 } 178 { 179 auto PAC = PA1.getChecker<TestModuleAnalysis>(); 180 EXPECT_FALSE(PAC.preserved()); 181 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Module>>()); 182 } 183 auto PA2 = PreservedAnalyses::none(); 184 { 185 auto PAC = PA2.getChecker<TestFunctionAnalysis>(); 186 EXPECT_FALSE(PAC.preserved()); 187 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>()); 188 } 189 auto PA3 = PreservedAnalyses::all(); 190 { 191 auto PAC = PA3.getChecker<TestFunctionAnalysis>(); 192 EXPECT_TRUE(PAC.preserved()); 193 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>()); 194 } 195 PreservedAnalyses PA4 = PA1; 196 { 197 auto PAC = PA4.getChecker<TestFunctionAnalysis>(); 198 EXPECT_FALSE(PAC.preserved()); 199 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>()); 200 } 201 PA4 = PA3; 202 { 203 auto PAC = PA4.getChecker<TestFunctionAnalysis>(); 204 EXPECT_TRUE(PAC.preserved()); 205 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>()); 206 } 207 PA4 = std::move(PA2); 208 { 209 auto PAC = PA4.getChecker<TestFunctionAnalysis>(); 210 EXPECT_FALSE(PAC.preserved()); 211 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>()); 212 } 213 auto PA5 = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>(); 214 { 215 auto PAC = PA5.getChecker<TestFunctionAnalysis>(); 216 EXPECT_FALSE(PAC.preserved()); 217 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>()); 218 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Module>>()); 219 } 220 } 221 222 TEST(PreservedAnalysesTest, Preserve) { 223 auto PA = PreservedAnalyses::none(); 224 PA.preserve<TestFunctionAnalysis>(); 225 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved()); 226 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>().preserved()); 227 PA.preserve<TestModuleAnalysis>(); 228 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved()); 229 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved()); 230 231 // Redundant calls are fine. 232 PA.preserve<TestFunctionAnalysis>(); 233 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved()); 234 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved()); 235 } 236 237 TEST(PreservedAnalysesTest, PreserveSets) { 238 auto PA = PreservedAnalyses::none(); 239 PA.preserveSet<AllAnalysesOn<Function>>(); 240 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>() 241 .preservedSet<AllAnalysesOn<Function>>()); 242 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>() 243 .preservedSet<AllAnalysesOn<Module>>()); 244 PA.preserveSet<AllAnalysesOn<Module>>(); 245 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>() 246 .preservedSet<AllAnalysesOn<Function>>()); 247 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>() 248 .preservedSet<AllAnalysesOn<Module>>()); 249 250 // Mixing is fine. 251 PA.preserve<TestFunctionAnalysis>(); 252 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>() 253 .preservedSet<AllAnalysesOn<Function>>()); 254 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>() 255 .preservedSet<AllAnalysesOn<Module>>()); 256 257 // Redundant calls are fine. 258 PA.preserveSet<AllAnalysesOn<Module>>(); 259 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>() 260 .preservedSet<AllAnalysesOn<Function>>()); 261 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>() 262 .preservedSet<AllAnalysesOn<Module>>()); 263 } 264 265 TEST(PreservedAnalysisTest, Intersect) { 266 // Setup the initial sets. 267 auto PA1 = PreservedAnalyses::none(); 268 PA1.preserve<TestFunctionAnalysis>(); 269 PA1.preserveSet<AllAnalysesOn<Module>>(); 270 auto PA2 = PreservedAnalyses::none(); 271 PA2.preserve<TestFunctionAnalysis>(); 272 PA2.preserveSet<AllAnalysesOn<Function>>(); 273 PA2.preserve<TestModuleAnalysis>(); 274 PA2.preserveSet<AllAnalysesOn<Module>>(); 275 auto PA3 = PreservedAnalyses::none(); 276 PA3.preserve<TestModuleAnalysis>(); 277 PA3.preserveSet<AllAnalysesOn<Function>>(); 278 279 // Self intersection is a no-op. 280 auto Intersected = PA1; 281 Intersected.intersect(PA1); 282 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 283 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 284 .preservedSet<AllAnalysesOn<Function>>()); 285 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 286 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 287 .preservedSet<AllAnalysesOn<Module>>()); 288 289 // Intersecting with all is a no-op. 290 Intersected.intersect(PreservedAnalyses::all()); 291 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 292 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 293 .preservedSet<AllAnalysesOn<Function>>()); 294 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 295 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 296 .preservedSet<AllAnalysesOn<Module>>()); 297 298 // Intersecting a narrow set with a more broad set is the narrow set. 299 Intersected.intersect(PA2); 300 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 301 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 302 .preservedSet<AllAnalysesOn<Function>>()); 303 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 304 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 305 .preservedSet<AllAnalysesOn<Module>>()); 306 307 // Intersecting a broad set with a more narrow set is the narrow set. 308 Intersected = PA2; 309 Intersected.intersect(PA1); 310 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 311 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 312 .preservedSet<AllAnalysesOn<Function>>()); 313 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 314 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 315 .preservedSet<AllAnalysesOn<Module>>()); 316 317 // Intersecting with empty clears. 318 Intersected.intersect(PreservedAnalyses::none()); 319 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 320 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 321 .preservedSet<AllAnalysesOn<Function>>()); 322 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 323 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>() 324 .preservedSet<AllAnalysesOn<Module>>()); 325 326 // Intersecting non-overlapping clears. 327 Intersected = PA1; 328 Intersected.intersect(PA3); 329 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 330 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 331 .preservedSet<AllAnalysesOn<Function>>()); 332 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 333 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>() 334 .preservedSet<AllAnalysesOn<Module>>()); 335 336 // Intersecting with moves works in when there is storage on both sides. 337 Intersected = PA1; 338 auto Tmp = PA2; 339 Intersected.intersect(std::move(Tmp)); 340 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 341 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 342 .preservedSet<AllAnalysesOn<Function>>()); 343 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 344 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 345 .preservedSet<AllAnalysesOn<Module>>()); 346 347 // Intersecting with move works for incoming all and existing all. 348 auto Tmp2 = PreservedAnalyses::all(); 349 Intersected.intersect(std::move(Tmp2)); 350 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 351 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 352 .preservedSet<AllAnalysesOn<Function>>()); 353 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 354 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 355 .preservedSet<AllAnalysesOn<Module>>()); 356 Intersected = PreservedAnalyses::all(); 357 auto Tmp3 = PA1; 358 Intersected.intersect(std::move(Tmp3)); 359 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 360 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 361 .preservedSet<AllAnalysesOn<Function>>()); 362 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 363 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 364 .preservedSet<AllAnalysesOn<Module>>()); 365 } 366 367 TEST(PreservedAnalysisTest, Abandon) { 368 auto PA = PreservedAnalyses::none(); 369 370 // We can abandon things after they are preserved. 371 PA.preserve<TestFunctionAnalysis>(); 372 PA.abandon<TestFunctionAnalysis>(); 373 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved()); 374 375 // Repeated is fine, and abandoning if they were never preserved is fine. 376 PA.abandon<TestFunctionAnalysis>(); 377 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved()); 378 PA.abandon<TestModuleAnalysis>(); 379 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>().preserved()); 380 381 // Even if the sets are preserved, the abandoned analyses' checker won't 382 // return true for those sets. 383 PA.preserveSet<AllAnalysesOn<Function>>(); 384 PA.preserveSet<AllAnalysesOn<Module>>(); 385 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>() 386 .preservedSet<AllAnalysesOn<Function>>()); 387 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>() 388 .preservedSet<AllAnalysesOn<Module>>()); 389 390 // But an arbitrary (opaque) analysis will still observe the sets as 391 // preserved. This also checks that we can use an explicit ID rather than 392 // a type. 393 AnalysisKey FakeKey, *FakeID = &FakeKey; 394 EXPECT_TRUE(PA.getChecker(FakeID).preservedSet<AllAnalysesOn<Function>>()); 395 EXPECT_TRUE(PA.getChecker(FakeID).preservedSet<AllAnalysesOn<Module>>()); 396 } 397 398 TEST_F(PassManagerTest, Basic) { 399 FunctionAnalysisManager FAM(/*DebugLogging*/ true); 400 int FunctionAnalysisRuns = 0; 401 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 402 403 ModuleAnalysisManager MAM(/*DebugLogging*/ true); 404 int ModuleAnalysisRuns = 0; 405 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 406 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); 407 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); 408 409 ModulePassManager MPM; 410 411 // Count the runs over a Function. 412 int FunctionPassRunCount1 = 0; 413 int AnalyzedInstrCount1 = 0; 414 int AnalyzedFunctionCount1 = 0; 415 { 416 // Pointless scoped copy to test move assignment. 417 ModulePassManager NestedMPM(/*DebugLogging*/ true); 418 FunctionPassManager FPM; 419 { 420 // Pointless scope to test move assignment. 421 FunctionPassManager NestedFPM(/*DebugLogging*/ true); 422 NestedFPM.addPass(TestFunctionPass( 423 FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1)); 424 FPM = std::move(NestedFPM); 425 } 426 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 427 MPM = std::move(NestedMPM); 428 } 429 430 // Count the runs over a module. 431 int ModulePassRunCount = 0; 432 MPM.addPass(TestModulePass(ModulePassRunCount)); 433 434 // Count the runs over a Function in a separate manager. 435 int FunctionPassRunCount2 = 0; 436 int AnalyzedInstrCount2 = 0; 437 int AnalyzedFunctionCount2 = 0; 438 { 439 FunctionPassManager FPM(/*DebugLogging*/ true); 440 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2, 441 AnalyzedFunctionCount2)); 442 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 443 } 444 445 // A third function pass manager but with only preserving intervening passes 446 // and with a function pass that invalidates exactly one analysis. 447 MPM.addPass(TestPreservingModulePass()); 448 int FunctionPassRunCount3 = 0; 449 int AnalyzedInstrCount3 = 0; 450 int AnalyzedFunctionCount3 = 0; 451 { 452 FunctionPassManager FPM(/*DebugLogging*/ true); 453 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3, 454 AnalyzedFunctionCount3)); 455 FPM.addPass(TestInvalidationFunctionPass("f")); 456 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 457 } 458 459 // A fourth function pass manager but with only preserving intervening 460 // passes but triggering the module analysis. 461 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 462 int FunctionPassRunCount4 = 0; 463 int AnalyzedInstrCount4 = 0; 464 int AnalyzedFunctionCount4 = 0; 465 { 466 FunctionPassManager FPM; 467 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4, 468 AnalyzedFunctionCount4)); 469 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 470 } 471 472 // A fifth function pass manager which invalidates one function first but 473 // uses only cached results. 474 int FunctionPassRunCount5 = 0; 475 int AnalyzedInstrCount5 = 0; 476 int AnalyzedFunctionCount5 = 0; 477 { 478 FunctionPassManager FPM(/*DebugLogging*/ true); 479 FPM.addPass(TestInvalidationFunctionPass("f")); 480 FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5, 481 AnalyzedFunctionCount5, 482 /*OnlyUseCachedResults=*/true)); 483 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 484 } 485 486 MPM.run(*M, MAM); 487 488 // Validate module pass counters. 489 EXPECT_EQ(1, ModulePassRunCount); 490 491 // Validate all function pass counter sets are the same. 492 EXPECT_EQ(3, FunctionPassRunCount1); 493 EXPECT_EQ(5, AnalyzedInstrCount1); 494 EXPECT_EQ(0, AnalyzedFunctionCount1); 495 EXPECT_EQ(3, FunctionPassRunCount2); 496 EXPECT_EQ(5, AnalyzedInstrCount2); 497 EXPECT_EQ(0, AnalyzedFunctionCount2); 498 EXPECT_EQ(3, FunctionPassRunCount3); 499 EXPECT_EQ(5, AnalyzedInstrCount3); 500 EXPECT_EQ(0, AnalyzedFunctionCount3); 501 EXPECT_EQ(3, FunctionPassRunCount4); 502 EXPECT_EQ(5, AnalyzedInstrCount4); 503 EXPECT_EQ(9, AnalyzedFunctionCount4); 504 EXPECT_EQ(3, FunctionPassRunCount5); 505 EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached. 506 EXPECT_EQ(9, AnalyzedFunctionCount5); 507 508 // Validate the analysis counters: 509 // first run over 3 functions, then module pass invalidates 510 // second run over 3 functions, nothing invalidates 511 // third run over 0 functions, but 1 function invalidated 512 // fourth run over 1 function 513 // fifth run invalidates 1 function first, but runs over 0 functions 514 EXPECT_EQ(7, FunctionAnalysisRuns); 515 516 EXPECT_EQ(1, ModuleAnalysisRuns); 517 } 518 519 // A customized pass manager that passes extra arguments through the 520 // infrastructure. 521 typedef AnalysisManager<Function, int> CustomizedAnalysisManager; 522 typedef PassManager<Function, CustomizedAnalysisManager, int, int &> 523 CustomizedPassManager; 524 525 class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> { 526 public: 527 struct Result { 528 Result(int I) : I(I) {} 529 int I; 530 }; 531 532 Result run(Function &F, CustomizedAnalysisManager &AM, int I) { 533 return Result(I); 534 } 535 536 private: 537 friend AnalysisInfoMixin<CustomizedAnalysis>; 538 static AnalysisKey Key; 539 }; 540 541 AnalysisKey CustomizedAnalysis::Key; 542 543 struct CustomizedPass : PassInfoMixin<CustomizedPass> { 544 std::function<void(CustomizedAnalysis::Result &, int &)> Callback; 545 546 template <typename CallbackT> 547 CustomizedPass(CallbackT Callback) : Callback(Callback) {} 548 549 PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I, 550 int &O) { 551 Callback(AM.getResult<CustomizedAnalysis>(F, I), O); 552 return PreservedAnalyses::none(); 553 } 554 }; 555 556 TEST_F(PassManagerTest, CustomizedPassManagerArgs) { 557 CustomizedAnalysisManager AM; 558 AM.registerPass([&] { return CustomizedAnalysis(); }); 559 560 CustomizedPassManager PM; 561 562 // Add an instance of the customized pass that just accumulates the input 563 // after it is round-tripped through the analysis. 564 int Result = 0; 565 PM.addPass( 566 CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; })); 567 568 // Run this over every function with the input of 42. 569 for (Function &F : *M) 570 PM.run(F, AM, 42, Result); 571 572 // And ensure that we accumulated the correct result. 573 EXPECT_EQ(42 * (int)M->size(), Result); 574 } 575 576 /// A test analysis pass which caches in its result another analysis pass and 577 /// uses it to serve queries. This requires the result to invalidate itself 578 /// when its dependency is invalidated. 579 struct TestIndirectFunctionAnalysis 580 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> { 581 struct Result { 582 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep) 583 : FDep(FDep), MDep(MDep) {} 584 TestFunctionAnalysis::Result &FDep; 585 TestModuleAnalysis::Result &MDep; 586 587 bool invalidate(Function &F, const PreservedAnalyses &PA, 588 FunctionAnalysisManager::Invalidator &Inv) { 589 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>(); 590 return !(PAC.preserved() || 591 PAC.preservedSet<AllAnalysesOn<Function>>()) || 592 Inv.invalidate<TestFunctionAnalysis>(F, PA); 593 } 594 }; 595 596 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {} 597 598 /// Run the analysis pass over the function and return a result. 599 Result run(Function &F, FunctionAnalysisManager &AM) { 600 ++Runs; 601 auto &FDep = AM.getResult<TestFunctionAnalysis>(F); 602 auto &Proxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F); 603 const ModuleAnalysisManager &MAM = Proxy.getManager(); 604 // For the test, we insist that the module analysis starts off in the 605 // cache. 606 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 607 // And register the dependency as module analysis dependencies have to be 608 // pre-registered on the proxy. 609 Proxy.registerOuterAnalysisInvalidation<TestModuleAnalysis, 610 TestIndirectFunctionAnalysis>(); 611 return Result(FDep, MDep); 612 } 613 614 private: 615 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>; 616 static AnalysisKey Key; 617 618 int &Runs; 619 }; 620 621 AnalysisKey TestIndirectFunctionAnalysis::Key; 622 623 /// A test analysis pass which chaches in its result the result from the above 624 /// indirect analysis pass. 625 /// 626 /// This allows us to ensure that whenever an analysis pass is invalidated due 627 /// to dependencies (especially dependencies across IR units that trigger 628 /// asynchronous invalidation) we correctly detect that this may in turn cause 629 /// other analysis to be invalidated. 630 struct TestDoublyIndirectFunctionAnalysis 631 : public AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis> { 632 struct Result { 633 Result(TestIndirectFunctionAnalysis::Result &IDep) : IDep(IDep) {} 634 TestIndirectFunctionAnalysis::Result &IDep; 635 636 bool invalidate(Function &F, const PreservedAnalyses &PA, 637 FunctionAnalysisManager::Invalidator &Inv) { 638 auto PAC = PA.getChecker<TestDoublyIndirectFunctionAnalysis>(); 639 return !(PAC.preserved() || 640 PAC.preservedSet<AllAnalysesOn<Function>>()) || 641 Inv.invalidate<TestIndirectFunctionAnalysis>(F, PA); 642 } 643 }; 644 645 TestDoublyIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {} 646 647 /// Run the analysis pass over the function and return a result. 648 Result run(Function &F, FunctionAnalysisManager &AM) { 649 ++Runs; 650 auto &IDep = AM.getResult<TestIndirectFunctionAnalysis>(F); 651 return Result(IDep); 652 } 653 654 private: 655 friend AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis>; 656 static AnalysisKey Key; 657 658 int &Runs; 659 }; 660 661 AnalysisKey TestDoublyIndirectFunctionAnalysis::Key; 662 663 struct LambdaPass : public PassInfoMixin<LambdaPass> { 664 using FuncT = std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)>; 665 666 LambdaPass(FuncT Func) : Func(std::move(Func)) {} 667 668 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { 669 return Func(F, AM); 670 } 671 672 FuncT Func; 673 }; 674 675 TEST_F(PassManagerTest, IndirectAnalysisInvalidation) { 676 FunctionAnalysisManager FAM(/*DebugLogging*/ true); 677 int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0, 678 IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0; 679 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 680 FAM.registerPass( 681 [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns); }); 682 FAM.registerPass([&] { 683 return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns); 684 }); 685 686 ModuleAnalysisManager MAM(/*DebugLogging*/ true); 687 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 688 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); 689 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); 690 691 int InstrCount = 0, FunctionCount = 0; 692 ModulePassManager MPM(/*DebugLogging*/ true); 693 FunctionPassManager FPM(/*DebugLogging*/ true); 694 // First just use the analysis to get the instruction count, and preserve 695 // everything. 696 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 697 auto &DoublyIndirectResult = 698 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 699 auto &IndirectResult = DoublyIndirectResult.IDep; 700 InstrCount += IndirectResult.FDep.InstructionCount; 701 FunctionCount += IndirectResult.MDep.FunctionCount; 702 return PreservedAnalyses::all(); 703 })); 704 // Next, invalidate 705 // - both analyses for "f", 706 // - just the underlying (indirect) analysis for "g", and 707 // - just the direct analysis for "h". 708 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 709 auto &DoublyIndirectResult = 710 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 711 auto &IndirectResult = DoublyIndirectResult.IDep; 712 InstrCount += IndirectResult.FDep.InstructionCount; 713 FunctionCount += IndirectResult.MDep.FunctionCount; 714 auto PA = PreservedAnalyses::none(); 715 if (F.getName() == "g") 716 PA.preserve<TestFunctionAnalysis>(); 717 else if (F.getName() == "h") 718 PA.preserve<TestIndirectFunctionAnalysis>(); 719 return PA; 720 })); 721 // Finally, use the analysis again on each function, forcing re-computation 722 // for all of them. 723 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 724 auto &DoublyIndirectResult = 725 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 726 auto &IndirectResult = DoublyIndirectResult.IDep; 727 InstrCount += IndirectResult.FDep.InstructionCount; 728 FunctionCount += IndirectResult.MDep.FunctionCount; 729 return PreservedAnalyses::all(); 730 })); 731 732 // Create a second function pass manager. This will cause the module-level 733 // invalidation to occur, which will force yet another invalidation of the 734 // indirect function-level analysis as the module analysis it depends on gets 735 // invalidated. 736 FunctionPassManager FPM2(/*DebugLogging*/ true); 737 FPM2.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 738 auto &DoublyIndirectResult = 739 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 740 auto &IndirectResult = DoublyIndirectResult.IDep; 741 InstrCount += IndirectResult.FDep.InstructionCount; 742 FunctionCount += IndirectResult.MDep.FunctionCount; 743 return PreservedAnalyses::all(); 744 })); 745 746 // Add a requires pass to populate the module analysis and then our function 747 // pass pipeline. 748 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 749 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 750 // Now require the module analysis again (it will have been invalidated once) 751 // and then use it again from a function pass manager. 752 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 753 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2))); 754 MPM.run(*M, MAM); 755 756 // There are generally two possible runs for each of the three functions. But 757 // for one function, we only invalidate the indirect analysis so the base one 758 // only gets run five times. 759 EXPECT_EQ(5, FunctionAnalysisRuns); 760 // The module analysis pass should be run twice here. 761 EXPECT_EQ(2, ModuleAnalysisRuns); 762 // The indirect analysis is invalidated for each function (either directly or 763 // indirectly) and run twice for each. 764 EXPECT_EQ(9, IndirectAnalysisRuns); 765 EXPECT_EQ(9, DoublyIndirectAnalysisRuns); 766 767 // There are five instructions in the module and we add the count four 768 // times. 769 EXPECT_EQ(5 * 4, InstrCount); 770 771 // There are three functions and we count them four times for each of the 772 // three functions. 773 EXPECT_EQ(3 * 4 * 3, FunctionCount); 774 } 775 } 776