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