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