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