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