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