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