1 //===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===// 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/IR/PassManager.h" 10 #include "llvm/Analysis/AssumptionCache.h" 11 #include "llvm/Analysis/TargetTransformInfo.h" 12 #include "llvm/AsmParser/Parser.h" 13 #include "llvm/IR/Function.h" 14 #include "llvm/IR/LLVMContext.h" 15 #include "llvm/IR/Module.h" 16 #include "llvm/IR/PassManagerImpl.h" 17 #include "llvm/Passes/StandardInstrumentations.h" 18 #include "llvm/Support/SourceMgr.h" 19 #include "llvm/Transforms/Scalar/SimplifyCFG.h" 20 #include "gtest/gtest.h" 21 22 using namespace llvm; 23 24 namespace { 25 26 class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> { 27 public: 28 struct Result { 29 Result(int Count) : InstructionCount(Count) {} 30 int InstructionCount; 31 bool invalidate(Function &, const PreservedAnalyses &PA, 32 FunctionAnalysisManager::Invalidator &) { 33 // Check whether the analysis or all analyses on functions have been 34 // preserved. 35 auto PAC = PA.getChecker<TestFunctionAnalysis>(); 36 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()); 37 } 38 }; 39 40 TestFunctionAnalysis(int &Runs) : Runs(Runs) {} 41 42 /// Run the analysis pass over the function and return a result. 43 Result run(Function &F, FunctionAnalysisManager &AM) { 44 ++Runs; 45 int Count = 0; 46 for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) 47 for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; 48 ++II) 49 ++Count; 50 return Result(Count); 51 } 52 53 private: 54 friend AnalysisInfoMixin<TestFunctionAnalysis>; 55 static AnalysisKey Key; 56 57 int &Runs; 58 }; 59 60 AnalysisKey TestFunctionAnalysis::Key; 61 62 class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> { 63 public: 64 struct Result { 65 Result(int Count) : FunctionCount(Count) {} 66 int FunctionCount; 67 bool invalidate(Module &, const PreservedAnalyses &PA, 68 ModuleAnalysisManager::Invalidator &) { 69 // Check whether the analysis or all analyses on modules have been 70 // preserved. 71 auto PAC = PA.getChecker<TestModuleAnalysis>(); 72 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>()); 73 } 74 }; 75 76 TestModuleAnalysis(int &Runs) : Runs(Runs) {} 77 78 Result run(Module &M, ModuleAnalysisManager &AM) { 79 ++Runs; 80 int Count = 0; 81 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) 82 ++Count; 83 return Result(Count); 84 } 85 86 private: 87 friend AnalysisInfoMixin<TestModuleAnalysis>; 88 static AnalysisKey Key; 89 90 int &Runs; 91 }; 92 93 AnalysisKey TestModuleAnalysis::Key; 94 95 struct TestModulePass : PassInfoMixin<TestModulePass> { 96 TestModulePass(int &RunCount) : RunCount(RunCount) {} 97 98 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) { 99 ++RunCount; 100 return PreservedAnalyses::none(); 101 } 102 103 int &RunCount; 104 }; 105 106 struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> { 107 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) { 108 return PreservedAnalyses::all(); 109 } 110 }; 111 112 struct TestFunctionPass : PassInfoMixin<TestFunctionPass> { 113 TestFunctionPass(int &RunCount, int &AnalyzedInstrCount, 114 int &AnalyzedFunctionCount, ModuleAnalysisManager &MAM, 115 bool OnlyUseCachedResults = false) 116 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount), 117 AnalyzedFunctionCount(AnalyzedFunctionCount), MAM(MAM), 118 OnlyUseCachedResults(OnlyUseCachedResults) {} 119 120 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { 121 ++RunCount; 122 123 // Getting a cached result that isn't stateless through the proxy will 124 // trigger an assert: 125 // auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F); 126 // Use MAM, for the purposes of this unittest. 127 if (TestModuleAnalysis::Result *TMA = 128 MAM.getCachedResult<TestModuleAnalysis>(*F.getParent())) { 129 AnalyzedFunctionCount += TMA->FunctionCount; 130 } 131 132 if (OnlyUseCachedResults) { 133 // Hack to force the use of the cached interface. 134 if (TestFunctionAnalysis::Result *AR = 135 AM.getCachedResult<TestFunctionAnalysis>(F)) 136 AnalyzedInstrCount += AR->InstructionCount; 137 } else { 138 // Typical path just runs the analysis as needed. 139 TestFunctionAnalysis::Result &AR = AM.getResult<TestFunctionAnalysis>(F); 140 AnalyzedInstrCount += AR.InstructionCount; 141 } 142 143 return PreservedAnalyses::all(); 144 } 145 146 int &RunCount; 147 int &AnalyzedInstrCount; 148 int &AnalyzedFunctionCount; 149 ModuleAnalysisManager &MAM; 150 bool OnlyUseCachedResults; 151 }; 152 153 // A test function pass that invalidates all function analyses for a function 154 // with a specific name. 155 struct TestInvalidationFunctionPass 156 : PassInfoMixin<TestInvalidationFunctionPass> { 157 TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {} 158 159 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { 160 return F.getName() == Name ? PreservedAnalyses::none() 161 : PreservedAnalyses::all(); 162 } 163 164 StringRef Name; 165 }; 166 167 std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) { 168 SMDiagnostic Err; 169 return parseAssemblyString(IR, Err, Context); 170 } 171 172 class PassManagerTest : public ::testing::Test { 173 protected: 174 LLVMContext Context; 175 std::unique_ptr<Module> M; 176 177 public: 178 PassManagerTest() 179 : M(parseIR(Context, "define void @f() {\n" 180 "entry:\n" 181 " call void @g()\n" 182 " call void @h()\n" 183 " ret void\n" 184 "}\n" 185 "define void @g() {\n" 186 " ret void\n" 187 "}\n" 188 "define void @h() {\n" 189 " ret void\n" 190 "}\n")) {} 191 }; 192 193 TEST(PreservedAnalysesTest, Basic) { 194 PreservedAnalyses PA1 = PreservedAnalyses(); 195 { 196 auto PAC = PA1.getChecker<TestFunctionAnalysis>(); 197 EXPECT_FALSE(PAC.preserved()); 198 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>()); 199 } 200 { 201 auto PAC = PA1.getChecker<TestModuleAnalysis>(); 202 EXPECT_FALSE(PAC.preserved()); 203 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Module>>()); 204 } 205 auto PA2 = PreservedAnalyses::none(); 206 { 207 auto PAC = PA2.getChecker<TestFunctionAnalysis>(); 208 EXPECT_FALSE(PAC.preserved()); 209 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>()); 210 } 211 auto PA3 = PreservedAnalyses::all(); 212 { 213 auto PAC = PA3.getChecker<TestFunctionAnalysis>(); 214 EXPECT_TRUE(PAC.preserved()); 215 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>()); 216 } 217 PreservedAnalyses PA4 = PA1; 218 { 219 auto PAC = PA4.getChecker<TestFunctionAnalysis>(); 220 EXPECT_FALSE(PAC.preserved()); 221 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>()); 222 } 223 PA4 = PA3; 224 { 225 auto PAC = PA4.getChecker<TestFunctionAnalysis>(); 226 EXPECT_TRUE(PAC.preserved()); 227 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>()); 228 } 229 PA4 = std::move(PA2); 230 { 231 auto PAC = PA4.getChecker<TestFunctionAnalysis>(); 232 EXPECT_FALSE(PAC.preserved()); 233 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>()); 234 } 235 auto PA5 = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>(); 236 { 237 auto PAC = PA5.getChecker<TestFunctionAnalysis>(); 238 EXPECT_FALSE(PAC.preserved()); 239 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>()); 240 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Module>>()); 241 } 242 } 243 244 TEST(PreservedAnalysesTest, Preserve) { 245 auto PA = PreservedAnalyses::none(); 246 PA.preserve<TestFunctionAnalysis>(); 247 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved()); 248 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>().preserved()); 249 PA.preserve<TestModuleAnalysis>(); 250 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved()); 251 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved()); 252 253 // Redundant calls are fine. 254 PA.preserve<TestFunctionAnalysis>(); 255 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved()); 256 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved()); 257 } 258 259 TEST(PreservedAnalysesTest, PreserveSets) { 260 auto PA = PreservedAnalyses::none(); 261 PA.preserveSet<AllAnalysesOn<Function>>(); 262 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>() 263 .preservedSet<AllAnalysesOn<Function>>()); 264 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>() 265 .preservedSet<AllAnalysesOn<Module>>()); 266 PA.preserveSet<AllAnalysesOn<Module>>(); 267 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>() 268 .preservedSet<AllAnalysesOn<Function>>()); 269 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>() 270 .preservedSet<AllAnalysesOn<Module>>()); 271 272 // Mixing is fine. 273 PA.preserve<TestFunctionAnalysis>(); 274 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>() 275 .preservedSet<AllAnalysesOn<Function>>()); 276 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>() 277 .preservedSet<AllAnalysesOn<Module>>()); 278 279 // Redundant calls are fine. 280 PA.preserveSet<AllAnalysesOn<Module>>(); 281 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>() 282 .preservedSet<AllAnalysesOn<Function>>()); 283 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>() 284 .preservedSet<AllAnalysesOn<Module>>()); 285 } 286 287 TEST(PreservedAnalysisTest, Intersect) { 288 // Setup the initial sets. 289 auto PA1 = PreservedAnalyses::none(); 290 PA1.preserve<TestFunctionAnalysis>(); 291 PA1.preserveSet<AllAnalysesOn<Module>>(); 292 auto PA2 = PreservedAnalyses::none(); 293 PA2.preserve<TestFunctionAnalysis>(); 294 PA2.preserveSet<AllAnalysesOn<Function>>(); 295 PA2.preserve<TestModuleAnalysis>(); 296 PA2.preserveSet<AllAnalysesOn<Module>>(); 297 auto PA3 = PreservedAnalyses::none(); 298 PA3.preserve<TestModuleAnalysis>(); 299 PA3.preserveSet<AllAnalysesOn<Function>>(); 300 301 // Self intersection is a no-op. 302 auto Intersected = PA1; 303 Intersected.intersect(PA1); 304 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 305 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 306 .preservedSet<AllAnalysesOn<Function>>()); 307 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 308 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 309 .preservedSet<AllAnalysesOn<Module>>()); 310 311 // Intersecting with all is a no-op. 312 Intersected.intersect(PreservedAnalyses::all()); 313 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 314 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 315 .preservedSet<AllAnalysesOn<Function>>()); 316 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 317 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 318 .preservedSet<AllAnalysesOn<Module>>()); 319 320 // Intersecting a narrow set with a more broad set is the narrow set. 321 Intersected.intersect(PA2); 322 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 323 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 324 .preservedSet<AllAnalysesOn<Function>>()); 325 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 326 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 327 .preservedSet<AllAnalysesOn<Module>>()); 328 329 // Intersecting a broad set with a more narrow set is the narrow set. 330 Intersected = PA2; 331 Intersected.intersect(PA1); 332 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 333 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 334 .preservedSet<AllAnalysesOn<Function>>()); 335 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 336 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 337 .preservedSet<AllAnalysesOn<Module>>()); 338 339 // Intersecting with empty clears. 340 Intersected.intersect(PreservedAnalyses::none()); 341 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 342 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 343 .preservedSet<AllAnalysesOn<Function>>()); 344 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 345 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>() 346 .preservedSet<AllAnalysesOn<Module>>()); 347 348 // Intersecting non-overlapping clears. 349 Intersected = PA1; 350 Intersected.intersect(PA3); 351 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 352 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 353 .preservedSet<AllAnalysesOn<Function>>()); 354 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 355 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>() 356 .preservedSet<AllAnalysesOn<Module>>()); 357 358 // Intersecting with moves works in when there is storage on both sides. 359 Intersected = PA1; 360 auto Tmp = PA2; 361 Intersected.intersect(std::move(Tmp)); 362 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 363 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 364 .preservedSet<AllAnalysesOn<Function>>()); 365 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 366 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 367 .preservedSet<AllAnalysesOn<Module>>()); 368 369 // Intersecting with move works for incoming all and existing all. 370 auto Tmp2 = PreservedAnalyses::all(); 371 Intersected.intersect(std::move(Tmp2)); 372 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 373 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 374 .preservedSet<AllAnalysesOn<Function>>()); 375 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 376 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 377 .preservedSet<AllAnalysesOn<Module>>()); 378 Intersected = PreservedAnalyses::all(); 379 auto Tmp3 = PA1; 380 Intersected.intersect(std::move(Tmp3)); 381 EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved()); 382 EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>() 383 .preservedSet<AllAnalysesOn<Function>>()); 384 EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved()); 385 EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>() 386 .preservedSet<AllAnalysesOn<Module>>()); 387 } 388 389 TEST(PreservedAnalysisTest, Abandon) { 390 auto PA = PreservedAnalyses::none(); 391 392 // We can abandon things after they are preserved. 393 PA.preserve<TestFunctionAnalysis>(); 394 PA.abandon<TestFunctionAnalysis>(); 395 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved()); 396 397 // Repeated is fine, and abandoning if they were never preserved is fine. 398 PA.abandon<TestFunctionAnalysis>(); 399 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved()); 400 PA.abandon<TestModuleAnalysis>(); 401 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>().preserved()); 402 403 // Even if the sets are preserved, the abandoned analyses' checker won't 404 // return true for those sets. 405 PA.preserveSet<AllAnalysesOn<Function>>(); 406 PA.preserveSet<AllAnalysesOn<Module>>(); 407 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>() 408 .preservedSet<AllAnalysesOn<Function>>()); 409 EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>() 410 .preservedSet<AllAnalysesOn<Module>>()); 411 412 // But an arbitrary (opaque) analysis will still observe the sets as 413 // preserved. This also checks that we can use an explicit ID rather than 414 // a type. 415 AnalysisKey FakeKey, *FakeID = &FakeKey; 416 EXPECT_TRUE(PA.getChecker(FakeID).preservedSet<AllAnalysesOn<Function>>()); 417 EXPECT_TRUE(PA.getChecker(FakeID).preservedSet<AllAnalysesOn<Module>>()); 418 } 419 420 TEST_F(PassManagerTest, Basic) { 421 FunctionAnalysisManager FAM(/*DebugLogging*/ true); 422 int FunctionAnalysisRuns = 0; 423 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 424 425 ModuleAnalysisManager MAM(/*DebugLogging*/ true); 426 int ModuleAnalysisRuns = 0; 427 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 428 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); 429 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); 430 431 MAM.registerPass([&] { return PassInstrumentationAnalysis(); }); 432 FAM.registerPass([&] { return PassInstrumentationAnalysis(); }); 433 434 ModulePassManager MPM; 435 436 // Count the runs over a Function. 437 int FunctionPassRunCount1 = 0; 438 int AnalyzedInstrCount1 = 0; 439 int AnalyzedFunctionCount1 = 0; 440 { 441 // Pointless scoped copy to test move assignment. 442 ModulePassManager NestedMPM(/*DebugLogging*/ true); 443 FunctionPassManager FPM; 444 { 445 // Pointless scope to test move assignment. 446 FunctionPassManager NestedFPM(/*DebugLogging*/ true); 447 NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1, 448 AnalyzedInstrCount1, 449 AnalyzedFunctionCount1, MAM)); 450 FPM = std::move(NestedFPM); 451 } 452 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 453 MPM = std::move(NestedMPM); 454 } 455 456 // Count the runs over a module. 457 int ModulePassRunCount = 0; 458 MPM.addPass(TestModulePass(ModulePassRunCount)); 459 460 // Count the runs over a Function in a separate manager. 461 int FunctionPassRunCount2 = 0; 462 int AnalyzedInstrCount2 = 0; 463 int AnalyzedFunctionCount2 = 0; 464 { 465 FunctionPassManager FPM(/*DebugLogging*/ true); 466 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2, 467 AnalyzedFunctionCount2, MAM)); 468 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 469 } 470 471 // A third function pass manager but with only preserving intervening passes 472 // and with a function pass that invalidates exactly one analysis. 473 MPM.addPass(TestPreservingModulePass()); 474 int FunctionPassRunCount3 = 0; 475 int AnalyzedInstrCount3 = 0; 476 int AnalyzedFunctionCount3 = 0; 477 { 478 FunctionPassManager FPM(/*DebugLogging*/ true); 479 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3, 480 AnalyzedFunctionCount3, MAM)); 481 FPM.addPass(TestInvalidationFunctionPass("f")); 482 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 483 } 484 485 // A fourth function pass manager but with only preserving intervening 486 // passes but triggering the module analysis. 487 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 488 int FunctionPassRunCount4 = 0; 489 int AnalyzedInstrCount4 = 0; 490 int AnalyzedFunctionCount4 = 0; 491 { 492 FunctionPassManager FPM; 493 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4, 494 AnalyzedFunctionCount4, MAM)); 495 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 496 } 497 498 // A fifth function pass manager which invalidates one function first but 499 // uses only cached results. 500 int FunctionPassRunCount5 = 0; 501 int AnalyzedInstrCount5 = 0; 502 int AnalyzedFunctionCount5 = 0; 503 { 504 FunctionPassManager FPM(/*DebugLogging*/ true); 505 FPM.addPass(TestInvalidationFunctionPass("f")); 506 FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5, 507 AnalyzedFunctionCount5, MAM, 508 /*OnlyUseCachedResults=*/true)); 509 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 510 } 511 512 MPM.run(*M, MAM); 513 514 // Validate module pass counters. 515 EXPECT_EQ(1, ModulePassRunCount); 516 517 // Validate all function pass counter sets are the same. 518 EXPECT_EQ(3, FunctionPassRunCount1); 519 EXPECT_EQ(5, AnalyzedInstrCount1); 520 EXPECT_EQ(0, AnalyzedFunctionCount1); 521 EXPECT_EQ(3, FunctionPassRunCount2); 522 EXPECT_EQ(5, AnalyzedInstrCount2); 523 EXPECT_EQ(0, AnalyzedFunctionCount2); 524 EXPECT_EQ(3, FunctionPassRunCount3); 525 EXPECT_EQ(5, AnalyzedInstrCount3); 526 EXPECT_EQ(0, AnalyzedFunctionCount3); 527 EXPECT_EQ(3, FunctionPassRunCount4); 528 EXPECT_EQ(5, AnalyzedInstrCount4); 529 EXPECT_EQ(9, AnalyzedFunctionCount4); 530 EXPECT_EQ(3, FunctionPassRunCount5); 531 EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached. 532 EXPECT_EQ(9, AnalyzedFunctionCount5); 533 534 // Validate the analysis counters: 535 // first run over 3 functions, then module pass invalidates 536 // second run over 3 functions, nothing invalidates 537 // third run over 0 functions, but 1 function invalidated 538 // fourth run over 1 function 539 // fifth run invalidates 1 function first, but runs over 0 functions 540 EXPECT_EQ(7, FunctionAnalysisRuns); 541 542 EXPECT_EQ(1, ModuleAnalysisRuns); 543 } 544 545 // A customized pass manager that passes extra arguments through the 546 // infrastructure. 547 typedef AnalysisManager<Function, int> CustomizedAnalysisManager; 548 typedef PassManager<Function, CustomizedAnalysisManager, int, int &> 549 CustomizedPassManager; 550 551 class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> { 552 public: 553 struct Result { 554 Result(int I) : I(I) {} 555 int I; 556 }; 557 558 Result run(Function &F, CustomizedAnalysisManager &AM, int I) { 559 return Result(I); 560 } 561 562 private: 563 friend AnalysisInfoMixin<CustomizedAnalysis>; 564 static AnalysisKey Key; 565 }; 566 567 AnalysisKey CustomizedAnalysis::Key; 568 569 struct CustomizedPass : PassInfoMixin<CustomizedPass> { 570 std::function<void(CustomizedAnalysis::Result &, int &)> Callback; 571 572 template <typename CallbackT> 573 CustomizedPass(CallbackT Callback) : Callback(Callback) {} 574 575 PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I, 576 int &O) { 577 Callback(AM.getResult<CustomizedAnalysis>(F, I), O); 578 return PreservedAnalyses::none(); 579 } 580 }; 581 582 TEST_F(PassManagerTest, CustomizedPassManagerArgs) { 583 CustomizedAnalysisManager AM; 584 AM.registerPass([&] { return CustomizedAnalysis(); }); 585 PassInstrumentationCallbacks PIC; 586 AM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); 587 588 CustomizedPassManager PM; 589 590 // Add an instance of the customized pass that just accumulates the input 591 // after it is round-tripped through the analysis. 592 int Result = 0; 593 PM.addPass( 594 CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; })); 595 596 // Run this over every function with the input of 42. 597 for (Function &F : *M) 598 PM.run(F, AM, 42, Result); 599 600 // And ensure that we accumulated the correct result. 601 EXPECT_EQ(42 * (int)M->size(), Result); 602 } 603 604 /// A test analysis pass which caches in its result another analysis pass and 605 /// uses it to serve queries. This requires the result to invalidate itself 606 /// when its dependency is invalidated. 607 struct TestIndirectFunctionAnalysis 608 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> { 609 struct Result { 610 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep) 611 : FDep(FDep), MDep(MDep) {} 612 TestFunctionAnalysis::Result &FDep; 613 TestModuleAnalysis::Result &MDep; 614 615 bool invalidate(Function &F, const PreservedAnalyses &PA, 616 FunctionAnalysisManager::Invalidator &Inv) { 617 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>(); 618 return !(PAC.preserved() || 619 PAC.preservedSet<AllAnalysesOn<Function>>()) || 620 Inv.invalidate<TestFunctionAnalysis>(F, PA); 621 } 622 }; 623 624 TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM) 625 : Runs(Runs), MAM(MAM) {} 626 627 /// Run the analysis pass over the function and return a result. 628 Result run(Function &F, FunctionAnalysisManager &AM) { 629 ++Runs; 630 auto &FDep = AM.getResult<TestFunctionAnalysis>(F); 631 auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F); 632 // For the test, we insist that the module analysis starts off in the 633 // cache. Getting a cached result that isn't stateless trigger an assert. 634 // Use MAM, for the purposes of this unittest. 635 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); 636 // And register the dependency as module analysis dependencies have to be 637 // pre-registered on the proxy. 638 MAMProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis, 639 TestIndirectFunctionAnalysis>(); 640 return Result(FDep, MDep); 641 } 642 643 private: 644 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>; 645 static AnalysisKey Key; 646 647 int &Runs; 648 ModuleAnalysisManager &MAM; 649 }; 650 651 AnalysisKey TestIndirectFunctionAnalysis::Key; 652 653 /// A test analysis pass which chaches in its result the result from the above 654 /// indirect analysis pass. 655 /// 656 /// This allows us to ensure that whenever an analysis pass is invalidated due 657 /// to dependencies (especially dependencies across IR units that trigger 658 /// asynchronous invalidation) we correctly detect that this may in turn cause 659 /// other analysis to be invalidated. 660 struct TestDoublyIndirectFunctionAnalysis 661 : public AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis> { 662 struct Result { 663 Result(TestIndirectFunctionAnalysis::Result &IDep) : IDep(IDep) {} 664 TestIndirectFunctionAnalysis::Result &IDep; 665 666 bool invalidate(Function &F, const PreservedAnalyses &PA, 667 FunctionAnalysisManager::Invalidator &Inv) { 668 auto PAC = PA.getChecker<TestDoublyIndirectFunctionAnalysis>(); 669 return !(PAC.preserved() || 670 PAC.preservedSet<AllAnalysesOn<Function>>()) || 671 Inv.invalidate<TestIndirectFunctionAnalysis>(F, PA); 672 } 673 }; 674 675 TestDoublyIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {} 676 677 /// Run the analysis pass over the function and return a result. 678 Result run(Function &F, FunctionAnalysisManager &AM) { 679 ++Runs; 680 auto &IDep = AM.getResult<TestIndirectFunctionAnalysis>(F); 681 return Result(IDep); 682 } 683 684 private: 685 friend AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis>; 686 static AnalysisKey Key; 687 688 int &Runs; 689 }; 690 691 AnalysisKey TestDoublyIndirectFunctionAnalysis::Key; 692 693 struct LambdaPass : public PassInfoMixin<LambdaPass> { 694 using FuncT = std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)>; 695 696 LambdaPass(FuncT Func) : Func(std::move(Func)) {} 697 698 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { 699 return Func(F, AM); 700 } 701 702 FuncT Func; 703 }; 704 705 TEST_F(PassManagerTest, IndirectAnalysisInvalidation) { 706 FunctionAnalysisManager FAM(/*DebugLogging*/ true); 707 ModuleAnalysisManager MAM(/*DebugLogging*/ true); 708 int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0, 709 IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0; 710 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); 711 FAM.registerPass( 712 [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns, MAM); }); 713 FAM.registerPass([&] { 714 return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns); 715 }); 716 717 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); 718 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); 719 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); 720 721 PassInstrumentationCallbacks PIC; 722 MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); 723 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); 724 725 int InstrCount = 0, FunctionCount = 0; 726 ModulePassManager MPM(/*DebugLogging*/ true); 727 FunctionPassManager FPM(/*DebugLogging*/ true); 728 // First just use the analysis to get the instruction count, and preserve 729 // everything. 730 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 731 auto &DoublyIndirectResult = 732 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 733 auto &IndirectResult = DoublyIndirectResult.IDep; 734 InstrCount += IndirectResult.FDep.InstructionCount; 735 FunctionCount += IndirectResult.MDep.FunctionCount; 736 return PreservedAnalyses::all(); 737 })); 738 // Next, invalidate 739 // - both analyses for "f", 740 // - just the underlying (indirect) analysis for "g", and 741 // - just the direct analysis for "h". 742 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 743 auto &DoublyIndirectResult = 744 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 745 auto &IndirectResult = DoublyIndirectResult.IDep; 746 InstrCount += IndirectResult.FDep.InstructionCount; 747 FunctionCount += IndirectResult.MDep.FunctionCount; 748 auto PA = PreservedAnalyses::none(); 749 if (F.getName() == "g") 750 PA.preserve<TestFunctionAnalysis>(); 751 else if (F.getName() == "h") 752 PA.preserve<TestIndirectFunctionAnalysis>(); 753 return PA; 754 })); 755 // Finally, use the analysis again on each function, forcing re-computation 756 // for all of them. 757 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 758 auto &DoublyIndirectResult = 759 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 760 auto &IndirectResult = DoublyIndirectResult.IDep; 761 InstrCount += IndirectResult.FDep.InstructionCount; 762 FunctionCount += IndirectResult.MDep.FunctionCount; 763 return PreservedAnalyses::all(); 764 })); 765 766 // Create a second function pass manager. This will cause the module-level 767 // invalidation to occur, which will force yet another invalidation of the 768 // indirect function-level analysis as the module analysis it depends on gets 769 // invalidated. 770 FunctionPassManager FPM2(/*DebugLogging*/ true); 771 FPM2.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) { 772 auto &DoublyIndirectResult = 773 AM.getResult<TestDoublyIndirectFunctionAnalysis>(F); 774 auto &IndirectResult = DoublyIndirectResult.IDep; 775 InstrCount += IndirectResult.FDep.InstructionCount; 776 FunctionCount += IndirectResult.MDep.FunctionCount; 777 return PreservedAnalyses::all(); 778 })); 779 780 // Add a requires pass to populate the module analysis and then our function 781 // pass pipeline. 782 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 783 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 784 // Now require the module analysis again (it will have been invalidated once) 785 // and then use it again from a function pass manager. 786 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>()); 787 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2))); 788 MPM.run(*M, MAM); 789 790 // There are generally two possible runs for each of the three functions. But 791 // for one function, we only invalidate the indirect analysis so the base one 792 // only gets run five times. 793 EXPECT_EQ(5, FunctionAnalysisRuns); 794 // The module analysis pass should be run twice here. 795 EXPECT_EQ(2, ModuleAnalysisRuns); 796 // The indirect analysis is invalidated for each function (either directly or 797 // indirectly) and run twice for each. 798 EXPECT_EQ(9, IndirectAnalysisRuns); 799 EXPECT_EQ(9, DoublyIndirectAnalysisRuns); 800 801 // There are five instructions in the module and we add the count four 802 // times. 803 EXPECT_EQ(5 * 4, InstrCount); 804 805 // There are three functions and we count them four times for each of the 806 // three functions. 807 EXPECT_EQ(3 * 4 * 3, FunctionCount); 808 } 809 810 // Run SimplifyCFGPass that makes CFG changes and reports PreservedAnalyses 811 // without CFGAnalyses. So the CFGChecker does not complain. 812 TEST_F(PassManagerTest, FunctionPassCFGChecker) { 813 LLVMContext Context; 814 // SimplifyCFG changes this function to 815 // define void @foo {next: ret void} 816 auto M = parseIR(Context, "define void @foo() {\n" 817 " br label %next\n" 818 "next:\n" 819 " br label %exit\n" 820 "exit:\n" 821 " ret void\n" 822 "}\n"); 823 824 auto *F = M->getFunction("foo"); 825 FunctionAnalysisManager FAM(/*DebugLogging*/ true); 826 FunctionPassManager FPM(/*DebugLogging*/ true); 827 PassInstrumentationCallbacks PIC; 828 StandardInstrumentations SI(/*DebugLogging*/ true); 829 SI.registerCallbacks(PIC); 830 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); 831 FAM.registerPass([&] { return AssumptionAnalysis(); }); 832 FAM.registerPass([&] { return TargetIRAnalysis(); }); 833 834 FPM.addPass(SimplifyCFGPass()); 835 FPM.run(*F, FAM); 836 } 837 838 // FunctionPass that manually invalidates analyses and always returns 839 // PreservedAnalyses::all(). 840 struct TestSimplifyCFGInvalidatingAnalysisPass 841 : PassInfoMixin<TestSimplifyCFGInvalidatingAnalysisPass> { 842 PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) { 843 // Run SimplifyCFG and if it changes CFG then invalidate the CFG analysis. 844 // This allows to return PreserveAnalysis::all(). 845 PreservedAnalyses PA = CFGSimplifier.run(F, FAM); 846 FAM.invalidate(F, PA); 847 return PreservedAnalyses::all(); 848 } 849 850 SimplifyCFGPass CFGSimplifier; 851 }; 852 853 // Run TestSimplifyCFGInvalidatingAnalysisPass which changes CFG by running 854 // SimplifyCFGPass then manually invalidates analyses and always returns 855 // PreservedAnalyses::all(). CFGChecker does not complain because it resets 856 // its saved CFG snapshot when the analyses are invalidated manually. 857 TEST_F(PassManagerTest, FunctionPassCFGCheckerInvalidateAnalysis) { 858 LLVMContext Context; 859 // SimplifyCFG changes this function to 860 // define void @foo {next: ret void} 861 auto M = parseIR(Context, "define void @foo() {\n" 862 " br label %next\n" 863 "next:\n" 864 " br label %exit\n" 865 "exit:\n" 866 " ret void\n" 867 "}\n"); 868 869 auto *F = M->getFunction("foo"); 870 FunctionAnalysisManager FAM(/*DebugLogging*/ true); 871 FunctionPassManager FPM(/*DebugLogging*/ true); 872 PassInstrumentationCallbacks PIC; 873 StandardInstrumentations SI(/*DebugLogging*/ true); 874 SI.registerCallbacks(PIC); 875 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); 876 FAM.registerPass([&] { return AssumptionAnalysis(); }); 877 FAM.registerPass([&] { return TargetIRAnalysis(); }); 878 879 FPM.addPass(TestSimplifyCFGInvalidatingAnalysisPass()); 880 FPM.run(*F, FAM); 881 } 882 883 // Wrap a FunctionPassManager running SimplifyCFG pass with another 884 // FunctionPassManager. 885 struct TestSimplifyCFGWrapperPass : PassInfoMixin<TestSimplifyCFGWrapperPass> { 886 TestSimplifyCFGWrapperPass(FunctionPassManager &InnerPM) : InnerPM(InnerPM) {} 887 888 PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) { 889 // Here we simulate exactly what FunctionPassManager::run() does but 890 // instead of running all passes from InnerPM.Passes we run them in bulk 891 // by calling InnerPM.run(). 892 PreservedAnalyses PA = PreservedAnalyses::all(); 893 PassInstrumentation PI = FAM.getResult<PassInstrumentationAnalysis>(F); 894 895 if (!PI.runBeforePass<Function>(InnerPM, F)) 896 return PreservedAnalyses::all(); 897 898 PreservedAnalyses PassPA = InnerPM.run(F, FAM); 899 PI.runAfterPass(InnerPM, F, PassPA); 900 FAM.invalidate(F, PassPA); 901 PA.intersect(PassPA); 902 PA.preserveSet<AllAnalysesOn<Function>>(); 903 return PA; 904 } 905 906 FunctionPassManager &InnerPM; 907 }; 908 909 // Run TestSimplifyCFGWrapperPass which simulates behavior of 910 // FunctionPassManager::run() except that it runs all passes at once by calling 911 // an inner pass manager's passes with PassManager::run(). This is how one pass 912 // manager is expected to wrap another pass manager. 913 // SimplifyCFGPass, which is called by the inner pass manager, changes the CFG. 914 // The CFGChecker's AfterPassCallback, run right after SimplifyCFGPass, does not 915 // complain because CFGAnalyses is not in the PreservedAnalises set returned by 916 // SimplifyCFGPass. Then the CFG analysis is invalidated by the analysis manager 917 // according to the PreservedAnalises set. Further calls to CFGChecker's 918 // AfterPassCallback see that all analyses for the current function are 919 // preserved but there is no CFG snapshot available (i.e. 920 // AM.getCachedResult<PreservedCFGCheckerAnalysis>(F) returns nullptr). 921 TEST_F(PassManagerTest, FunctionPassCFGCheckerWrapped) { 922 LLVMContext Context; 923 // SimplifyCFG changes this function to 924 // define void @foo {next: ret void} 925 auto M = parseIR(Context, "define void @foo() {\n" 926 " br label %next\n" 927 "next:\n" 928 " br label %exit\n" 929 "exit:\n" 930 " ret void\n" 931 "}\n"); 932 933 auto *F = M->getFunction("foo"); 934 FunctionAnalysisManager FAM(/*DebugLogging*/ true); 935 FunctionPassManager FPM(/*DebugLogging*/ true); 936 PassInstrumentationCallbacks PIC; 937 StandardInstrumentations SI(/*DebugLogging*/ true); 938 SI.registerCallbacks(PIC); 939 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); 940 FAM.registerPass([&] { return AssumptionAnalysis(); }); 941 FAM.registerPass([&] { return TargetIRAnalysis(); }); 942 943 FunctionPassManager InnerFPM(/*DebugLogging*/ true); 944 InnerFPM.addPass(SimplifyCFGPass()); 945 946 FPM.addPass(TestSimplifyCFGWrapperPass(InnerFPM)); 947 FPM.run(*F, FAM); 948 } 949 } 950