Fix test failures introduced by PR #113697 (#116941)
[llvm-project.git] / llvm / unittests / IR / PassManagerTest.cpp
bloba6487169224c2bd15b525368735d42f2d114e3e4
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 //===----------------------------------------------------------------------===//
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"
23 using namespace llvm;
25 namespace {
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>>());
41 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
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);
54 private:
55 friend AnalysisInfoMixin<TestFunctionAnalysis>;
56 static AnalysisKey Key;
58 int &Runs;
61 AnalysisKey TestFunctionAnalysis::Key;
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>>());
77 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
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);
87 private:
88 friend AnalysisInfoMixin<TestModuleAnalysis>;
89 static AnalysisKey Key;
91 int &Runs;
94 AnalysisKey TestModuleAnalysis::Key;
96 struct TestModulePass : PassInfoMixin<TestModulePass> {
97 TestModulePass(int &RunCount) : RunCount(RunCount) {}
99 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
100 ++RunCount;
101 return PreservedAnalyses::none();
104 int &RunCount;
107 struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> {
108 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
109 return PreservedAnalyses::all();
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) {}
121 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
122 ++RunCount;
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;
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;
144 return PreservedAnalyses::all();
147 int &RunCount;
148 int &AnalyzedInstrCount;
149 int &AnalyzedFunctionCount;
150 ModuleAnalysisManager &MAM;
151 bool OnlyUseCachedResults;
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) {}
160 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
161 return F.getName() == Name ? PreservedAnalyses::none()
162 : PreservedAnalyses::all();
165 StringRef Name;
168 std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
169 SMDiagnostic Err;
170 return parseAssemblyString(IR, Err, Context);
173 class PassManagerTest : public ::testing::Test {
174 protected:
175 LLVMContext Context;
176 std::unique_ptr<Module> M;
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")) {}
194 TEST(PreservedAnalysesTest, Basic) {
195 PreservedAnalyses PA1 = PreservedAnalyses();
197 auto PAC = PA1.getChecker<TestFunctionAnalysis>();
198 EXPECT_FALSE(PAC.preserved());
199 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
202 auto PAC = PA1.getChecker<TestModuleAnalysis>();
203 EXPECT_FALSE(PAC.preserved());
204 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Module>>());
206 auto PA2 = PreservedAnalyses::none();
208 auto PAC = PA2.getChecker<TestFunctionAnalysis>();
209 EXPECT_FALSE(PAC.preserved());
210 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
212 auto PA3 = PreservedAnalyses::all();
214 auto PAC = PA3.getChecker<TestFunctionAnalysis>();
215 EXPECT_TRUE(PAC.preserved());
216 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>());
218 PreservedAnalyses PA4 = PA1;
220 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
221 EXPECT_FALSE(PAC.preserved());
222 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
224 PA4 = PA3;
226 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
227 EXPECT_TRUE(PAC.preserved());
228 EXPECT_TRUE(PAC.preservedSet<AllAnalysesOn<Function>>());
230 PA4 = std::move(PA2);
232 auto PAC = PA4.getChecker<TestFunctionAnalysis>();
233 EXPECT_FALSE(PAC.preserved());
234 EXPECT_FALSE(PAC.preservedSet<AllAnalysesOn<Function>>());
236 auto PA5 = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();
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>>());
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());
254 // Redundant calls are fine.
255 PA.preserve<TestFunctionAnalysis>();
256 EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
257 EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved());
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>>());
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>>());
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>>());
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>>();
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>>());
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>>());
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>>());
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>>());
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>>());
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>>());
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>>());
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>>());
390 TEST(PreservedAnalysisTest, Abandon) {
391 auto PA = PreservedAnalyses::none();
393 // We can abandon things after they are preserved.
394 PA.preserve<TestFunctionAnalysis>();
395 PA.abandon<TestFunctionAnalysis>();
396 EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved());
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());
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>>());
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>>());
421 TEST_F(PassManagerTest, Basic) {
422 FunctionAnalysisManager FAM;
423 int FunctionAnalysisRuns = 0;
424 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
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); });
432 MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
433 FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
435 ModulePassManager MPM;
437 // Count the runs over a Function.
438 int FunctionPassRunCount1 = 0;
439 int AnalyzedInstrCount1 = 0;
440 int AnalyzedFunctionCount1 = 0;
442 // Pointless scoped copy to test move assignment.
443 ModulePassManager NestedMPM;
444 FunctionPassManager FPM;
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);
453 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
454 MPM = std::move(NestedMPM);
457 // Count the runs over a module.
458 int ModulePassRunCount = 0;
459 MPM.addPass(TestModulePass(ModulePassRunCount));
461 // Count the runs over a Function in a separate manager.
462 int FunctionPassRunCount2 = 0;
463 int AnalyzedInstrCount2 = 0;
464 int AnalyzedFunctionCount2 = 0;
466 FunctionPassManager FPM;
467 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
468 AnalyzedFunctionCount2, MAM));
469 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
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;
479 FunctionPassManager FPM;
480 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
481 AnalyzedFunctionCount3, MAM));
482 FPM.addPass(TestInvalidationFunctionPass("f"));
483 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
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;
493 FunctionPassManager FPM;
494 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
495 AnalyzedFunctionCount4, MAM));
496 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
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;
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)));
513 MPM.run(*M, MAM);
515 // Validate module pass counters.
516 EXPECT_EQ(1, ModulePassRunCount);
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);
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);
543 EXPECT_EQ(1, ModuleAnalysisRuns);
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;
552 class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> {
553 public:
554 struct Result {
555 Result(int I) : I(I) {}
556 int I;
559 Result run(Function &F, CustomizedAnalysisManager &AM, int I) {
560 return Result(I);
563 private:
564 friend AnalysisInfoMixin<CustomizedAnalysis>;
565 static AnalysisKey Key;
568 AnalysisKey CustomizedAnalysis::Key;
570 struct CustomizedPass : PassInfoMixin<CustomizedPass> {
571 std::function<void(CustomizedAnalysis::Result &, int &)> Callback;
573 template <typename CallbackT>
574 CustomizedPass(CallbackT Callback) : Callback(Callback) {}
576 PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I,
577 int &O) {
578 Callback(AM.getResult<CustomizedAnalysis>(F, I), O);
579 return PreservedAnalyses::none();
583 TEST_F(PassManagerTest, CustomizedPassManagerArgs) {
584 CustomizedAnalysisManager AM;
585 AM.registerPass([&] { return CustomizedAnalysis(); });
586 PassInstrumentationCallbacks PIC;
587 AM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
589 CustomizedPassManager PM;
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; }));
597 // Run this over every function with the input of 42.
598 for (Function &F : *M)
599 PM.run(F, AM, 42, Result);
601 // And ensure that we accumulated the correct result.
602 EXPECT_EQ(42 * (int)M->size(), Result);
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;
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);
625 TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM)
626 : Runs(Runs), MAM(MAM) {}
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);
644 private:
645 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
646 static AnalysisKey Key;
648 int &Runs;
649 ModuleAnalysisManager &MAM;
652 AnalysisKey TestIndirectFunctionAnalysis::Key;
654 /// A test analysis pass which chaches in its result the result from the above
655 /// indirect analysis pass.
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;
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);
676 TestDoublyIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
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);
685 private:
686 friend AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis>;
687 static AnalysisKey Key;
689 int &Runs;
692 AnalysisKey TestDoublyIndirectFunctionAnalysis::Key;
694 struct LambdaPass : public PassInfoMixin<LambdaPass> {
695 using FuncT = std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)>;
697 LambdaPass(FuncT Func) : Func(std::move(Func)) {}
699 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
700 return Func(F, AM);
703 FuncT Func;
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);
718 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
719 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
720 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
722 PassInstrumentationCallbacks PIC;
723 MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
724 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
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 }));
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 }));
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);
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);
802 // There are five instructions in the module and we add the count four
803 // times.
804 EXPECT_EQ(5 * 4, InstrCount);
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);
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");
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(); });
839 FPM.addPass(SimplifyCFGPass());
840 FPM.run(*F, FAM);
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();
855 SimplifyCFGPass CFGSimplifier;
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");
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(); });
888 FPM.addPass(TestSimplifyCFGInvalidatingAnalysisPass());
889 FPM.run(*F, FAM);
892 // Wrap a FunctionPassManager running SimplifyCFG pass with another
893 // FunctionPassManager.
894 struct TestSimplifyCFGWrapperPass : PassInfoMixin<TestSimplifyCFGWrapperPass> {
895 TestSimplifyCFGWrapperPass(FunctionPassManager &InnerPM) : InnerPM(InnerPM) {}
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);
904 if (!PI.runBeforePass<Function>(InnerPM, F))
905 return PreservedAnalyses::all();
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;
915 FunctionPassManager &InnerPM;
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");
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(); });
956 FunctionPassManager InnerFPM;
957 InnerFPM.addPass(SimplifyCFGPass());
959 FPM.addPass(TestSimplifyCFGWrapperPass(InnerFPM));
960 FPM.run(*F, FAM);
963 #ifdef EXPENSIVE_CHECKS
965 struct WrongFunctionPass : PassInfoMixin<WrongFunctionPass> {
966 PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
967 F.getEntryBlock().begin()->eraseFromParent();
968 return PreservedAnalyses::all();
970 static StringRef name() { return "WrongFunctionPass"; }
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");
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 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
990 FunctionPassManager FPM;
991 FPM.addPass(WrongFunctionPass());
993 auto *F = M->getFunction("foo");
994 EXPECT_DEATH(FPM.run(*F, FAM), "Function @foo changed by WrongFunctionPass without invalidating analyses");
997 struct WrongModulePass : PassInfoMixin<WrongModulePass> {
998 PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM) {
999 for (Function &F : M)
1000 F.getEntryBlock().begin()->eraseFromParent();
1002 PreservedAnalyses PA;
1003 PA.preserveSet<AllAnalysesOn<Function>>();
1004 PA.preserve<FunctionAnalysisManagerModuleProxy>();
1005 return PA;
1007 static StringRef name() { return "WrongModulePass"; }
1010 TEST_F(PassManagerTest, ModulePassMissedFunctionAnalysisInvalidation) {
1011 LLVMContext Context;
1012 auto M = parseIR(Context, "define void @foo() {\n"
1013 " %a = add i32 0, 0\n"
1014 " ret void\n"
1015 "}\n");
1017 FunctionAnalysisManager FAM;
1018 ModuleAnalysisManager MAM;
1019 PassInstrumentationCallbacks PIC;
1020 StandardInstrumentations SI(M->getContext(), /*DebugLogging*/ false);
1021 SI.registerCallbacks(PIC, &MAM);
1022 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
1023 MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
1024 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
1025 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
1027 ModulePassManager MPM;
1028 MPM.addPass(WrongModulePass());
1030 EXPECT_DEATH(
1031 MPM.run(*M, MAM),
1032 "Function @foo changed by WrongModulePass without invalidating analyses");
1035 struct WrongModulePass2 : PassInfoMixin<WrongModulePass2> {
1036 PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM) {
1037 for (Function &F : M)
1038 F.getEntryBlock().begin()->eraseFromParent();
1040 PreservedAnalyses PA;
1041 PA.preserveSet<AllAnalysesOn<Module>>();
1042 PA.abandon<FunctionAnalysisManagerModuleProxy>();
1043 return PA;
1045 static StringRef name() { return "WrongModulePass2"; }
1048 TEST_F(PassManagerTest, ModulePassMissedModuleAnalysisInvalidation) {
1049 LLVMContext Context;
1050 auto M = parseIR(Context, "define void @foo() {\n"
1051 " %a = add i32 0, 0\n"
1052 " ret void\n"
1053 "}\n");
1055 FunctionAnalysisManager FAM;
1056 ModuleAnalysisManager MAM;
1057 PassInstrumentationCallbacks PIC;
1058 StandardInstrumentations SI(M->getContext(), /*DebugLogging*/ false);
1059 SI.registerCallbacks(PIC, &MAM);
1060 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
1061 MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
1062 FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
1063 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
1065 ModulePassManager MPM;
1066 MPM.addPass(WrongModulePass2());
1068 EXPECT_DEATH(
1069 MPM.run(*M, MAM),
1070 "Module changed by WrongModulePass2 without invalidating analyses");
1073 #endif