1 //===- CGSCCPassManagerTest.cpp -------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Analysis/CGSCCPassManager.h" 10 #include "llvm/Analysis/LazyCallGraph.h" 11 #include "llvm/Analysis/TargetLibraryInfo.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 "llvm/Transforms/Utils/CallGraphUpdater.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 bool invalidate(Module &, const PreservedAnalyses &PA, 32 ModuleAnalysisManager::Invalidator &) { 33 // Check whether the analysis or all analyses on modules have been 34 // preserved. 35 auto PAC = PA.getChecker<TestModuleAnalysis>(); 36 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>()); 37 } 38 }; 39 40 TestModuleAnalysis(int &Runs) : Runs(Runs) {} 41 42 Result run(Module &M, ModuleAnalysisManager &AM) { 43 ++Runs; 44 return Result(M.size()); 45 } 46 47 private: 48 friend AnalysisInfoMixin<TestModuleAnalysis>; 49 static AnalysisKey Key; 50 51 int &Runs; 52 }; 53 54 AnalysisKey TestModuleAnalysis::Key; 55 56 class TestSCCAnalysis : public AnalysisInfoMixin<TestSCCAnalysis> { 57 public: 58 struct Result { 59 Result(int Count) : FunctionCount(Count) {} 60 int FunctionCount; 61 bool invalidate(LazyCallGraph::SCC &, const PreservedAnalyses &PA, 62 CGSCCAnalysisManager::Invalidator &) { 63 // Check whether the analysis or all analyses on SCCs have been 64 // preserved. 65 auto PAC = PA.getChecker<TestSCCAnalysis>(); 66 return !(PAC.preserved() || 67 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()); 68 } 69 }; 70 71 TestSCCAnalysis(int &Runs) : Runs(Runs) {} 72 73 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) { 74 ++Runs; 75 return Result(C.size()); 76 } 77 78 private: 79 friend AnalysisInfoMixin<TestSCCAnalysis>; 80 static AnalysisKey Key; 81 82 int &Runs; 83 }; 84 85 AnalysisKey TestSCCAnalysis::Key; 86 87 class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> { 88 public: 89 struct Result { 90 Result(int Count) : InstructionCount(Count) {} 91 int InstructionCount; 92 bool invalidate(Function &, const PreservedAnalyses &PA, 93 FunctionAnalysisManager::Invalidator &) { 94 // Check whether the analysis or all analyses on functions have been 95 // preserved. 96 auto PAC = PA.getChecker<TestFunctionAnalysis>(); 97 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()); 98 } 99 }; 100 101 TestFunctionAnalysis(int &Runs) : Runs(Runs) {} 102 103 Result run(Function &F, FunctionAnalysisManager &AM) { 104 ++Runs; 105 int Count = 0; 106 for (Instruction &I : instructions(F)) { 107 (void)I; 108 ++Count; 109 } 110 return Result(Count); 111 } 112 113 private: 114 friend AnalysisInfoMixin<TestFunctionAnalysis>; 115 static AnalysisKey Key; 116 117 int &Runs; 118 }; 119 120 AnalysisKey TestFunctionAnalysis::Key; 121 122 class TestImmutableFunctionAnalysis 123 : public AnalysisInfoMixin<TestImmutableFunctionAnalysis> { 124 public: 125 struct Result { 126 bool invalidate(Function &, const PreservedAnalyses &, 127 FunctionAnalysisManager::Invalidator &) { 128 return false; 129 } 130 }; 131 132 TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {} 133 134 Result run(Function &F, FunctionAnalysisManager &AM) { 135 ++Runs; 136 return Result(); 137 } 138 139 private: 140 friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>; 141 static AnalysisKey Key; 142 143 int &Runs; 144 }; 145 146 AnalysisKey TestImmutableFunctionAnalysis::Key; 147 148 struct LambdaModulePass : public PassInfoMixin<LambdaModulePass> { 149 template <typename T> 150 LambdaModulePass(T &&Arg) : Func(std::forward<T>(Arg)) {} 151 152 PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) { 153 return Func(F, AM); 154 } 155 156 std::function<PreservedAnalyses(Module &, ModuleAnalysisManager &)> Func; 157 }; 158 159 struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> { 160 template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {} 161 162 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 163 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 164 return Func(C, AM, CG, UR); 165 } 166 167 std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &, 168 LazyCallGraph &, CGSCCUpdateResult &)> 169 Func; 170 }; 171 172 struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> { 173 template <typename T> 174 LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {} 175 176 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { 177 return Func(F, AM); 178 } 179 180 std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func; 181 }; 182 183 std::unique_ptr<Module> parseIR(const char *IR) { 184 // We just use a static context here. This is never called from multiple 185 // threads so it is harmless no matter how it is implemented. We just need 186 // the context to outlive the module which it does. 187 static LLVMContext C; 188 SMDiagnostic Err; 189 return parseAssemblyString(IR, Err, C); 190 } 191 192 class CGSCCPassManagerTest : public ::testing::Test { 193 protected: 194 LLVMContext Context; 195 FunctionAnalysisManager FAM; 196 CGSCCAnalysisManager CGAM; 197 ModuleAnalysisManager MAM; 198 199 std::unique_ptr<Module> M; 200 201 public: 202 CGSCCPassManagerTest() 203 : FAM(/*DebugLogging*/ true), CGAM(/*DebugLogging*/ true), 204 MAM(/*DebugLogging*/ true), 205 M(parseIR( 206 // Define a module with the following call graph, where calls go 207 // out the bottom of nodes and enter the top: 208 // 209 // f 210 // |\ _ 211 // | \ / | 212 // g h1 | 213 // | | | 214 // | h2 | 215 // | | | 216 // | h3 | 217 // | / \_/ 218 // |/ 219 // x 220 // 221 "define void @f() {\n" 222 "entry:\n" 223 " call void @g()\n" 224 " call void @h1()\n" 225 " ret void\n" 226 "}\n" 227 "define void @g() {\n" 228 "entry:\n" 229 " call void @g()\n" 230 " call void @x()\n" 231 " ret void\n" 232 "}\n" 233 "define void @h1() {\n" 234 "entry:\n" 235 " call void @h2()\n" 236 " ret void\n" 237 "}\n" 238 "define void @h2() {\n" 239 "entry:\n" 240 " call void @h3()\n" 241 " call void @x()\n" 242 " ret void\n" 243 "}\n" 244 "define void @h3() {\n" 245 "entry:\n" 246 " call void @h1()\n" 247 " ret void\n" 248 "}\n" 249 "define void @x() {\n" 250 "entry:\n" 251 " ret void\n" 252 "}\n")) { 253 FAM.registerPass([&] { return TargetLibraryAnalysis(); }); 254 MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); 255 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); 256 257 // Register required pass instrumentation analysis. 258 MAM.registerPass([&] { return PassInstrumentationAnalysis(); }); 259 CGAM.registerPass([&] { return PassInstrumentationAnalysis(); }); 260 FAM.registerPass([&] { return PassInstrumentationAnalysis(); }); 261 262 // Cross-register proxies. 263 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); }); 264 CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); }); 265 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); }); 266 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); }); 267 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); 268 } 269 }; 270 271 TEST_F(CGSCCPassManagerTest, Basic) { 272 int FunctionAnalysisRuns = 0; 273 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 274 int ImmutableFunctionAnalysisRuns = 0; 275 FAM.registerPass([&] { 276 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns); 277 }); 278 279 int SCCAnalysisRuns = 0; 280 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 281 282 int ModuleAnalysisRuns = 0; 283 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 284 285 ModulePassManager MPM(/*DebugLogging*/ true); 286 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 287 288 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 289 FunctionPassManager FPM1(/*DebugLogging*/ true); 290 int FunctionPassRunCount1 = 0; 291 FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) { 292 ++FunctionPassRunCount1; 293 return PreservedAnalyses::none(); 294 })); 295 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 296 297 int SCCPassRunCount1 = 0; 298 int AnalyzedInstrCount1 = 0; 299 int AnalyzedSCCFunctionCount1 = 0; 300 int AnalyzedModuleFunctionCount1 = 0; 301 CGPM1.addPass( 302 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 303 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 304 ++SCCPassRunCount1; 305 306 const ModuleAnalysisManager &MAM = 307 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager(); 308 FunctionAnalysisManager &FAM = 309 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager(); 310 if (TestModuleAnalysis::Result *TMA = 311 MAM.getCachedResult<TestModuleAnalysis>( 312 *C.begin()->getFunction().getParent())) 313 AnalyzedModuleFunctionCount1 += TMA->FunctionCount; 314 315 TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG); 316 AnalyzedSCCFunctionCount1 += AR.FunctionCount; 317 for (LazyCallGraph::Node &N : C) { 318 TestFunctionAnalysis::Result &FAR = 319 FAM.getResult<TestFunctionAnalysis>(N.getFunction()); 320 AnalyzedInstrCount1 += FAR.InstructionCount; 321 322 // Just ensure we get the immutable results. 323 (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction()); 324 } 325 326 return PreservedAnalyses::all(); 327 })); 328 329 FunctionPassManager FPM2(/*DebugLogging*/ true); 330 int FunctionPassRunCount2 = 0; 331 FPM2.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) { 332 ++FunctionPassRunCount2; 333 return PreservedAnalyses::none(); 334 })); 335 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 336 337 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 338 339 FunctionPassManager FPM3(/*DebugLogging*/ true); 340 int FunctionPassRunCount3 = 0; 341 FPM3.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) { 342 ++FunctionPassRunCount3; 343 return PreservedAnalyses::none(); 344 })); 345 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3))); 346 347 MPM.run(*M, MAM); 348 349 EXPECT_EQ(4, SCCPassRunCount1); 350 EXPECT_EQ(6, FunctionPassRunCount1); 351 EXPECT_EQ(6, FunctionPassRunCount2); 352 EXPECT_EQ(6, FunctionPassRunCount3); 353 354 EXPECT_EQ(1, ModuleAnalysisRuns); 355 EXPECT_EQ(4, SCCAnalysisRuns); 356 EXPECT_EQ(6, FunctionAnalysisRuns); 357 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns); 358 359 EXPECT_EQ(14, AnalyzedInstrCount1); 360 EXPECT_EQ(6, AnalyzedSCCFunctionCount1); 361 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1); 362 } 363 364 // Test that an SCC pass which fails to preserve a module analysis does in fact 365 // invalidate that module analysis. 366 TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) { 367 int ModuleAnalysisRuns = 0; 368 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 369 370 ModulePassManager MPM(/*DebugLogging*/ true); 371 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 372 373 // The first CGSCC run we preserve everything and make sure that works and 374 // the module analysis is available in the second CGSCC run from the one 375 // required module pass above. 376 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 377 int CountFoundModuleAnalysis1 = 0; 378 CGPM1.addPass( 379 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 380 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 381 const auto &MAM = 382 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager(); 383 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>( 384 *C.begin()->getFunction().getParent()); 385 386 if (TMA) 387 ++CountFoundModuleAnalysis1; 388 389 return PreservedAnalyses::all(); 390 })); 391 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 392 393 // The second CGSCC run checks that the module analysis got preserved the 394 // previous time and in one SCC fails to preserve it. 395 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 396 int CountFoundModuleAnalysis2 = 0; 397 CGPM2.addPass( 398 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 399 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 400 const auto &MAM = 401 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager(); 402 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>( 403 *C.begin()->getFunction().getParent()); 404 405 if (TMA) 406 ++CountFoundModuleAnalysis2; 407 408 // Only fail to preserve analyses on one SCC and make sure that gets 409 // propagated. 410 return C.getName() == "(g)" ? PreservedAnalyses::none() 411 : PreservedAnalyses::all(); 412 })); 413 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 414 415 // The third CGSCC run should fail to find a cached module analysis as it 416 // should have been invalidated by the above CGSCC run. 417 CGSCCPassManager CGPM3(/*DebugLogging*/ true); 418 int CountFoundModuleAnalysis3 = 0; 419 CGPM3.addPass( 420 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 421 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 422 const auto &MAM = 423 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager(); 424 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>( 425 *C.begin()->getFunction().getParent()); 426 427 if (TMA) 428 ++CountFoundModuleAnalysis3; 429 430 return PreservedAnalyses::none(); 431 })); 432 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3))); 433 434 MPM.run(*M, MAM); 435 436 EXPECT_EQ(1, ModuleAnalysisRuns); 437 EXPECT_EQ(4, CountFoundModuleAnalysis1); 438 EXPECT_EQ(4, CountFoundModuleAnalysis2); 439 EXPECT_EQ(0, CountFoundModuleAnalysis3); 440 } 441 442 // Similar to the above, but test that this works for function passes embedded 443 // *within* a CGSCC layer. 444 TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) { 445 int ModuleAnalysisRuns = 0; 446 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 447 448 ModulePassManager MPM(/*DebugLogging*/ true); 449 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 450 451 // The first run we preserve everything and make sure that works and the 452 // module analysis is available in the second run from the one required 453 // module pass above. 454 FunctionPassManager FPM1(/*DebugLogging*/ true); 455 // Start true and mark false if we ever failed to find a module analysis 456 // because we expect this to succeed for each SCC. 457 bool FoundModuleAnalysis1 = true; 458 FPM1.addPass( 459 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { 460 const auto &MAM = 461 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); 462 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 463 464 if (!TMA) 465 FoundModuleAnalysis1 = false; 466 467 return PreservedAnalyses::all(); 468 })); 469 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 470 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 471 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 472 473 // The second run checks that the module analysis got preserved the previous 474 // time and in one function fails to preserve it. 475 FunctionPassManager FPM2(/*DebugLogging*/ true); 476 // Again, start true and mark false if we ever failed to find a module analysis 477 // because we expect this to succeed for each SCC. 478 bool FoundModuleAnalysis2 = true; 479 FPM2.addPass( 480 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { 481 const auto &MAM = 482 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); 483 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 484 485 if (!TMA) 486 FoundModuleAnalysis2 = false; 487 488 // Only fail to preserve analyses on one SCC and make sure that gets 489 // propagated. 490 return F.getName() == "h2" ? PreservedAnalyses::none() 491 : PreservedAnalyses::all(); 492 })); 493 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 494 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 495 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 496 497 // The third run should fail to find a cached module analysis as it should 498 // have been invalidated by the above run. 499 FunctionPassManager FPM3(/*DebugLogging*/ true); 500 // Start false and mark true if we ever *succeeded* to find a module 501 // analysis, as we expect this to fail for every function. 502 bool FoundModuleAnalysis3 = false; 503 FPM3.addPass( 504 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { 505 const auto &MAM = 506 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); 507 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 508 509 if (TMA) 510 FoundModuleAnalysis3 = true; 511 512 return PreservedAnalyses::none(); 513 })); 514 CGSCCPassManager CGPM3(/*DebugLogging*/ true); 515 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3))); 516 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3))); 517 518 MPM.run(*M, MAM); 519 520 EXPECT_EQ(1, ModuleAnalysisRuns); 521 EXPECT_TRUE(FoundModuleAnalysis1); 522 EXPECT_TRUE(FoundModuleAnalysis2); 523 EXPECT_FALSE(FoundModuleAnalysis3); 524 } 525 526 // Test that a Module pass which fails to preserve an SCC analysis in fact 527 // invalidates that analysis. 528 TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysis) { 529 int SCCAnalysisRuns = 0; 530 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 531 532 ModulePassManager MPM(/*DebugLogging*/ true); 533 534 // First force the analysis to be run. 535 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 536 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 537 CGSCCAnalysisManager, LazyCallGraph &, 538 CGSCCUpdateResult &>()); 539 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 540 541 // Now run a module pass that preserves the LazyCallGraph and the proxy but 542 // not the SCC analysis. 543 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 544 PreservedAnalyses PA; 545 PA.preserve<LazyCallGraphAnalysis>(); 546 PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 547 PA.preserve<FunctionAnalysisManagerModuleProxy>(); 548 return PA; 549 })); 550 551 // And now a second CGSCC run which requires the SCC analysis again. This 552 // will trigger re-running it. 553 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 554 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 555 CGSCCAnalysisManager, LazyCallGraph &, 556 CGSCCUpdateResult &>()); 557 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 558 559 MPM.run(*M, MAM); 560 // Two runs and four SCCs. 561 EXPECT_EQ(2 * 4, SCCAnalysisRuns); 562 } 563 564 // Check that marking the SCC analysis preserved is sufficient to avoid 565 // invaliadtion. This should only run the analysis once for each SCC. 566 TEST_F(CGSCCPassManagerTest, TestModulePassCanPreserveSCCAnalysis) { 567 int SCCAnalysisRuns = 0; 568 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 569 570 ModulePassManager MPM(/*DebugLogging*/ true); 571 572 // First force the analysis to be run. 573 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 574 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 575 CGSCCAnalysisManager, LazyCallGraph &, 576 CGSCCUpdateResult &>()); 577 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 578 579 // Now run a module pass that preserves each of the necessary components 580 // (but not everything). 581 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 582 PreservedAnalyses PA; 583 PA.preserve<LazyCallGraphAnalysis>(); 584 PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 585 PA.preserve<FunctionAnalysisManagerModuleProxy>(); 586 PA.preserve<TestSCCAnalysis>(); 587 return PA; 588 })); 589 590 // And now a second CGSCC run which requires the SCC analysis again but find 591 // it in the cache. 592 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 593 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 594 CGSCCAnalysisManager, LazyCallGraph &, 595 CGSCCUpdateResult &>()); 596 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 597 598 MPM.run(*M, MAM); 599 // Four SCCs 600 EXPECT_EQ(4, SCCAnalysisRuns); 601 } 602 603 // Check that even when the analysis is preserved, if the SCC information isn't 604 // we still nuke things because the SCC keys could change. 605 TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysisOnCGChange) { 606 int SCCAnalysisRuns = 0; 607 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 608 609 ModulePassManager MPM(/*DebugLogging*/ true); 610 611 // First force the analysis to be run. 612 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 613 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 614 CGSCCAnalysisManager, LazyCallGraph &, 615 CGSCCUpdateResult &>()); 616 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 617 618 // Now run a module pass that preserves the analysis but not the call 619 // graph or proxy. 620 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 621 PreservedAnalyses PA; 622 PA.preserve<TestSCCAnalysis>(); 623 return PA; 624 })); 625 626 // And now a second CGSCC run which requires the SCC analysis again. 627 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 628 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC, 629 CGSCCAnalysisManager, LazyCallGraph &, 630 CGSCCUpdateResult &>()); 631 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 632 633 MPM.run(*M, MAM); 634 // Two runs and four SCCs. 635 EXPECT_EQ(2 * 4, SCCAnalysisRuns); 636 } 637 638 // Test that an SCC pass which fails to preserve a Function analysis in fact 639 // invalidates that analysis. 640 TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesFunctionAnalysis) { 641 int FunctionAnalysisRuns = 0; 642 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 643 644 // Create a very simple module with a single function and SCC to make testing 645 // these issues much easier. 646 std::unique_ptr<Module> M = parseIR("declare void @g()\n" 647 "declare void @h()\n" 648 "define void @f() {\n" 649 "entry:\n" 650 " call void @g()\n" 651 " call void @h()\n" 652 " ret void\n" 653 "}\n"); 654 655 CGSCCPassManager CGPM(/*DebugLogging*/ true); 656 657 // First force the analysis to be run. 658 FunctionPassManager FPM1(/*DebugLogging*/ true); 659 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 660 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 661 662 // Now run a module pass that preserves the LazyCallGraph and proxy but not 663 // the SCC analysis. 664 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &, 665 LazyCallGraph &, CGSCCUpdateResult &) { 666 PreservedAnalyses PA; 667 PA.preserve<LazyCallGraphAnalysis>(); 668 return PA; 669 })); 670 671 // And now a second CGSCC run which requires the SCC analysis again. This 672 // will trigger re-running it. 673 FunctionPassManager FPM2(/*DebugLogging*/ true); 674 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 675 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 676 677 ModulePassManager MPM(/*DebugLogging*/ true); 678 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 679 MPM.run(*M, MAM); 680 EXPECT_EQ(2, FunctionAnalysisRuns); 681 } 682 683 // Check that marking the SCC analysis preserved is sufficient. This should 684 // only run the analysis once the SCC. 685 TEST_F(CGSCCPassManagerTest, TestSCCPassCanPreserveFunctionAnalysis) { 686 int FunctionAnalysisRuns = 0; 687 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 688 689 // Create a very simple module with a single function and SCC to make testing 690 // these issues much easier. 691 std::unique_ptr<Module> M = parseIR("declare void @g()\n" 692 "declare void @h()\n" 693 "define void @f() {\n" 694 "entry:\n" 695 " call void @g()\n" 696 " call void @h()\n" 697 " ret void\n" 698 "}\n"); 699 700 CGSCCPassManager CGPM(/*DebugLogging*/ true); 701 702 // First force the analysis to be run. 703 FunctionPassManager FPM1(/*DebugLogging*/ true); 704 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 705 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 706 707 // Now run a module pass that preserves each of the necessary components 708 // (but 709 // not everything). 710 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &, 711 LazyCallGraph &, CGSCCUpdateResult &) { 712 PreservedAnalyses PA; 713 PA.preserve<LazyCallGraphAnalysis>(); 714 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 715 PA.preserve<TestFunctionAnalysis>(); 716 return PA; 717 })); 718 719 // And now a second CGSCC run which requires the SCC analysis again but find 720 // it in the cache. 721 FunctionPassManager FPM2(/*DebugLogging*/ true); 722 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 723 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 724 725 ModulePassManager MPM(/*DebugLogging*/ true); 726 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 727 MPM.run(*M, MAM); 728 EXPECT_EQ(1, FunctionAnalysisRuns); 729 } 730 731 // Note that there is no test for invalidating the call graph or other 732 // structure with an SCC pass because there is no mechanism to do that from 733 // withinsuch a pass. Instead, such a pass has to directly update the call 734 // graph structure. 735 736 // Test that a madule pass invalidates function analyses when the CGSCC proxies 737 // and pass manager. 738 TEST_F(CGSCCPassManagerTest, 739 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC) { 740 MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); 741 742 int FunctionAnalysisRuns = 0; 743 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 744 745 ModulePassManager MPM(/*DebugLogging*/ true); 746 747 // First force the analysis to be run. 748 FunctionPassManager FPM1(/*DebugLogging*/ true); 749 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 750 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 751 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 752 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 753 754 // Now run a module pass that preserves the LazyCallGraph and proxies but not 755 // the Function analysis. 756 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 757 PreservedAnalyses PA; 758 PA.preserve<LazyCallGraphAnalysis>(); 759 PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 760 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 761 PA.preserve<FunctionAnalysisManagerModuleProxy>(); 762 return PA; 763 })); 764 765 // And now a second CGSCC run which requires the SCC analysis again. This 766 // will trigger re-running it. 767 FunctionPassManager FPM2(/*DebugLogging*/ true); 768 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 769 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 770 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 771 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 772 773 MPM.run(*M, MAM); 774 // Two runs and 6 functions. 775 EXPECT_EQ(2 * 6, FunctionAnalysisRuns); 776 } 777 778 // Check that by marking the function pass and proxies as preserved, this 779 // propagates all the way through. 780 TEST_F(CGSCCPassManagerTest, 781 TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC) { 782 MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); 783 784 int FunctionAnalysisRuns = 0; 785 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 786 787 ModulePassManager MPM(/*DebugLogging*/ true); 788 789 // First force the analysis to be run. 790 FunctionPassManager FPM1(/*DebugLogging*/ true); 791 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 792 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 793 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 794 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 795 796 // Now run a module pass that preserves the LazyCallGraph, the proxy, and 797 // the Function analysis. 798 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 799 PreservedAnalyses PA; 800 PA.preserve<LazyCallGraphAnalysis>(); 801 PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 802 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 803 PA.preserve<FunctionAnalysisManagerModuleProxy>(); 804 PA.preserve<TestFunctionAnalysis>(); 805 return PA; 806 })); 807 808 // And now a second CGSCC run which requires the SCC analysis again. This 809 // will trigger re-running it. 810 FunctionPassManager FPM2(/*DebugLogging*/ true); 811 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 812 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 813 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 814 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 815 816 MPM.run(*M, MAM); 817 // One run and 6 functions. 818 EXPECT_EQ(6, FunctionAnalysisRuns); 819 } 820 821 // Check that if the lazy call graph itself isn't preserved we still manage to 822 // invalidate everything. 823 TEST_F(CGSCCPassManagerTest, 824 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange) { 825 MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); 826 827 int FunctionAnalysisRuns = 0; 828 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 829 830 ModulePassManager MPM(/*DebugLogging*/ true); 831 832 // First force the analysis to be run. 833 FunctionPassManager FPM1(/*DebugLogging*/ true); 834 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 835 CGSCCPassManager CGPM1(/*DebugLogging*/ true); 836 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); 837 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); 838 839 // Now run a module pass that preserves the LazyCallGraph but not the 840 // Function analysis. 841 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) { 842 PreservedAnalyses PA; 843 return PA; 844 })); 845 846 // And now a second CGSCC run which requires the SCC analysis again. This 847 // will trigger re-running it. 848 FunctionPassManager FPM2(/*DebugLogging*/ true); 849 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>()); 850 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 851 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); 852 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 853 854 MPM.run(*M, MAM); 855 // Two runs and 6 functions. 856 EXPECT_EQ(2 * 6, FunctionAnalysisRuns); 857 } 858 859 /// A test CGSCC-level analysis pass which caches in its result another 860 /// analysis pass and uses it to serve queries. This requires the result to 861 /// invalidate itself when its dependency is invalidated. 862 /// 863 /// FIXME: Currently this doesn't also depend on a function analysis, and if it 864 /// did we would fail to invalidate it correctly. 865 struct TestIndirectSCCAnalysis 866 : public AnalysisInfoMixin<TestIndirectSCCAnalysis> { 867 struct Result { 868 Result(TestSCCAnalysis::Result &SCCDep, TestModuleAnalysis::Result &MDep) 869 : SCCDep(SCCDep), MDep(MDep) {} 870 TestSCCAnalysis::Result &SCCDep; 871 TestModuleAnalysis::Result &MDep; 872 873 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA, 874 CGSCCAnalysisManager::Invalidator &Inv) { 875 auto PAC = PA.getChecker<TestIndirectSCCAnalysis>(); 876 return !(PAC.preserved() || 877 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) || 878 Inv.invalidate<TestSCCAnalysis>(C, PA); 879 } 880 }; 881 882 TestIndirectSCCAnalysis(int &Runs) : Runs(Runs) {} 883 884 /// Run the analysis pass over the function and return a result. 885 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 886 LazyCallGraph &CG) { 887 ++Runs; 888 auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG); 889 890 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG); 891 const ModuleAnalysisManager &MAM = ModuleProxy.getManager(); 892 // For the test, we insist that the module analysis starts off in the 893 // cache. 894 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>( 895 *C.begin()->getFunction().getParent()); 896 // Register the dependency as module analysis dependencies have to be 897 // pre-registered on the proxy. 898 ModuleProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis, 899 TestIndirectSCCAnalysis>(); 900 901 return Result(SCCDep, MDep); 902 } 903 904 private: 905 friend AnalysisInfoMixin<TestIndirectSCCAnalysis>; 906 static AnalysisKey Key; 907 908 int &Runs; 909 }; 910 911 AnalysisKey TestIndirectSCCAnalysis::Key; 912 913 /// A test analysis pass which caches in its result the result from the above 914 /// indirect analysis pass. 915 /// 916 /// This allows us to ensure that whenever an analysis pass is invalidated due 917 /// to dependencies (especially dependencies across IR units that trigger 918 /// asynchronous invalidation) we correctly detect that this may in turn cause 919 /// other analysis to be invalidated. 920 struct TestDoublyIndirectSCCAnalysis 921 : public AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis> { 922 struct Result { 923 Result(TestIndirectSCCAnalysis::Result &IDep) : IDep(IDep) {} 924 TestIndirectSCCAnalysis::Result &IDep; 925 926 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA, 927 CGSCCAnalysisManager::Invalidator &Inv) { 928 auto PAC = PA.getChecker<TestDoublyIndirectSCCAnalysis>(); 929 return !(PAC.preserved() || 930 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) || 931 Inv.invalidate<TestIndirectSCCAnalysis>(C, PA); 932 } 933 }; 934 935 TestDoublyIndirectSCCAnalysis(int &Runs) : Runs(Runs) {} 936 937 /// Run the analysis pass over the function and return a result. 938 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 939 LazyCallGraph &CG) { 940 ++Runs; 941 auto &IDep = AM.getResult<TestIndirectSCCAnalysis>(C, CG); 942 return Result(IDep); 943 } 944 945 private: 946 friend AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis>; 947 static AnalysisKey Key; 948 949 int &Runs; 950 }; 951 952 AnalysisKey TestDoublyIndirectSCCAnalysis::Key; 953 954 /// A test analysis pass which caches results from three different IR unit 955 /// layers and requires intermediate layers to correctly propagate the entire 956 /// distance. 957 struct TestIndirectFunctionAnalysis 958 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> { 959 struct Result { 960 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep, 961 TestSCCAnalysis::Result &SCCDep) 962 : FDep(FDep), MDep(MDep), SCCDep(SCCDep) {} 963 TestFunctionAnalysis::Result &FDep; 964 TestModuleAnalysis::Result &MDep; 965 TestSCCAnalysis::Result &SCCDep; 966 967 bool invalidate(Function &F, const PreservedAnalyses &PA, 968 FunctionAnalysisManager::Invalidator &Inv) { 969 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>(); 970 return !(PAC.preserved() || 971 PAC.preservedSet<AllAnalysesOn<Function>>()) || 972 Inv.invalidate<TestFunctionAnalysis>(F, PA); 973 } 974 }; 975 976 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {} 977 978 /// Run the analysis pass over the function and return a result. 979 Result run(Function &F, FunctionAnalysisManager &AM) { 980 ++Runs; 981 auto &FDep = AM.getResult<TestFunctionAnalysis>(F); 982 983 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F); 984 const ModuleAnalysisManager &MAM = ModuleProxy.getManager(); 985 // For the test, we insist that the module analysis starts off in the 986 // cache. 987 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 988 // Register the dependency as module analysis dependencies have to be 989 // pre-registered on the proxy. 990 ModuleProxy.registerOuterAnalysisInvalidation< 991 TestModuleAnalysis, TestIndirectFunctionAnalysis>(); 992 993 // For thet test we assume this is run inside a CGSCC pass manager. 994 const LazyCallGraph &CG = 995 *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent()); 996 auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F); 997 const CGSCCAnalysisManager &CGAM = CGSCCProxy.getManager(); 998 // For the test, we insist that the CGSCC analysis starts off in the cache. 999 auto &SCCDep = 1000 *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F))); 1001 // Register the dependency as CGSCC analysis dependencies have to be 1002 // pre-registered on the proxy. 1003 CGSCCProxy.registerOuterAnalysisInvalidation< 1004 TestSCCAnalysis, TestIndirectFunctionAnalysis>(); 1005 1006 return Result(FDep, MDep, SCCDep); 1007 } 1008 1009 private: 1010 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>; 1011 static AnalysisKey Key; 1012 1013 int &Runs; 1014 }; 1015 1016 AnalysisKey TestIndirectFunctionAnalysis::Key; 1017 1018 TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) { 1019 int ModuleAnalysisRuns = 0; 1020 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 1021 1022 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0, 1023 DoublyIndirectSCCAnalysisRuns = 0; 1024 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 1025 CGAM.registerPass( 1026 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); }); 1027 CGAM.registerPass([&] { 1028 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns); 1029 }); 1030 1031 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0; 1032 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 1033 FAM.registerPass([&] { 1034 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns); 1035 }); 1036 1037 ModulePassManager MPM(/*DebugLogging*/ true); 1038 1039 int FunctionCount = 0; 1040 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1041 // First just use the analysis to get the function count and preserve 1042 // everything. 1043 CGPM.addPass( 1044 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1045 LazyCallGraph &CG, CGSCCUpdateResult &) { 1046 auto &DoublyIndirectResult = 1047 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1048 auto &IndirectResult = DoublyIndirectResult.IDep; 1049 FunctionCount += IndirectResult.SCCDep.FunctionCount; 1050 return PreservedAnalyses::all(); 1051 })); 1052 CGPM.addPass(createCGSCCToFunctionPassAdaptor( 1053 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>())); 1054 1055 // Next, invalidate 1056 // - both analyses for the (f) and (x) SCCs, 1057 // - just the underlying (indirect) analysis for (g) SCC, and 1058 // - just the direct analysis for (h1,h2,h3) SCC. 1059 CGPM.addPass( 1060 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1061 LazyCallGraph &CG, CGSCCUpdateResult &) { 1062 auto &DoublyIndirectResult = 1063 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1064 auto &IndirectResult = DoublyIndirectResult.IDep; 1065 FunctionCount += IndirectResult.SCCDep.FunctionCount; 1066 auto PA = PreservedAnalyses::none(); 1067 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 1068 PA.preserveSet<AllAnalysesOn<Function>>(); 1069 if (C.getName() == "(g)") 1070 PA.preserve<TestSCCAnalysis>(); 1071 else if (C.getName() == "(h3, h1, h2)") 1072 PA.preserve<TestIndirectSCCAnalysis>(); 1073 return PA; 1074 })); 1075 // Finally, use the analysis again on each SCC (and function), forcing 1076 // re-computation for all of them. 1077 CGPM.addPass( 1078 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1079 LazyCallGraph &CG, CGSCCUpdateResult &) { 1080 auto &DoublyIndirectResult = 1081 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1082 auto &IndirectResult = DoublyIndirectResult.IDep; 1083 FunctionCount += IndirectResult.SCCDep.FunctionCount; 1084 return PreservedAnalyses::all(); 1085 })); 1086 CGPM.addPass(createCGSCCToFunctionPassAdaptor( 1087 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>())); 1088 1089 // Create a second CGSCC pass manager. This will cause the module-level 1090 // invalidation to occur, which will force yet another invalidation of the 1091 // indirect SCC-level analysis as the module analysis it depends on gets 1092 // invalidated. 1093 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 1094 CGPM2.addPass( 1095 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1096 LazyCallGraph &CG, CGSCCUpdateResult &) { 1097 auto &DoublyIndirectResult = 1098 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1099 auto &IndirectResult = DoublyIndirectResult.IDep; 1100 FunctionCount += IndirectResult.SCCDep.FunctionCount; 1101 return PreservedAnalyses::all(); 1102 })); 1103 CGPM2.addPass(createCGSCCToFunctionPassAdaptor( 1104 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>())); 1105 1106 // Add a requires pass to populate the module analysis and then our CGSCC 1107 // pass pipeline. 1108 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1109 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1110 // Now require the module analysis again (it will have been invalidated once) 1111 // and then use it again from our second CGSCC pipeline.. 1112 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1113 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 1114 MPM.run(*M, MAM); 1115 1116 // There are generally two possible runs for each of the four SCCs. But 1117 // for one SCC, we only invalidate the indirect analysis so the base one 1118 // only gets run seven times. 1119 EXPECT_EQ(7, SCCAnalysisRuns); 1120 // The module analysis pass should be run twice here. 1121 EXPECT_EQ(2, ModuleAnalysisRuns); 1122 // The indirect analysis is invalidated (either directly or indirectly) three 1123 // times for each of four SCCs. 1124 EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns); 1125 EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns); 1126 1127 // We run the indirect function analysis once per function the first time. 1128 // Then we re-run it for every SCC but "(g)". Then we re-run it for every 1129 // function again. 1130 EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns); 1131 1132 // Four passes count each of six functions once (via SCCs). 1133 EXPECT_EQ(4 * 6, FunctionCount); 1134 } 1135 1136 TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) { 1137 int ModuleAnalysisRuns = 0; 1138 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 1139 1140 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0, 1141 DoublyIndirectSCCAnalysisRuns = 0; 1142 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); 1143 CGAM.registerPass( 1144 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); }); 1145 CGAM.registerPass([&] { 1146 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns); 1147 }); 1148 1149 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0; 1150 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 1151 FAM.registerPass([&] { 1152 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns); 1153 }); 1154 1155 ModulePassManager MPM(/*DebugLogging*/ true); 1156 1157 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1158 // First just use the analysis to get the function count and preserve 1159 // everything. 1160 using RequireTestIndirectFunctionAnalysisPass = 1161 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>; 1162 using RequireTestDoublyIndirectSCCAnalysisPass = 1163 RequireAnalysisPass<TestDoublyIndirectSCCAnalysis, LazyCallGraph::SCC, 1164 CGSCCAnalysisManager, LazyCallGraph &, 1165 CGSCCUpdateResult &>; 1166 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass()); 1167 CGPM.addPass(createCGSCCToFunctionPassAdaptor( 1168 RequireTestIndirectFunctionAnalysisPass())); 1169 1170 // Next, we inject an SCC pass that invalidates everything for the `(h3, h1, 1171 // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the 1172 // CG. This should successfully invalidate (and force to be re-run) all the 1173 // analyses for that SCC and for the functions. 1174 CGPM.addPass( 1175 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1176 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 1177 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1178 if (C.getName() != "(h3, h1, h2)") 1179 return PreservedAnalyses::all(); 1180 1181 // Build the preserved set. 1182 auto PA = PreservedAnalyses::none(); 1183 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 1184 PA.preserve<TestIndirectSCCAnalysis>(); 1185 PA.preserve<TestDoublyIndirectSCCAnalysis>(); 1186 1187 // Delete the call from `h2` to `h3`. 1188 auto &H2N = *llvm::find_if( 1189 C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; }); 1190 auto &H2F = H2N.getFunction(); 1191 auto &H3F = *cast<CallInst>(H2F.begin()->begin())->getCalledFunction(); 1192 assert(H3F.getName() == "h3" && "Wrong called function!"); 1193 H2F.begin()->begin()->eraseFromParent(); 1194 // Insert a bitcast of `h3` so that we retain a ref edge to it. 1195 (void)CastInst::CreatePointerCast(&H3F, 1196 Type::getInt8PtrTy(H2F.getContext()), 1197 "dummy", &*H2F.begin()->begin()); 1198 1199 // Now update the call graph. 1200 auto &NewC = 1201 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR); 1202 assert(&NewC != &C && "Should get a new SCC due to update!"); 1203 (void)&NewC; 1204 1205 return PA; 1206 })); 1207 // Now use the analysis again on each SCC and function, forcing 1208 // re-computation for all of them. 1209 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass()); 1210 CGPM.addPass(createCGSCCToFunctionPassAdaptor( 1211 RequireTestIndirectFunctionAnalysisPass())); 1212 1213 // Create another CGSCC pipeline that requires all the analyses again. 1214 CGSCCPassManager CGPM2(/*DebugLogging*/ true); 1215 CGPM2.addPass(RequireTestDoublyIndirectSCCAnalysisPass()); 1216 CGPM2.addPass(createCGSCCToFunctionPassAdaptor( 1217 RequireTestIndirectFunctionAnalysisPass())); 1218 1219 // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3` 1220 // back to `h2`, and then invalidates everything for what will then be the 1221 // `(h3, h1, h2)` SCC again. 1222 CGSCCPassManager CGPM3(/*DebugLogging*/ true); 1223 CGPM3.addPass( 1224 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1225 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 1226 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG); 1227 if (C.getName() != "(h2)") 1228 return PreservedAnalyses::all(); 1229 1230 // Build the preserved set. 1231 auto PA = PreservedAnalyses::none(); 1232 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 1233 PA.preserve<TestIndirectSCCAnalysis>(); 1234 PA.preserve<TestDoublyIndirectSCCAnalysis>(); 1235 1236 // Delete the bitcast of `h3` that we added earlier. 1237 auto &H2N = *C.begin(); 1238 auto &H2F = H2N.getFunction(); 1239 auto &H3F = *cast<Function>(cast<BitCastInst>(H2F.begin()->begin())->getOperand(0)); 1240 assert(H3F.getName() == "h3" && "Wrong called function!"); 1241 H2F.begin()->begin()->eraseFromParent(); 1242 // And insert a call to `h3`. 1243 (void)CallInst::Create(&H3F, {}, "", &*H2F.begin()->begin()); 1244 1245 // Now update the call graph. 1246 auto &NewC = 1247 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR); 1248 assert(&NewC != &C && "Should get a new SCC due to update!"); 1249 (void)&NewC; 1250 1251 return PA; 1252 })); 1253 // Now use the analysis again on each SCC and function, forcing 1254 // re-computation for all of them. 1255 CGPM3.addPass(RequireTestDoublyIndirectSCCAnalysisPass()); 1256 CGPM3.addPass(createCGSCCToFunctionPassAdaptor( 1257 RequireTestIndirectFunctionAnalysisPass())); 1258 1259 // Create a second CGSCC pass manager. This will cause the module-level 1260 // invalidation to occur, which will force yet another invalidation of the 1261 // indirect SCC-level analysis as the module analysis it depends on gets 1262 // invalidated. 1263 CGSCCPassManager CGPM4(/*DebugLogging*/ true); 1264 CGPM4.addPass(RequireTestDoublyIndirectSCCAnalysisPass()); 1265 CGPM4.addPass(createCGSCCToFunctionPassAdaptor( 1266 RequireTestIndirectFunctionAnalysisPass())); 1267 1268 // Add a requires pass to populate the module analysis and then one of our 1269 // CGSCC pipelines. Repeat for all four CGSCC pipelines. 1270 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1271 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1272 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1273 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); 1274 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1275 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3))); 1276 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 1277 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4))); 1278 MPM.run(*M, MAM); 1279 1280 // We run over four SCCs the first time. But then we split an SCC into three. 1281 // And then we merge those three back into one. However, this also 1282 // invalidates all three SCCs further down in the PO walk. 1283 EXPECT_EQ(4 + 3 + 1 + 3, SCCAnalysisRuns); 1284 // The module analysis pass should be run three times. 1285 EXPECT_EQ(3, ModuleAnalysisRuns); 1286 // We run over four SCCs the first time. Then over the two new ones. Then the 1287 // entire module is invalidated causing a full run over all seven. Then we 1288 // fold three SCCs back to one, re-compute for it and the two SCCs above it 1289 // in the graph, and then run over the whole module again. 1290 EXPECT_EQ(4 + 2 + 7 + 1 + 3 + 4, IndirectSCCAnalysisRuns); 1291 EXPECT_EQ(4 + 2 + 7 + 1 + 3 + 4, DoublyIndirectSCCAnalysisRuns); 1292 1293 // First we run over all six functions. Then we re-run it over three when we 1294 // split their SCCs. Then we re-run over the whole module. Then we re-run 1295 // over three functions merged back into a single SCC, then those three 1296 // functions again, the two functions in SCCs above it in the graph, and then 1297 // over the whole module again. 1298 EXPECT_EQ(6 + 3 + 6 + 3 + 3 + 2 + 6, FunctionAnalysisRuns); 1299 1300 // Re run the function analysis over the entire module, and then re-run it 1301 // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over 1302 // the entire module, then the three functions merged back into a single SCC, 1303 // those three functions again, then the two functions in SCCs above it in 1304 // the graph, and then over the whole module. 1305 EXPECT_EQ(6 + 3 + 6 + 3 + 3 + 2 + 6, IndirectFunctionAnalysisRuns); 1306 } 1307 1308 // The (negative) tests below check for assertions so we only run them if NDEBUG 1309 // is not defined. 1310 #ifndef NDEBUG 1311 1312 struct LambdaSCCPassNoPreserve : public PassInfoMixin<LambdaSCCPassNoPreserve> { 1313 template <typename T> 1314 LambdaSCCPassNoPreserve(T &&Arg) : Func(std::forward<T>(Arg)) {} 1315 1316 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, 1317 LazyCallGraph &CG, CGSCCUpdateResult &UR) { 1318 Func(C, AM, CG, UR); 1319 PreservedAnalyses PA; 1320 // We update the core CGSCC data structures and so can preserve the proxy to 1321 // the function analysis manager. 1322 PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 1323 return PA; 1324 } 1325 1326 std::function<void(LazyCallGraph::SCC &, CGSCCAnalysisManager &, 1327 LazyCallGraph &, CGSCCUpdateResult &)> 1328 Func; 1329 }; 1330 1331 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses0) { 1332 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1333 CGPM.addPass(LambdaSCCPassNoPreserve( 1334 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, 1335 CGSCCUpdateResult &UR) { 1336 if (C.getName() != "(h3, h1, h2)") 1337 return; 1338 1339 Function *FnX = M->getFunction("x"); 1340 Function *FnH1 = M->getFunction("h1"); 1341 Function *FnH2 = M->getFunction("h2"); 1342 Function *FnH3 = M->getFunction("h3"); 1343 ASSERT_NE(FnX, nullptr); 1344 ASSERT_NE(FnH1, nullptr); 1345 ASSERT_NE(FnH2, nullptr); 1346 ASSERT_NE(FnH3, nullptr); 1347 1348 // And insert a call to `h1`, `h2`, and `h3`. 1349 Instruction *IP = &FnH2->getEntryBlock().front(); 1350 (void)CallInst::Create(FnH1, {}, "", IP); 1351 (void)CallInst::Create(FnH2, {}, "", IP); 1352 (void)CallInst::Create(FnH3, {}, "", IP); 1353 1354 auto &H2N = *llvm::find_if( 1355 C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; }); 1356 ASSERT_NO_FATAL_FAILURE( 1357 updateCGAndAnalysisManagerForCGSCCPass(CG, C, H2N, AM, UR)); 1358 })); 1359 1360 ModulePassManager MPM(/*DebugLogging*/ true); 1361 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1362 MPM.run(*M, MAM); 1363 } 1364 1365 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses1) { 1366 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1367 CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C, 1368 CGSCCAnalysisManager &AM, 1369 LazyCallGraph &CG, 1370 CGSCCUpdateResult &UR) { 1371 if (C.getName() != "(h3, h1, h2)") 1372 return; 1373 1374 Function *FnX = M->getFunction("x"); 1375 Function *FnH1 = M->getFunction("h1"); 1376 Function *FnH2 = M->getFunction("h2"); 1377 Function *FnH3 = M->getFunction("h3"); 1378 ASSERT_NE(FnX, nullptr); 1379 ASSERT_NE(FnH1, nullptr); 1380 ASSERT_NE(FnH2, nullptr); 1381 ASSERT_NE(FnH3, nullptr); 1382 1383 // And insert a call to `h1`, `h2`, and `h3`. 1384 Instruction *IP = &FnH2->getEntryBlock().front(); 1385 (void)CallInst::Create(FnH1, {}, "", IP); 1386 (void)CallInst::Create(FnH2, {}, "", IP); 1387 (void)CallInst::Create(FnH3, {}, "", IP); 1388 1389 auto &H2N = *llvm::find_if( 1390 C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; }); 1391 ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR), 1392 "Any new calls should be modeled as"); 1393 })); 1394 1395 ModulePassManager MPM(/*DebugLogging*/ true); 1396 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1397 MPM.run(*M, MAM); 1398 } 1399 1400 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses2) { 1401 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1402 CGPM.addPass(LambdaSCCPassNoPreserve( 1403 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, 1404 CGSCCUpdateResult &UR) { 1405 if (C.getName() != "(f)") 1406 return; 1407 1408 Function *FnF = M->getFunction("f"); 1409 Function *FnH2 = M->getFunction("h2"); 1410 ASSERT_NE(FnF, nullptr); 1411 ASSERT_NE(FnH2, nullptr); 1412 1413 // And insert a call to `h2` 1414 Instruction *IP = &FnF->getEntryBlock().front(); 1415 (void)CallInst::Create(FnH2, {}, "", IP); 1416 1417 auto &FN = *llvm::find_if( 1418 C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; }); 1419 ASSERT_NO_FATAL_FAILURE( 1420 updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR)); 1421 })); 1422 1423 ModulePassManager MPM(/*DebugLogging*/ true); 1424 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1425 MPM.run(*M, MAM); 1426 } 1427 1428 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses3) { 1429 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1430 CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C, 1431 CGSCCAnalysisManager &AM, 1432 LazyCallGraph &CG, 1433 CGSCCUpdateResult &UR) { 1434 if (C.getName() != "(f)") 1435 return; 1436 1437 Function *FnF = M->getFunction("f"); 1438 Function *FnH2 = M->getFunction("h2"); 1439 ASSERT_NE(FnF, nullptr); 1440 ASSERT_NE(FnH2, nullptr); 1441 1442 // And insert a call to `h2` 1443 Instruction *IP = &FnF->getEntryBlock().front(); 1444 (void)CallInst::Create(FnH2, {}, "", IP); 1445 1446 auto &FN = *llvm::find_if( 1447 C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; }); 1448 ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR), 1449 "Any new calls should be modeled as"); 1450 })); 1451 1452 ModulePassManager MPM(/*DebugLogging*/ true); 1453 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1454 MPM.run(*M, MAM); 1455 } 1456 1457 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses4) { 1458 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1459 CGPM.addPass(LambdaSCCPassNoPreserve( 1460 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, 1461 CGSCCUpdateResult &UR) { 1462 if (C.getName() != "(f)") 1463 return; 1464 1465 Function *FnF = M->getFunction("f"); 1466 Function *FnewF = Function::Create(FnF->getFunctionType(), 1467 FnF->getLinkage(), "newF", *M); 1468 BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF); 1469 ReturnInst::Create(FnewF->getContext(), BB); 1470 1471 // Use the CallGraphUpdater to update the call graph for the new 1472 // function. 1473 CallGraphUpdater CGU; 1474 CGU.initialize(CG, C, AM, UR); 1475 CGU.registerOutlinedFunction(*FnewF); 1476 1477 // And insert a call to `newF` 1478 Instruction *IP = &FnF->getEntryBlock().front(); 1479 (void)CallInst::Create(FnewF, {}, "", IP); 1480 1481 auto &FN = *llvm::find_if( 1482 C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; }); 1483 1484 ASSERT_NO_FATAL_FAILURE( 1485 updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR)); 1486 })); 1487 1488 ModulePassManager MPM(/*DebugLogging*/ true); 1489 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1490 MPM.run(*M, MAM); 1491 } 1492 1493 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses5) { 1494 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1495 CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C, 1496 CGSCCAnalysisManager &AM, 1497 LazyCallGraph &CG, 1498 CGSCCUpdateResult &UR) { 1499 if (C.getName() != "(f)") 1500 return; 1501 1502 Function *FnF = M->getFunction("f"); 1503 Function *FnewF = 1504 Function::Create(FnF->getFunctionType(), FnF->getLinkage(), "newF", *M); 1505 BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF); 1506 ReturnInst::Create(FnewF->getContext(), BB); 1507 1508 // Use the CallGraphUpdater to update the call graph for the new 1509 // function. 1510 CallGraphUpdater CGU; 1511 CGU.initialize(CG, C, AM, UR); 1512 CGU.registerOutlinedFunction(*FnewF); 1513 1514 // And insert a call to `newF` 1515 Instruction *IP = &FnF->getEntryBlock().front(); 1516 (void)CallInst::Create(FnewF, {}, "", IP); 1517 1518 auto &FN = *llvm::find_if( 1519 C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; }); 1520 1521 ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR), 1522 "Any new calls should be modeled as"); 1523 })); 1524 1525 ModulePassManager MPM(/*DebugLogging*/ true); 1526 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1527 MPM.run(*M, MAM); 1528 } 1529 1530 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses6) { 1531 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1532 CGPM.addPass(LambdaSCCPassNoPreserve( 1533 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, 1534 CGSCCUpdateResult &UR) { 1535 if (C.getName() != "(h3, h1, h2)") 1536 return; 1537 1538 Function *FnX = M->getFunction("x"); 1539 Function *FnH1 = M->getFunction("h1"); 1540 Function *FnH2 = M->getFunction("h2"); 1541 Function *FnH3 = M->getFunction("h3"); 1542 ASSERT_NE(FnX, nullptr); 1543 ASSERT_NE(FnH1, nullptr); 1544 ASSERT_NE(FnH2, nullptr); 1545 ASSERT_NE(FnH3, nullptr); 1546 1547 // And insert a call to `h1`, `h2`, and `h3`. 1548 Instruction *IP = &FnH2->getEntryBlock().front(); 1549 (void)CallInst::Create(FnH1, {}, "", IP); 1550 (void)CallInst::Create(FnH2, {}, "", IP); 1551 (void)CallInst::Create(FnH3, {}, "", IP); 1552 1553 // Use the CallGraphUpdater to update the call graph for the new 1554 // function. 1555 CallGraphUpdater CGU; 1556 CGU.initialize(CG, C, AM, UR); 1557 ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnH2)); 1558 })); 1559 1560 ModulePassManager MPM(/*DebugLogging*/ true); 1561 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1562 MPM.run(*M, MAM); 1563 } 1564 1565 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses7) { 1566 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1567 CGPM.addPass(LambdaSCCPassNoPreserve( 1568 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, 1569 CGSCCUpdateResult &UR) { 1570 if (C.getName() != "(f)") 1571 return; 1572 1573 Function *FnF = M->getFunction("f"); 1574 Function *FnH2 = M->getFunction("h2"); 1575 ASSERT_NE(FnF, nullptr); 1576 ASSERT_NE(FnH2, nullptr); 1577 1578 // And insert a call to `h2` 1579 Instruction *IP = &FnF->getEntryBlock().front(); 1580 (void)CallInst::Create(FnH2, {}, "", IP); 1581 1582 // Use the CallGraphUpdater to update the call graph for the new 1583 // function. 1584 CallGraphUpdater CGU; 1585 CGU.initialize(CG, C, AM, UR); 1586 ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnF)); 1587 })); 1588 1589 ModulePassManager MPM(/*DebugLogging*/ true); 1590 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1591 MPM.run(*M, MAM); 1592 } 1593 1594 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses8) { 1595 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1596 CGPM.addPass(LambdaSCCPassNoPreserve( 1597 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, 1598 CGSCCUpdateResult &UR) { 1599 if (C.getName() != "(f)") 1600 return; 1601 1602 Function *FnF = M->getFunction("f"); 1603 Function *FnewF = Function::Create(FnF->getFunctionType(), 1604 FnF->getLinkage(), "newF", *M); 1605 BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF); 1606 auto *RI = ReturnInst::Create(FnewF->getContext(), BB); 1607 while (FnF->getEntryBlock().size() > 1) 1608 FnF->getEntryBlock().front().moveBefore(RI); 1609 ASSERT_NE(FnF, nullptr); 1610 1611 // Use the CallGraphUpdater to update the call graph. 1612 CallGraphUpdater CGU; 1613 CGU.initialize(CG, C, AM, UR); 1614 ASSERT_NO_FATAL_FAILURE(CGU.replaceFunctionWith(*FnF, *FnewF)); 1615 ASSERT_TRUE(FnF->isDeclaration()); 1616 ASSERT_EQ(FnF->getNumUses(), 0U); 1617 })); 1618 1619 ModulePassManager MPM(/*DebugLogging*/ true); 1620 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1621 MPM.run(*M, MAM); 1622 } 1623 1624 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses9) { 1625 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1626 CGPM.addPass(LambdaSCCPassNoPreserve( 1627 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, 1628 CGSCCUpdateResult &UR) { 1629 if (C.getName() != "(f)") 1630 return; 1631 1632 Function *FnF = M->getFunction("f"); 1633 1634 // Use the CallGraphUpdater to update the call graph. 1635 { 1636 CallGraphUpdater CGU; 1637 CGU.initialize(CG, C, AM, UR); 1638 ASSERT_NO_FATAL_FAILURE(CGU.removeFunction(*FnF)); 1639 ASSERT_EQ(M->getFunctionList().size(), 6U); 1640 } 1641 ASSERT_EQ(M->getFunctionList().size(), 5U); 1642 })); 1643 1644 ModulePassManager MPM(/*DebugLogging*/ true); 1645 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1646 MPM.run(*M, MAM); 1647 } 1648 1649 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses10) { 1650 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1651 CGPM.addPass(LambdaSCCPassNoPreserve( 1652 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, 1653 CGSCCUpdateResult &UR) { 1654 if (C.getName() != "(h3, h1, h2)") 1655 return; 1656 1657 Function *FnX = M->getFunction("x"); 1658 Function *FnH1 = M->getFunction("h1"); 1659 Function *FnH2 = M->getFunction("h2"); 1660 Function *FnH3 = M->getFunction("h3"); 1661 ASSERT_NE(FnX, nullptr); 1662 ASSERT_NE(FnH1, nullptr); 1663 ASSERT_NE(FnH2, nullptr); 1664 ASSERT_NE(FnH3, nullptr); 1665 1666 // And insert a call to `h1`, and `h3`. 1667 Instruction *IP = &FnH1->getEntryBlock().front(); 1668 (void)CallInst::Create(FnH1, {}, "", IP); 1669 (void)CallInst::Create(FnH3, {}, "", IP); 1670 1671 // Remove the `h2` call. 1672 ASSERT_TRUE(isa<CallBase>(IP)); 1673 ASSERT_EQ(cast<CallBase>(IP)->getCalledFunction(), FnH2); 1674 IP->eraseFromParent(); 1675 1676 // Use the CallGraphUpdater to update the call graph. 1677 CallGraphUpdater CGU; 1678 CGU.initialize(CG, C, AM, UR); 1679 ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnH1)); 1680 ASSERT_NO_FATAL_FAILURE(CGU.removeFunction(*FnH2)); 1681 })); 1682 1683 ModulePassManager MPM(/*DebugLogging*/ true); 1684 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1685 MPM.run(*M, MAM); 1686 } 1687 1688 TEST_F(CGSCCPassManagerTest, TestInsertionOfNewRefSCC) { 1689 std::unique_ptr<Module> M = parseIR("define void @f() {\n" 1690 "entry:\n" 1691 " call void @f()\n" 1692 " ret void\n" 1693 "}\n"); 1694 1695 CGSCCPassManager CGPM(/*DebugLogging*/ true); 1696 CGPM.addPass(LambdaSCCPassNoPreserve( 1697 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, 1698 CGSCCUpdateResult &UR) { 1699 for (auto &N : C) { 1700 auto &F = N.getFunction(); 1701 if (F.getName() != "f") 1702 continue; 1703 auto *Call = dyn_cast<CallInst>(F.begin()->begin()); 1704 if (!Call || Call->getCalledFunction()->getName() != "f") 1705 continue; 1706 1707 // Create a new function 'g'. 1708 auto *G = Function::Create(F.getFunctionType(), F.getLinkage(), 1709 F.getAddressSpace(), "g", F.getParent()); 1710 BasicBlock::Create(F.getParent()->getContext(), "entry", G); 1711 // Instruct the LazyCallGraph to create a new node for 'g', as the 1712 // single node in a new SCC, into the call graph. As a result 1713 // the call graph is composed of a single RefSCC with two SCCs: 1714 // [(f), (g)]. 1715 CG.addNewFunctionIntoRefSCC(*G, C.getOuterRefSCC()); 1716 1717 // "Demote" the 'f -> f' call egde to a ref edge. 1718 // 1. Erase the call edge from 'f' to 'f'. 1719 Call->eraseFromParent(); 1720 // 2. Insert a ref edge from 'f' to 'f'. 1721 (void)CastInst::CreatePointerCast(&F, 1722 Type::getInt8PtrTy(F.getContext()), 1723 "f.ref", &*F.begin()->begin()); 1724 1725 ASSERT_NO_FATAL_FAILURE( 1726 updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR)) 1727 << "Updating the call graph with a demoted, self-referential " 1728 "call edge 'f -> f', and a newly inserted ref edge 'f -> g', " 1729 "caused a fatal failure"; 1730 } 1731 })); 1732 1733 ModulePassManager MPM(/*DebugLogging*/ true); 1734 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1735 MPM.run(*M, MAM); 1736 } 1737 1738 #endif 1739 } // namespace 1740