1 //===- CGSCCPassManagerTest.cpp -------------------------------------------===// 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/Analysis/CGSCCPassManager.h" 11 #include "llvm/Analysis/LazyCallGraph.h" 12 #include "llvm/Analysis/TargetLibraryInfo.h" 13 #include "llvm/AsmParser/Parser.h" 14 #include "llvm/IR/Function.h" 15 #include "llvm/IR/InstIterator.h" 16 #include "llvm/IR/LLVMContext.h" 17 #include "llvm/IR/Module.h" 18 #include "llvm/IR/PassManager.h" 19 #include "llvm/Support/SourceMgr.h" 20 #include "gtest/gtest.h" 21 22 using namespace llvm; 23 24 namespace { 25 26 class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> { 27 public: 28 struct Result { 29 Result(int Count) : FunctionCount(Count) {} 30 int FunctionCount; 31 }; 32 33 TestModuleAnalysis(int &Runs) : Runs(Runs) {} 34 35 Result run(Module &M, ModuleAnalysisManager &AM) { 36 ++Runs; 37 return Result(M.size()); 38 } 39 40 private: 41 friend AnalysisInfoMixin<TestModuleAnalysis>; 42 static AnalysisKey Key; 43 44 int &Runs; 45 }; 46 47 AnalysisKey TestModuleAnalysis::Key; 48 49 class TestSCCAnalysis : public AnalysisInfoMixin<TestSCCAnalysis> { 50 public: 51 struct Result { 52 Result(int Count) : FunctionCount(Count) {} 53 int FunctionCount; 54 }; 55 56 TestSCCAnalysis(int &Runs) : Runs(Runs) {} 57 58 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) { 59 ++Runs; 60 return Result(C.size()); 61 } 62 63 private: 64 friend AnalysisInfoMixin<TestSCCAnalysis>; 65 static AnalysisKey Key; 66 67 int &Runs; 68 }; 69 70 AnalysisKey TestSCCAnalysis::Key; 71 72 class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> { 73 public: 74 struct Result { 75 Result(int Count) : InstructionCount(Count) {} 76 int InstructionCount; 77 }; 78 79 TestFunctionAnalysis(int &Runs) : Runs(Runs) {} 80 81 Result run(Function &F, FunctionAnalysisManager &AM) { 82 ++Runs; 83 int Count = 0; 84 for (Instruction &I : instructions(F)) { 85 (void)I; 86 ++Count; 87 } 88 return Result(Count); 89 } 90 91 private: 92 friend AnalysisInfoMixin<TestFunctionAnalysis>; 93 static AnalysisKey Key; 94 95 int &Runs; 96 }; 97 98 AnalysisKey TestFunctionAnalysis::Key; 99 100 class TestImmutableFunctionAnalysis 101 : public AnalysisInfoMixin<TestImmutableFunctionAnalysis> { 102 public: 103 struct Result { 104 bool invalidate(Function &, const PreservedAnalyses &, 105 FunctionAnalysisManager::Invalidator &) { 106 return false; 107 } 108 }; 109 110 TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {} 111 112 Result run(Function &F, FunctionAnalysisManager &AM) { 113 ++Runs; 114 return Result(); 115 } 116 117 private: 118 friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>; 119 static AnalysisKey Key; 120 121 int &Runs; 122 }; 123 124 AnalysisKey TestImmutableFunctionAnalysis::Key; 125 126 struct LambdaModulePass : public PassInfoMixin<LambdaModulePass> { 127 template <typename T> 128 LambdaModulePass(T &&Arg) : Func(std::forward<T>(Arg)) {} 129 130 PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) { 131 return Func(F, AM); 132 } 133 134 std::function<PreservedAnalyses(Module &, ModuleAnalysisManager &)> Func; 135 }; 136 137 struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> { 138 template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {} 139 140 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 141 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 142 return Func(C, AM, CG, UR); 143 } 144 145 std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &, 146 LazyCallGraph &, CGSCCUpdateResult &)> 147 Func; 148 }; 149 150 struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> { 151 template <typename T> 152 LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {} 153 154 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { 155 return Func(F, AM); 156 } 157 158 std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func; 159 }; 160 161 std::unique_ptr<Module> parseIR(const char *IR) { 162 // We just use a static context here. This is never called from multiple 163 // threads so it is harmless no matter how it is implemented. We just need 164 // the context to outlive the module which it does. 165 static LLVMContext C; 166 SMDiagnostic Err; 167 return parseAssemblyString(IR, Err, C); 168 } 169 170 class CGSCCPassManagerTest : public ::testing::Test { 171 protected: 172 LLVMContext Context; 173 FunctionAnalysisManager FAM; 174 CGSCCAnalysisManager CGAM; 175 ModuleAnalysisManager MAM; 176 177 std::unique_ptr<Module> M; 178 179 public: 180 CGSCCPassManagerTest() 181 : FAM(/*DebugLogging*/ true), CGAM(/*DebugLogging*/ true), 182 MAM(/*DebugLogging*/ true), 183 M(parseIR( 184 // Define a module with the following call graph, where calls go 185 // out the bottom of nodes and enter the top: 186 // 187 // f 188 // |\ _ 189 // | \ / | 190 // g h1 | 191 // | | | 192 // | h2 | 193 // | | | 194 // | h3 | 195 // | / \_/ 196 // |/ 197 // x 198 // 199 "define void @f() {\n" 200 "entry:\n" 201 " call void @g()\n" 202 " call void @h1()\n" 203 " ret void\n" 204 "}\n" 205 "define void @g() {\n" 206 "entry:\n" 207 " call void @g()\n" 208 " call void @x()\n" 209 " ret void\n" 210 "}\n" 211 "define void @h1() {\n" 212 "entry:\n" 213 " call void @h2()\n" 214 " ret void\n" 215 "}\n" 216 "define void @h2() {\n" 217 "entry:\n" 218 " call void @h3()\n" 219 " call void @x()\n" 220 " ret void\n" 221 "}\n" 222 "define void @h3() {\n" 223 "entry:\n" 224 " call void @h1()\n" 225 " ret void\n" 226 "}\n" 227 "define void @x() {\n" 228 "entry:\n" 229 " ret void\n" 230 "}\n")) { 231 MAM.registerPass([&] { return TargetLibraryAnalysis(); }); 232 MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); 233 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); 234 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); }); 235 CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); }); 236 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); }); 237 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); }); 238 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); 239 } 240 }; 241 242 TEST_F(CGSCCPassManagerTest, Basic) { 243 int FunctionAnalysisRuns = 0; 244 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 245 int ImmutableFunctionAnalysisRuns = 0; 246 FAM.registerPass([&] { 247 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns); 248 }); 249 250 int SCCAnalysisRuns = 0; 251 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 252 253 int ModuleAnalysisRuns = 0; 254 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 255 256 ModulePassManager MPM(/*DebugLogging*/ true); 257 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 258 259 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 260 FunctionPassManager FPM1(/*DebugLogging*/ true); 261 int FunctionPassRunCount1 = 0; 262 FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) { 263 ++FunctionPassRunCount1; 264 return PreservedAnalyses::none(); 265 })); 266 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 267 268 int SCCPassRunCount1 = 0; 269 int AnalyzedInstrCount1 = 0; 270 int AnalyzedSCCFunctionCount1 = 0; 271 int AnalyzedModuleFunctionCount1 = 0; 272 CGPM1.addPass( 273 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 274 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 275 ++SCCPassRunCount1; 276 277 const ModuleAnalysisManager &MAM = 278 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager(); 279 FunctionAnalysisManager &FAM = 280 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager(); 281 if (TestModuleAnalysis::Result *TMA = 282 MAM.getCachedResult<TestModuleAnalysis>( 283 *C.begin()->getFunction().getParent())) 284 AnalyzedModuleFunctionCount1 += TMA->FunctionCount; 285 286 TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG); 287 AnalyzedSCCFunctionCount1 += AR.FunctionCount; 288 for (LazyCallGraph::Node &N : C) { 289 TestFunctionAnalysis::Result &FAR = 290 FAM.getResult<TestFunctionAnalysis>(N.getFunction()); 291 AnalyzedInstrCount1 += FAR.InstructionCount; 292 293 // Just ensure we get the immutable results. 294 (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction()); 295 } 296 297 return PreservedAnalyses::all(); 298 })); 299 300 FunctionPassManager FPM2(/*DebugLogging*/ true); 301 int FunctionPassRunCount2 = 0; 302 FPM2.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) { 303 ++FunctionPassRunCount2; 304 return PreservedAnalyses::none(); 305 })); 306 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 307 308 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 309 310 FunctionPassManager FPM3(/*DebugLogging*/ true); 311 int FunctionPassRunCount3 = 0; 312 FPM3.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) { 313 ++FunctionPassRunCount3; 314 return PreservedAnalyses::none(); 315 })); 316 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3))); 317 318 MPM.run(*M, MAM); 319 320 EXPECT_EQ(4, SCCPassRunCount1); 321 EXPECT_EQ(6, FunctionPassRunCount1); 322 EXPECT_EQ(6, FunctionPassRunCount2); 323 EXPECT_EQ(6, FunctionPassRunCount3); 324 325 EXPECT_EQ(1, ModuleAnalysisRuns); 326 EXPECT_EQ(4, SCCAnalysisRuns); 327 EXPECT_EQ(6, FunctionAnalysisRuns); 328 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns); 329 330 EXPECT_EQ(14, AnalyzedInstrCount1); 331 EXPECT_EQ(6, AnalyzedSCCFunctionCount1); 332 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1); 333 } 334 335 // Test that an SCC pass which fails to preserve a module analysis does in fact 336 // invalidate that module analysis. 337 TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) { 338 int ModuleAnalysisRuns = 0; 339 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 340 341 ModulePassManager MPM(/*DebugLogging*/ true); 342 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 343 344 // The first CGSCC run we preserve everything and make sure that works and 345 // the module analysis is available in the second CGSCC run from the one 346 // required module pass above. 347 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 348 int CountFoundModuleAnalysis1 = 0; 349 CGPM1.addPass( 350 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 351 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 352 const auto &MAM = 353 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager(); 354 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>( 355 *C.begin()->getFunction().getParent()); 356 357 if (TMA) 358 ++CountFoundModuleAnalysis1; 359 360 return PreservedAnalyses::all(); 361 })); 362 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 363 364 // The second CGSCC run checks that the module analysis got preserved the 365 // previous time and in one SCC fails to preserve it. 366 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 367 int CountFoundModuleAnalysis2 = 0; 368 CGPM2.addPass( 369 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 370 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 371 const auto &MAM = 372 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager(); 373 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>( 374 *C.begin()->getFunction().getParent()); 375 376 if (TMA) 377 ++CountFoundModuleAnalysis2; 378 379 // Only fail to preserve analyses on one SCC and make sure that gets 380 // propagated. 381 return C.getName() == "(g)" ? PreservedAnalyses::none() 382 : PreservedAnalyses::all(); 383 })); 384 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 385 386 // The third CGSCC run should fail to find a cached module analysis as it 387 // should have been invalidated by the above CGSCC run. 388 CGSCCPassManager CGPM3(/*DebugLogging*/ true); 389 int CountFoundModuleAnalysis3 = 0; 390 CGPM3.addPass( 391 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 392 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 393 const auto &MAM = 394 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager(); 395 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>( 396 *C.begin()->getFunction().getParent()); 397 398 if (TMA) 399 ++CountFoundModuleAnalysis3; 400 401 return PreservedAnalyses::none(); 402 })); 403 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3))); 404 405 MPM.run(*M, MAM); 406 407 EXPECT_EQ(1, ModuleAnalysisRuns); 408 EXPECT_EQ(4, CountFoundModuleAnalysis1); 409 EXPECT_EQ(4, CountFoundModuleAnalysis2); 410 EXPECT_EQ(0, CountFoundModuleAnalysis3); 411 } 412 413 // Similar to the above, but test that this works for function passes embedded 414 // *within* a CGSCC layer. 415 TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) { 416 int ModuleAnalysisRuns = 0; 417 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 418 419 ModulePassManager MPM(/*DebugLogging*/ true); 420 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 421 422 // The first run we preserve everything and make sure that works and the 423 // module analysis is available in the second run from the one required 424 // module pass above. 425 FunctionPassManager FPM1(/*DebugLogging*/ true); 426 // Start true and mark false if we ever failed to find a module analysis 427 // because we expect this to succeed for each SCC. 428 bool FoundModuleAnalysis1 = true; 429 FPM1.addPass( 430 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { 431 const auto &MAM = 432 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); 433 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 434 435 if (!TMA) 436 FoundModuleAnalysis1 = false; 437 438 return PreservedAnalyses::all(); 439 })); 440 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 441 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 442 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 443 444 // The second run checks that the module analysis got preserved the previous 445 // time and in one function fails to preserve it. 446 FunctionPassManager FPM2(/*DebugLogging*/ true); 447 // Again, start true and mark false if we ever failed to find a module analysis 448 // because we expect this to succeed for each SCC. 449 bool FoundModuleAnalysis2 = true; 450 FPM2.addPass( 451 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { 452 const auto &MAM = 453 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); 454 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 455 456 if (!TMA) 457 FoundModuleAnalysis2 = false; 458 459 // Only fail to preserve analyses on one SCC and make sure that gets 460 // propagated. 461 return F.getName() == "h2" ? PreservedAnalyses::none() 462 : PreservedAnalyses::all(); 463 })); 464 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 465 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 466 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 467 468 // The third run should fail to find a cached module analysis as it should 469 // have been invalidated by the above run. 470 FunctionPassManager FPM3(/*DebugLogging*/ true); 471 // Start false and mark true if we ever *succeeded* to find a module 472 // analysis, as we expect this to fail for every function. 473 bool FoundModuleAnalysis3 = false; 474 FPM3.addPass( 475 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { 476 const auto &MAM = 477 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); 478 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 479 480 if (TMA) 481 FoundModuleAnalysis3 = true; 482 483 return PreservedAnalyses::none(); 484 })); 485 CGSCCPassManager CGPM3(/*DebugLogging*/ true); 486 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3))); 487 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3))); 488 489 MPM.run(*M, MAM); 490 491 EXPECT_EQ(1, ModuleAnalysisRuns); 492 EXPECT_TRUE(FoundModuleAnalysis1); 493 EXPECT_TRUE(FoundModuleAnalysis2); 494 EXPECT_FALSE(FoundModuleAnalysis3); 495 } 496 497 // Test that a Module pass which fails to preserve an SCC analysis in fact 498 // invalidates that analysis. 499 TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysis) { 500 int SCCAnalysisRuns = 0; 501 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 502 503 ModulePassManager MPM(/*DebugLogging*/ true); 504 505 // First force the analysis to be run. 506 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 507 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 508 CGSCCAnalysisManager, LazyCallGraph &, 509 CGSCCUpdateResult &>()); 510 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 511 512 // Now run a module pass that preserves the LazyCallGraph and the proxy but 513 // not the SCC analysis. 514 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 515 PreservedAnalyses PA; 516 PA.preserve<LazyCallGraphAnalysis>(); 517 PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 518 PA.preserve<FunctionAnalysisManagerModuleProxy>(); 519 return PA; 520 })); 521 522 // And now a second CGSCC run which requires the SCC analysis again. This 523 // will trigger re-running it. 524 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 525 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 526 CGSCCAnalysisManager, LazyCallGraph &, 527 CGSCCUpdateResult &>()); 528 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 529 530 MPM.run(*M, MAM); 531 // Two runs and four SCCs. 532 EXPECT_EQ(2 * 4, SCCAnalysisRuns); 533 } 534 535 // Check that marking the SCC analysis preserved is sufficient to avoid 536 // invaliadtion. This should only run the analysis once for each SCC. 537 TEST_F(CGSCCPassManagerTest, TestModulePassCanPreserveSCCAnalysis) { 538 int SCCAnalysisRuns = 0; 539 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 540 541 ModulePassManager MPM(/*DebugLogging*/ true); 542 543 // First force the analysis to be run. 544 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 545 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 546 CGSCCAnalysisManager, LazyCallGraph &, 547 CGSCCUpdateResult &>()); 548 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 549 550 // Now run a module pass that preserves each of the necessary components 551 // (but not everything). 552 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 553 PreservedAnalyses PA; 554 PA.preserve<LazyCallGraphAnalysis>(); 555 PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 556 PA.preserve<FunctionAnalysisManagerModuleProxy>(); 557 PA.preserve<TestSCCAnalysis>(); 558 return PA; 559 })); 560 561 // And now a second CGSCC run which requires the SCC analysis again but find 562 // it in the cache. 563 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 564 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 565 CGSCCAnalysisManager, LazyCallGraph &, 566 CGSCCUpdateResult &>()); 567 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 568 569 MPM.run(*M, MAM); 570 // Four SCCs 571 EXPECT_EQ(4, SCCAnalysisRuns); 572 } 573 574 // Check that even when the analysis is preserved, if the SCC information isn't 575 // we still nuke things because the SCC keys could change. 576 TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysisOnCGChange) { 577 int SCCAnalysisRuns = 0; 578 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 579 580 ModulePassManager MPM(/*DebugLogging*/ true); 581 582 // First force the analysis to be run. 583 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 584 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 585 CGSCCAnalysisManager, LazyCallGraph &, 586 CGSCCUpdateResult &>()); 587 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 588 589 // Now run a module pass that preserves the analysis but not the call 590 // graph or proxy. 591 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 592 PreservedAnalyses PA; 593 PA.preserve<TestSCCAnalysis>(); 594 return PA; 595 })); 596 597 // And now a second CGSCC run which requires the SCC analysis again. 598 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 599 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 600 CGSCCAnalysisManager, LazyCallGraph &, 601 CGSCCUpdateResult &>()); 602 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 603 604 MPM.run(*M, MAM); 605 // Two runs and four SCCs. 606 EXPECT_EQ(2 * 4, SCCAnalysisRuns); 607 } 608 609 // Test that an SCC pass which fails to preserve a Function analysis in fact 610 // invalidates that analysis. 611 TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesFunctionAnalysis) { 612 int FunctionAnalysisRuns = 0; 613 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 614 615 // Create a very simple module with a single function and SCC to make testing 616 // these issues much easier. 617 std::unique_ptr<Module> M = parseIR("declare void @g()\n" 618 "declare void @h()\n" 619 "define void @f() {\n" 620 "entry:\n" 621 " call void @g()\n" 622 " call void @h()\n" 623 " ret void\n" 624 "}\n"); 625 626 CGSCCPassManager CGPM(/*DebugLogging*/ true); 627 628 // First force the analysis to be run. 629 FunctionPassManager FPM1(/*DebugLogging*/ true); 630 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 631 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 632 633 // Now run a module pass that preserves the LazyCallGraph and proxy but not 634 // the SCC analysis. 635 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &, 636 LazyCallGraph &, CGSCCUpdateResult &) { 637 PreservedAnalyses PA; 638 PA.preserve<LazyCallGraphAnalysis>(); 639 return PA; 640 })); 641 642 // And now a second CGSCC run which requires the SCC analysis again. This 643 // will trigger re-running it. 644 FunctionPassManager FPM2(/*DebugLogging*/ true); 645 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 646 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 647 648 ModulePassManager MPM(/*DebugLogging*/ true); 649 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 650 MPM.run(*M, MAM); 651 EXPECT_EQ(2, FunctionAnalysisRuns); 652 } 653 654 // Check that marking the SCC analysis preserved is sufficient. This should 655 // only run the analysis once the SCC. 656 TEST_F(CGSCCPassManagerTest, TestSCCPassCanPreserveFunctionAnalysis) { 657 int FunctionAnalysisRuns = 0; 658 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 659 660 // Create a very simple module with a single function and SCC to make testing 661 // these issues much easier. 662 std::unique_ptr<Module> M = parseIR("declare void @g()\n" 663 "declare void @h()\n" 664 "define void @f() {\n" 665 "entry:\n" 666 " call void @g()\n" 667 " call void @h()\n" 668 " ret void\n" 669 "}\n"); 670 671 CGSCCPassManager CGPM(/*DebugLogging*/ true); 672 673 // First force the analysis to be run. 674 FunctionPassManager FPM1(/*DebugLogging*/ true); 675 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 676 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 677 678 // Now run a module pass that preserves each of the necessary components 679 // (but 680 // not everything). 681 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &, 682 LazyCallGraph &, CGSCCUpdateResult &) { 683 PreservedAnalyses PA; 684 PA.preserve<LazyCallGraphAnalysis>(); 685 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 686 PA.preserve<TestFunctionAnalysis>(); 687 return PA; 688 })); 689 690 // And now a second CGSCC run which requires the SCC analysis again but find 691 // it in the cache. 692 FunctionPassManager FPM2(/*DebugLogging*/ true); 693 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 694 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 695 696 ModulePassManager MPM(/*DebugLogging*/ true); 697 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 698 MPM.run(*M, MAM); 699 EXPECT_EQ(1, FunctionAnalysisRuns); 700 } 701 702 // Note that there is no test for invalidating the call graph or other 703 // structure with an SCC pass because there is no mechanism to do that from 704 // withinsuch a pass. Instead, such a pass has to directly update the call 705 // graph structure. 706 707 // Test that a madule pass invalidates function analyses when the CGSCC proxies 708 // and pass manager. 709 TEST_F(CGSCCPassManagerTest, 710 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC) { 711 MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); 712 713 int FunctionAnalysisRuns = 0; 714 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 715 716 ModulePassManager MPM(/*DebugLogging*/ true); 717 718 // First force the analysis to be run. 719 FunctionPassManager FPM1(/*DebugLogging*/ true); 720 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 721 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 722 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 723 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 724 725 // Now run a module pass that preserves the LazyCallGraph and proxies but not 726 // the Function analysis. 727 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 728 PreservedAnalyses PA; 729 PA.preserve<LazyCallGraphAnalysis>(); 730 PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 731 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 732 PA.preserve<FunctionAnalysisManagerModuleProxy>(); 733 return PA; 734 })); 735 736 // And now a second CGSCC run which requires the SCC analysis again. This 737 // will trigger re-running it. 738 FunctionPassManager FPM2(/*DebugLogging*/ true); 739 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 740 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 741 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 742 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 743 744 MPM.run(*M, MAM); 745 // Two runs and 6 functions. 746 EXPECT_EQ(2 * 6, FunctionAnalysisRuns); 747 } 748 749 // Check that by marking the function pass and proxies as preserved, this 750 // propagates all the way through. 751 TEST_F(CGSCCPassManagerTest, 752 TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC) { 753 MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); 754 755 int FunctionAnalysisRuns = 0; 756 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 757 758 ModulePassManager MPM(/*DebugLogging*/ true); 759 760 // First force the analysis to be run. 761 FunctionPassManager FPM1(/*DebugLogging*/ true); 762 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 763 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 764 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 765 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 766 767 // Now run a module pass that preserves the LazyCallGraph, the proxy, and 768 // the Function analysis. 769 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 770 PreservedAnalyses PA; 771 PA.preserve<LazyCallGraphAnalysis>(); 772 PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 773 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 774 PA.preserve<FunctionAnalysisManagerModuleProxy>(); 775 PA.preserve<TestFunctionAnalysis>(); 776 return PA; 777 })); 778 779 // And now a second CGSCC run which requires the SCC analysis again. This 780 // will trigger re-running it. 781 FunctionPassManager FPM2(/*DebugLogging*/ true); 782 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 783 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 784 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 785 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 786 787 MPM.run(*M, MAM); 788 // One run and 6 functions. 789 EXPECT_EQ(6, FunctionAnalysisRuns); 790 } 791 792 // Check that if the lazy call graph itself isn't preserved we still manage to 793 // invalidate everything. 794 TEST_F(CGSCCPassManagerTest, 795 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange) { 796 MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); 797 798 int FunctionAnalysisRuns = 0; 799 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 800 801 ModulePassManager MPM(/*DebugLogging*/ true); 802 803 // First force the analysis to be run. 804 FunctionPassManager FPM1(/*DebugLogging*/ true); 805 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 806 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 807 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 808 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 809 810 // Now run a module pass that preserves the LazyCallGraph but not the 811 // Function analysis. 812 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 813 PreservedAnalyses PA; 814 return PA; 815 })); 816 817 // And now a second CGSCC run which requires the SCC analysis again. This 818 // will trigger re-running it. 819 FunctionPassManager FPM2(/*DebugLogging*/ true); 820 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 821 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 822 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 823 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 824 825 MPM.run(*M, MAM); 826 // Two runs and 6 functions. 827 EXPECT_EQ(2 * 6, FunctionAnalysisRuns); 828 } 829 830 /// A test CGSCC-level analysis pass which caches in its result another 831 /// analysis pass and uses it to serve queries. This requires the result to 832 /// invalidate itself when its dependency is invalidated. 833 /// 834 /// FIXME: Currently this doesn't also depend on a function analysis, and if it 835 /// did we would fail to invalidate it correctly. 836 struct TestIndirectSCCAnalysis 837 : public AnalysisInfoMixin<TestIndirectSCCAnalysis> { 838 struct Result { 839 Result(TestSCCAnalysis::Result &SCCDep, TestModuleAnalysis::Result &MDep) 840 : SCCDep(SCCDep), MDep(MDep) {} 841 TestSCCAnalysis::Result &SCCDep; 842 TestModuleAnalysis::Result &MDep; 843 844 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA, 845 CGSCCAnalysisManager::Invalidator &Inv) { 846 auto PAC = PA.getChecker<TestIndirectSCCAnalysis>(); 847 return !(PAC.preserved() || 848 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) || 849 Inv.invalidate<TestSCCAnalysis>(C, PA); 850 } 851 }; 852 853 TestIndirectSCCAnalysis(int &Runs) : Runs(Runs) {} 854 855 /// Run the analysis pass over the function and return a result. 856 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 857 LazyCallGraph &CG) { 858 ++Runs; 859 auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG); 860 861 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG); 862 const ModuleAnalysisManager &MAM = ModuleProxy.getManager(); 863 // For the test, we insist that the module analysis starts off in the 864 // cache. 865 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>( 866 *C.begin()->getFunction().getParent()); 867 // Register the dependency as module analysis dependencies have to be 868 // pre-registered on the proxy. 869 ModuleProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis, 870 TestIndirectSCCAnalysis>(); 871 872 return Result(SCCDep, MDep); 873 } 874 875 private: 876 friend AnalysisInfoMixin<TestIndirectSCCAnalysis>; 877 static AnalysisKey Key; 878 879 int &Runs; 880 }; 881 882 AnalysisKey TestIndirectSCCAnalysis::Key; 883 884 /// A test analysis pass which caches in its result the result from the above 885 /// indirect analysis pass. 886 /// 887 /// This allows us to ensure that whenever an analysis pass is invalidated due 888 /// to dependencies (especially dependencies across IR units that trigger 889 /// asynchronous invalidation) we correctly detect that this may in turn cause 890 /// other analysis to be invalidated. 891 struct TestDoublyIndirectSCCAnalysis 892 : public AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis> { 893 struct Result { 894 Result(TestIndirectSCCAnalysis::Result &IDep) : IDep(IDep) {} 895 TestIndirectSCCAnalysis::Result &IDep; 896 897 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA, 898 CGSCCAnalysisManager::Invalidator &Inv) { 899 auto PAC = PA.getChecker<TestDoublyIndirectSCCAnalysis>(); 900 return !(PAC.preserved() || 901 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) || 902 Inv.invalidate<TestIndirectSCCAnalysis>(C, PA); 903 } 904 }; 905 906 TestDoublyIndirectSCCAnalysis(int &Runs) : Runs(Runs) {} 907 908 /// Run the analysis pass over the function and return a result. 909 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 910 LazyCallGraph &CG) { 911 ++Runs; 912 auto &IDep = AM.getResult<TestIndirectSCCAnalysis>(C, CG); 913 return Result(IDep); 914 } 915 916 private: 917 friend AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis>; 918 static AnalysisKey Key; 919 920 int &Runs; 921 }; 922 923 AnalysisKey TestDoublyIndirectSCCAnalysis::Key; 924 925 /// A test analysis pass which caches results from three different IR unit 926 /// layers and requires intermediate layers to correctly propagate the entire 927 /// distance. 928 struct TestIndirectFunctionAnalysis 929 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> { 930 struct Result { 931 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep, 932 TestSCCAnalysis::Result &SCCDep) 933 : FDep(FDep), MDep(MDep), SCCDep(SCCDep) {} 934 TestFunctionAnalysis::Result &FDep; 935 TestModuleAnalysis::Result &MDep; 936 TestSCCAnalysis::Result &SCCDep; 937 938 bool invalidate(Function &F, const PreservedAnalyses &PA, 939 FunctionAnalysisManager::Invalidator &Inv) { 940 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>(); 941 return !(PAC.preserved() || 942 PAC.preservedSet<AllAnalysesOn<Function>>()) || 943 Inv.invalidate<TestFunctionAnalysis>(F, PA); 944 } 945 }; 946 947 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {} 948 949 /// Run the analysis pass over the function and return a result. 950 Result run(Function &F, FunctionAnalysisManager &AM) { 951 ++Runs; 952 auto &FDep = AM.getResult<TestFunctionAnalysis>(F); 953 954 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F); 955 const ModuleAnalysisManager &MAM = ModuleProxy.getManager(); 956 // For the test, we insist that the module analysis starts off in the 957 // cache. 958 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 959 // Register the dependency as module analysis dependencies have to be 960 // pre-registered on the proxy. 961 ModuleProxy.registerOuterAnalysisInvalidation< 962 TestModuleAnalysis, TestIndirectFunctionAnalysis>(); 963 964 // For thet test we assume this is run inside a CGSCC pass manager. 965 const LazyCallGraph &CG = 966 *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent()); 967 auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F); 968 const CGSCCAnalysisManager &CGAM = CGSCCProxy.getManager(); 969 // For the test, we insist that the CGSCC analysis starts off in the cache. 970 auto &SCCDep = 971 *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F))); 972 // Register the dependency as CGSCC analysis dependencies have to be 973 // pre-registered on the proxy. 974 CGSCCProxy.registerOuterAnalysisInvalidation< 975 TestSCCAnalysis, TestIndirectFunctionAnalysis>(); 976 977 return Result(FDep, MDep, SCCDep); 978 } 979 980 private: 981 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>; 982 static AnalysisKey Key; 983 984 int &Runs; 985 }; 986 987 AnalysisKey TestIndirectFunctionAnalysis::Key; 988 989 TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) { 990 int ModuleAnalysisRuns = 0; 991 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 992 993 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0, 994 DoublyIndirectSCCAnalysisRuns = 0; 995 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 996 CGAM.registerPass( 997 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); }); 998 CGAM.registerPass([&] { 999 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns); 1000 }); 1001 1002 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0; 1003 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 1004 FAM.registerPass([&] { 1005 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns); 1006 }); 1007 1008 ModulePassManager MPM(/*DebugLogging*/ true); 1009 1010 int FunctionCount = 0; 1011 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1012 // First just use the analysis to get the function count and preserve 1013 // everything. 1014 CGPM.addPass( 1015 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1016 LazyCallGraph &CG, CGSCCUpdateResult &) { 1017 auto &DoublyIndirectResult = 1018 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1019 auto &IndirectResult = DoublyIndirectResult.IDep; 1020 FunctionCount += IndirectResult.SCCDep.FunctionCount; 1021 return PreservedAnalyses::all(); 1022 })); 1023 CGPM.addPass(createCGSCCToFunctionPassAdaptor( 1024 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>())); 1025 1026 // Next, invalidate 1027 // - both analyses for the (f) and (x) SCCs, 1028 // - just the underlying (indirect) analysis for (g) SCC, and 1029 // - just the direct analysis for (h1,h2,h3) SCC. 1030 CGPM.addPass( 1031 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1032 LazyCallGraph &CG, CGSCCUpdateResult &) { 1033 auto &DoublyIndirectResult = 1034 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1035 auto &IndirectResult = DoublyIndirectResult.IDep; 1036 FunctionCount += IndirectResult.SCCDep.FunctionCount; 1037 auto PA = PreservedAnalyses::none(); 1038 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 1039 PA.preserveSet<AllAnalysesOn<Function>>(); 1040 if (C.getName() == "(g)") 1041 PA.preserve<TestSCCAnalysis>(); 1042 else if (C.getName() == "(h3, h1, h2)") 1043 PA.preserve<TestIndirectSCCAnalysis>(); 1044 return PA; 1045 })); 1046 // Finally, use the analysis again on each SCC (and function), forcing 1047 // re-computation for all of them. 1048 CGPM.addPass( 1049 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1050 LazyCallGraph &CG, CGSCCUpdateResult &) { 1051 auto &DoublyIndirectResult = 1052 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1053 auto &IndirectResult = DoublyIndirectResult.IDep; 1054 FunctionCount += IndirectResult.SCCDep.FunctionCount; 1055 return PreservedAnalyses::all(); 1056 })); 1057 CGPM.addPass(createCGSCCToFunctionPassAdaptor( 1058 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>())); 1059 1060 // Create a second CGSCC pass manager. This will cause the module-level 1061 // invalidation to occur, which will force yet another invalidation of the 1062 // indirect SCC-level analysis as the module analysis it depends on gets 1063 // invalidated. 1064 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 1065 CGPM2.addPass( 1066 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1067 LazyCallGraph &CG, CGSCCUpdateResult &) { 1068 auto &DoublyIndirectResult = 1069 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1070 auto &IndirectResult = DoublyIndirectResult.IDep; 1071 FunctionCount += IndirectResult.SCCDep.FunctionCount; 1072 return PreservedAnalyses::all(); 1073 })); 1074 CGPM2.addPass(createCGSCCToFunctionPassAdaptor( 1075 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>())); 1076 1077 // Add a requires pass to populate the module analysis and then our CGSCC 1078 // pass pipeline. 1079 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1080 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1081 // Now require the module analysis again (it will have been invalidated once) 1082 // and then use it again from our second CGSCC pipeline.. 1083 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1084 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 1085 MPM.run(*M, MAM); 1086 1087 // There are generally two possible runs for each of the four SCCs. But 1088 // for one SCC, we only invalidate the indirect analysis so the base one 1089 // only gets run seven times. 1090 EXPECT_EQ(7, SCCAnalysisRuns); 1091 // The module analysis pass should be run twice here. 1092 EXPECT_EQ(2, ModuleAnalysisRuns); 1093 // The indirect analysis is invalidated (either directly or indirectly) three 1094 // times for each of four SCCs. 1095 EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns); 1096 EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns); 1097 1098 // We run the indirect function analysis once per function the first time. 1099 // Then we re-run it for every SCC but "(g)". Then we re-run it for every 1100 // function again. 1101 EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns); 1102 1103 // Four passes count each of six functions once (via SCCs). 1104 EXPECT_EQ(4 * 6, FunctionCount); 1105 } 1106 1107 TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) { 1108 int ModuleAnalysisRuns = 0; 1109 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 1110 1111 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0, 1112 DoublyIndirectSCCAnalysisRuns = 0; 1113 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 1114 CGAM.registerPass( 1115 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); }); 1116 CGAM.registerPass([&] { 1117 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns); 1118 }); 1119 1120 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0; 1121 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 1122 FAM.registerPass([&] { 1123 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns); 1124 }); 1125 1126 ModulePassManager MPM(/*DebugLogging*/ true); 1127 1128 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1129 // First just use the analysis to get the function count and preserve 1130 // everything. 1131 using RequireTestIndirectFunctionAnalysisPass = 1132 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>; 1133 using RequireTestDoublyIndirectSCCAnalysisPass = 1134 RequireAnalysisPass<TestDoublyIndirectSCCAnalysis, LazyCallGraph::SCC, 1135 CGSCCAnalysisManager, LazyCallGraph &, 1136 CGSCCUpdateResult &>; 1137 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass()); 1138 CGPM.addPass(createCGSCCToFunctionPassAdaptor( 1139 RequireTestIndirectFunctionAnalysisPass())); 1140 1141 // Next, we inject an SCC pass that invalidates everything for the `(h3, h1, 1142 // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the 1143 // CG. This should successfully invalidate (and force to be re-run) all the 1144 // analyses for that SCC and for the functions. 1145 CGPM.addPass( 1146 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1147 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 1148 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1149 if (C.getName() != "(h3, h1, h2)") 1150 return PreservedAnalyses::all(); 1151 1152 // Build the preserved set. 1153 auto PA = PreservedAnalyses::none(); 1154 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 1155 PA.preserve<TestIndirectSCCAnalysis>(); 1156 PA.preserve<TestDoublyIndirectSCCAnalysis>(); 1157 1158 // Delete the call from `h2` to `h3`. 1159 auto &H2N = *llvm::find_if( 1160 C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; }); 1161 auto &H2F = H2N.getFunction(); 1162 auto &H3F = *cast<CallInst>(H2F.begin()->begin())->getCalledFunction(); 1163 assert(H3F.getName() == "h3" && "Wrong called function!"); 1164 H2F.begin()->begin()->eraseFromParent(); 1165 // Insert a bitcast of `h3` so that we retain a ref edge to it. 1166 (void)CastInst::CreatePointerCast(&H3F, 1167 Type::getInt8PtrTy(H2F.getContext()), 1168 "dummy", &*H2F.begin()->begin()); 1169 1170 // Now update the call graph. 1171 auto &NewC = 1172 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR); 1173 assert(&NewC != &C && "Should get a new SCC due to update!"); 1174 (void)&NewC; 1175 1176 return PA; 1177 })); 1178 // Now use the analysis again on each SCC and function, forcing 1179 // re-computation for all of them. 1180 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass()); 1181 CGPM.addPass(createCGSCCToFunctionPassAdaptor( 1182 RequireTestIndirectFunctionAnalysisPass())); 1183 1184 // Create another CGSCC pipeline that requires all the analyses again. 1185 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 1186 CGPM2.addPass(RequireTestDoublyIndirectSCCAnalysisPass()); 1187 CGPM2.addPass(createCGSCCToFunctionPassAdaptor( 1188 RequireTestIndirectFunctionAnalysisPass())); 1189 1190 // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3` 1191 // back to `h2`, and then invalidates everything for what will then be the 1192 // `(h3, h1, h2)` SCC again. 1193 CGSCCPassManager CGPM3(/*DebugLogging*/ true); 1194 CGPM3.addPass( 1195 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1196 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 1197 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1198 if (C.getName() != "(h2)") 1199 return PreservedAnalyses::all(); 1200 1201 // Build the preserved set. 1202 auto PA = PreservedAnalyses::none(); 1203 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 1204 PA.preserve<TestIndirectSCCAnalysis>(); 1205 PA.preserve<TestDoublyIndirectSCCAnalysis>(); 1206 1207 // Delete the bitcast of `h3` that we added earlier. 1208 auto &H2N = *C.begin(); 1209 auto &H2F = H2N.getFunction(); 1210 auto &H3F = *cast<Function>(cast<BitCastInst>(H2F.begin()->begin())->getOperand(0)); 1211 assert(H3F.getName() == "h3" && "Wrong called function!"); 1212 H2F.begin()->begin()->eraseFromParent(); 1213 // And insert a call to `h3`. 1214 (void)CallInst::Create(&H3F, {}, "", &*H2F.begin()->begin()); 1215 1216 // Now update the call graph. 1217 auto &NewC = 1218 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR); 1219 assert(&NewC != &C && "Should get a new SCC due to update!"); 1220 (void)&NewC; 1221 1222 return PA; 1223 })); 1224 // Now use the analysis again on each SCC and function, forcing 1225 // re-computation for all of them. 1226 CGPM3.addPass(RequireTestDoublyIndirectSCCAnalysisPass()); 1227 CGPM3.addPass(createCGSCCToFunctionPassAdaptor( 1228 RequireTestIndirectFunctionAnalysisPass())); 1229 1230 // Create a second CGSCC pass manager. This will cause the module-level 1231 // invalidation to occur, which will force yet another invalidation of the 1232 // indirect SCC-level analysis as the module analysis it depends on gets 1233 // invalidated. 1234 CGSCCPassManager CGPM4(/*DebugLogging*/ true); 1235 CGPM4.addPass(RequireTestDoublyIndirectSCCAnalysisPass()); 1236 CGPM4.addPass(createCGSCCToFunctionPassAdaptor( 1237 RequireTestIndirectFunctionAnalysisPass())); 1238 1239 // Add a requires pass to populate the module analysis and then one of our 1240 // CGSCC pipelines. Repeat for all four CGSCC pipelines. 1241 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1242 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1243 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1244 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 1245 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1246 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3))); 1247 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1248 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4))); 1249 MPM.run(*M, MAM); 1250 1251 // We run over four SCCs the first time. But then we split an SCC into three. 1252 // And then we merge those three back into one. 1253 EXPECT_EQ(4 + 3 + 1, SCCAnalysisRuns); 1254 // The module analysis pass should be run three times. 1255 EXPECT_EQ(3, ModuleAnalysisRuns); 1256 // We run over four SCCs the first time. Then over the two new ones. Then the 1257 // entire module is invalidated causing a full run over all seven. Then we 1258 // fold three SCCs back to one, and then run over the whole module again. 1259 EXPECT_EQ(4 + 2 + 7 + 1 + 4, IndirectSCCAnalysisRuns); 1260 EXPECT_EQ(4 + 2 + 7 + 1 + 4, DoublyIndirectSCCAnalysisRuns); 1261 1262 // First we run over all six functions. Then we re-run it over three when we 1263 // split their SCCs. Then we re-run over the whole module. Then we re-run 1264 // over three functions merged back into a single SCC, and then over the 1265 // whole module again. 1266 EXPECT_EQ(6 + 3 + 6 + 3 + 6, FunctionAnalysisRuns); 1267 1268 // Re run the function analysis over the entire module, and then re-run it 1269 // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over 1270 // the entire module, then the three functions merged back into a single SCC, 1271 // and then over the whole module. 1272 EXPECT_EQ(6 + 3 + 6 + 3 + 6, IndirectFunctionAnalysisRuns); 1273 } 1274 } 1275