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 MAM.registerPass([&] { return PassInstrumentationAnalysis(); }); 410 FAM.registerPass([&] { return PassInstrumentationAnalysis(); }); 411 412 ModulePassManager MPM; 413 414 // Count the runs over a Function. 415 int FunctionPassRunCount1 = 0; 416 int AnalyzedInstrCount1 = 0; 417 int AnalyzedFunctionCount1 = 0; 418 { 419 // Pointless scoped copy to test move assignment. 420 ModulePassManager NestedMPM(/*DebugLogging*/ true); 421 FunctionPassManager FPM; 422 { 423 // Pointless scope to test move assignment. 424 FunctionPassManager NestedFPM(/*DebugLogging*/ true); 425 NestedFPM.addPass(TestFunctionPass( 426 FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1)); 427 FPM = std::move(NestedFPM); 428 } 429 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 430 MPM = std::move(NestedMPM); 431 } 432 433 // Count the runs over a module. 434 int ModulePassRunCount = 0; 435 MPM.addPass(TestModulePass(ModulePassRunCount)); 436 437 // Count the runs over a Function in a separate manager. 438 int FunctionPassRunCount2 = 0; 439 int AnalyzedInstrCount2 = 0; 440 int AnalyzedFunctionCount2 = 0; 441 { 442 FunctionPassManager FPM(/*DebugLogging*/ true); 443 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2, 444 AnalyzedFunctionCount2)); 445 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 446 } 447 448 // A third function pass manager but with only preserving intervening passes 449 // and with a function pass that invalidates exactly one analysis. 450 MPM.addPass(TestPreservingModulePass()); 451 int FunctionPassRunCount3 = 0; 452 int AnalyzedInstrCount3 = 0; 453 int AnalyzedFunctionCount3 = 0; 454 { 455 FunctionPassManager FPM(/*DebugLogging*/ true); 456 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3, 457 AnalyzedFunctionCount3)); 458 FPM.addPass(TestInvalidationFunctionPass("f")); 459 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 460 } 461 462 // A fourth function pass manager but with only preserving intervening 463 // passes but triggering the module analysis. 464 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 465 int FunctionPassRunCount4 = 0; 466 int AnalyzedInstrCount4 = 0; 467 int AnalyzedFunctionCount4 = 0; 468 { 469 FunctionPassManager FPM; 470 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4, 471 AnalyzedFunctionCount4)); 472 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 473 } 474 475 // A fifth function pass manager which invalidates one function first but 476 // uses only cached results. 477 int FunctionPassRunCount5 = 0; 478 int AnalyzedInstrCount5 = 0; 479 int AnalyzedFunctionCount5 = 0; 480 { 481 FunctionPassManager FPM(/*DebugLogging*/ true); 482 FPM.addPass(TestInvalidationFunctionPass("f")); 483 FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5, 484 AnalyzedFunctionCount5, 485 /*OnlyUseCachedResults=*/true)); 486 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 487 } 488 489 MPM.run(*M, MAM); 490 491 // Validate module pass counters. 492 EXPECT_EQ(1, ModulePassRunCount); 493 494 // Validate all function pass counter sets are the same. 495 EXPECT_EQ(3, FunctionPassRunCount1); 496 EXPECT_EQ(5, AnalyzedInstrCount1); 497 EXPECT_EQ(0, AnalyzedFunctionCount1); 498 EXPECT_EQ(3, FunctionPassRunCount2); 499 EXPECT_EQ(5, AnalyzedInstrCount2); 500 EXPECT_EQ(0, AnalyzedFunctionCount2); 501 EXPECT_EQ(3, FunctionPassRunCount3); 502 EXPECT_EQ(5, AnalyzedInstrCount3); 503 EXPECT_EQ(0, AnalyzedFunctionCount3); 504 EXPECT_EQ(3, FunctionPassRunCount4); 505 EXPECT_EQ(5, AnalyzedInstrCount4); 506 EXPECT_EQ(9, AnalyzedFunctionCount4); 507 EXPECT_EQ(3, FunctionPassRunCount5); 508 EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached. 509 EXPECT_EQ(9, AnalyzedFunctionCount5); 510 511 // Validate the analysis counters: 512 // first run over 3 functions, then module pass invalidates 513 // second run over 3 functions, nothing invalidates 514 // third run over 0 functions, but 1 function invalidated 515 // fourth run over 1 function 516 // fifth run invalidates 1 function first, but runs over 0 functions 517 EXPECT_EQ(7, FunctionAnalysisRuns); 518 519 EXPECT_EQ(1, ModuleAnalysisRuns); 520 } 521 522 // A customized pass manager that passes extra arguments through the 523 // infrastructure. 524 typedef AnalysisManager<Function, int> CustomizedAnalysisManager; 525 typedef PassManager<Function, CustomizedAnalysisManager, int, int &> 526 CustomizedPassManager; 527 528 class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> { 529 public: 530 struct Result { 531 Result(int I) : I(I) {} 532 int I; 533 }; 534 535 Result run(Function &F, CustomizedAnalysisManager &AM, int I) { 536 return Result(I); 537 } 538 539 private: 540 friend AnalysisInfoMixin<CustomizedAnalysis>; 541 static AnalysisKey Key; 542 }; 543 544 AnalysisKey CustomizedAnalysis::Key; 545 546 struct CustomizedPass : PassInfoMixin<CustomizedPass> { 547 std::function<void(CustomizedAnalysis::Result &, int &)> Callback; 548 549 template <typename CallbackT> 550 CustomizedPass(CallbackT Callback) : Callback(Callback) {} 551 552 PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I, 553 int &O) { 554 Callback(AM.getResult<CustomizedAnalysis>(F, I), O); 555 return PreservedAnalyses::none(); 556 } 557 }; 558 559 TEST_F(PassManagerTest, CustomizedPassManagerArgs) { 560 CustomizedAnalysisManager AM; 561 AM.registerPass([&] { return CustomizedAnalysis(); }); 562 PassInstrumentationCallbacks PIC; 563 AM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); 564 565 CustomizedPassManager PM; 566 567 // Add an instance of the customized pass that just accumulates the input 568 // after it is round-tripped through the analysis. 569 int Result = 0; 570 PM.addPass( 571 CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; })); 572 573 // Run this over every function with the input of 42. 574 for (Function &F : *M) 575 PM.run(F, AM, 42, Result); 576 577 // And ensure that we accumulated the correct result. 578 EXPECT_EQ(42 * (int)M->size(), Result); 579 } 580 581 /// A test analysis pass which caches in its result another analysis pass and 582 /// uses it to serve queries. This requires the result to invalidate itself 583 /// when its dependency is invalidated. 584 struct TestIndirectFunctionAnalysis 585 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> { 586 struct Result { 587 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep) 588 : FDep(FDep), MDep(MDep) {} 589 TestFunctionAnalysis::Result &FDep; 590 TestModuleAnalysis::Result &MDep; 591 592 bool invalidate(Function &F, const PreservedAnalyses &PA, 593 FunctionAnalysisManager::Invalidator &Inv) { 594 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>(); 595 return !(PAC.preserved() || 596 PAC.preservedSet<AllAnalysesOn<Function>>()) || 597 Inv.invalidate<TestFunctionAnalysis>(F, PA); 598 } 599 }; 600 601 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {} 602 603 /// Run the analysis pass over the function and return a result. 604 Result run(Function &F, FunctionAnalysisManager &AM) { 605 ++Runs; 606 auto &FDep = AM.getResult<TestFunctionAnalysis>(F); 607 auto &Proxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F); 608 const ModuleAnalysisManager &MAM = Proxy.getManager(); 609 // For the test, we insist that the module analysis starts off in the 610 // cache. 611 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 612 // And register the dependency as module analysis dependencies have to be 613 // pre-registered on the proxy. 614 Proxy.registerOuterAnalysisInvalidation<TestModuleAnalysis, 615 TestIndirectFunctionAnalysis>(); 616 return Result(FDep, MDep); 617 } 618 619 private: 620 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>; 621 static AnalysisKey Key; 622 623 int &Runs; 624 }; 625 626 AnalysisKey TestIndirectFunctionAnalysis::Key; 627 628 /// A test analysis pass which chaches in its result the result from the above 629 /// indirect analysis pass. 630 /// 631 /// This allows us to ensure that whenever an analysis pass is invalidated due 632 /// to dependencies (especially dependencies across IR units that trigger 633 /// asynchronous invalidation) we correctly detect that this may in turn cause 634 /// other analysis to be invalidated. 635 struct TestDoublyIndirectFunctionAnalysis 636 : public AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis> { 637 struct Result { 638 Result(TestIndirectFunctionAnalysis::Result &IDep) : IDep(IDep) {} 639 TestIndirectFunctionAnalysis::Result &IDep; 640 641 bool invalidate(Function &F, const PreservedAnalyses &PA, 642 FunctionAnalysisManager::Invalidator &Inv) { 643 auto PAC = PA.getChecker<TestDoublyIndirectFunctionAnalysis>(); 644 return !(PAC.preserved() || 645 PAC.preservedSet<AllAnalysesOn<Function>>()) || 646 Inv.invalidate<TestIndirectFunctionAnalysis>(F, PA); 647 } 648 }; 649 650 TestDoublyIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {} 651 652 /// Run the analysis pass over the function and return a result. 653 Result run(Function &F, FunctionAnalysisManager &AM) { 654 ++Runs; 655 auto &IDep = AM.getResult<TestIndirectFunctionAnalysis>(F); 656 return Result(IDep); 657 } 658 659 private: 660 friend AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis>; 661 static AnalysisKey Key; 662 663 int &Runs; 664 }; 665 666 AnalysisKey TestDoublyIndirectFunctionAnalysis::Key; 667 668 struct LambdaPass : public PassInfoMixin<LambdaPass> { 669 using FuncT = std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)>; 670 671 LambdaPass(FuncT Func) : Func(std::move(Func)) {} 672 673 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { 674 return Func(F, AM); 675 } 676 677 FuncT Func; 678 }; 679 680 TEST_F(PassManagerTest, IndirectAnalysisInvalidation) { 681 FunctionAnalysisManager FAM(/*DebugLogging*/ true); 682 int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0, 683 IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0; 684 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 685 FAM.registerPass( 686 [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns); }); 687 FAM.registerPass([&] { 688 return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns); 689 }); 690 691 ModuleAnalysisManager MAM(/*DebugLogging*/ true); 692 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 693 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); 694 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); 695 696 PassInstrumentationCallbacks PIC; 697 MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); 698 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); 699 700 int InstrCount = 0, FunctionCount = 0; 701 ModulePassManager MPM(/*DebugLogging*/ true); 702 FunctionPassManager FPM(/*DebugLogging*/ true); 703 // First just use the analysis to get the instruction count, and preserve 704 // everything. 705 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 706 auto &DoublyIndirectResult = 707 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 708 auto &IndirectResult = DoublyIndirectResult.IDep; 709 InstrCount += IndirectResult.FDep.InstructionCount; 710 FunctionCount += IndirectResult.MDep.FunctionCount; 711 return PreservedAnalyses::all(); 712 })); 713 // Next, invalidate 714 // - both analyses for "f", 715 // - just the underlying (indirect) analysis for "g", and 716 // - just the direct analysis for "h". 717 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 718 auto &DoublyIndirectResult = 719 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 720 auto &IndirectResult = DoublyIndirectResult.IDep; 721 InstrCount += IndirectResult.FDep.InstructionCount; 722 FunctionCount += IndirectResult.MDep.FunctionCount; 723 auto PA = PreservedAnalyses::none(); 724 if (F.getName() == "g") 725 PA.preserve<TestFunctionAnalysis>(); 726 else if (F.getName() == "h") 727 PA.preserve<TestIndirectFunctionAnalysis>(); 728 return PA; 729 })); 730 // Finally, use the analysis again on each function, forcing re-computation 731 // for all of them. 732 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 733 auto &DoublyIndirectResult = 734 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 735 auto &IndirectResult = DoublyIndirectResult.IDep; 736 InstrCount += IndirectResult.FDep.InstructionCount; 737 FunctionCount += IndirectResult.MDep.FunctionCount; 738 return PreservedAnalyses::all(); 739 })); 740 741 // Create a second function pass manager. This will cause the module-level 742 // invalidation to occur, which will force yet another invalidation of the 743 // indirect function-level analysis as the module analysis it depends on gets 744 // invalidated. 745 FunctionPassManager FPM2(/*DebugLogging*/ true); 746 FPM2.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 747 auto &DoublyIndirectResult = 748 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 749 auto &IndirectResult = DoublyIndirectResult.IDep; 750 InstrCount += IndirectResult.FDep.InstructionCount; 751 FunctionCount += IndirectResult.MDep.FunctionCount; 752 return PreservedAnalyses::all(); 753 })); 754 755 // Add a requires pass to populate the module analysis and then our function 756 // pass pipeline. 757 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 758 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 759 // Now require the module analysis again (it will have been invalidated once) 760 // and then use it again from a function pass manager. 761 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 762 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2))); 763 MPM.run(*M, MAM); 764 765 // There are generally two possible runs for each of the three functions. But 766 // for one function, we only invalidate the indirect analysis so the base one 767 // only gets run five times. 768 EXPECT_EQ(5, FunctionAnalysisRuns); 769 // The module analysis pass should be run twice here. 770 EXPECT_EQ(2, ModuleAnalysisRuns); 771 // The indirect analysis is invalidated for each function (either directly or 772 // indirectly) and run twice for each. 773 EXPECT_EQ(9, IndirectAnalysisRuns); 774 EXPECT_EQ(9, DoublyIndirectAnalysisRuns); 775 776 // There are five instructions in the module and we add the count four 777 // times. 778 EXPECT_EQ(5 * 4, InstrCount); 779 780 // There are three functions and we count them four times for each of the 781 // three functions. 782 EXPECT_EQ(3 * 4 * 3, FunctionCount); 783 } 784 } 785