xref: /llvm-project/llvm/unittests/IR/PassManagerTest.cpp (revision 55140fbbcd6527a3fe3636dda2078fe3652558ec)
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 {
Result__anon1d60355b0111::TestFunctionAnalysis::Result30     Result(int Count) : InstructionCount(Count) {}
31     int InstructionCount;
invalidate__anon1d60355b0111::TestFunctionAnalysis::Result32     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 
TestFunctionAnalysis(int & Runs)41   TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
42 
43   /// Run the analysis pass over the function and return a result.
run(Function & F,FunctionAnalysisManager & AM)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 {
Result__anon1d60355b0111::TestModuleAnalysis::Result66     Result(int Count) : FunctionCount(Count) {}
67     int FunctionCount;
invalidate__anon1d60355b0111::TestModuleAnalysis::Result68     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 
TestModuleAnalysis(int & Runs)77   TestModuleAnalysis(int &Runs) : Runs(Runs) {}
78 
run(Module & M,ModuleAnalysisManager & AM)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> {
TestModulePass__anon1d60355b0111::TestModulePass97   TestModulePass(int &RunCount) : RunCount(RunCount) {}
98 
run__anon1d60355b0111::TestModulePass99   PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
100     ++RunCount;
101     return PreservedAnalyses::none();
102   }
103 
104   int &RunCount;
105 };
106 
107 struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> {
run__anon1d60355b0111::TestPreservingModulePass108   PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
109     return PreservedAnalyses::all();
110   }
111 };
112 
113 struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
TestFunctionPass__anon1d60355b0111::TestFunctionPass114   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 
run__anon1d60355b0111::TestFunctionPass121   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> {
TestInvalidationFunctionPass__anon1d60355b0111::TestInvalidationFunctionPass158   TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
159 
run__anon1d60355b0111::TestInvalidationFunctionPass160   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
161     return F.getName() == Name ? PreservedAnalyses::none()
162                                : PreservedAnalyses::all();
163   }
164 
165   StringRef Name;
166 };
167 
parseIR(LLVMContext & Context,const char * IR)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:
PassManagerTest()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 
TEST(PreservedAnalysesTest,Basic)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 
TEST(PreservedAnalysesTest,Preserve)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 
TEST(PreservedAnalysesTest,PreserveSets)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 
TEST(PreservedAnalysisTest,Intersect)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 
TEST(PreservedAnalysisTest,Abandon)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 
TEST_F(PassManagerTest,Basic)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 {
Result__anon1d60355b0111::CustomizedAnalysis::Result555     Result(int I) : I(I) {}
556     int I;
557   };
558 
run(Function & F,CustomizedAnalysisManager & AM,int I)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>
CustomizedPass__anon1d60355b0111::CustomizedPass574   CustomizedPass(CallbackT Callback) : Callback(Callback) {}
575 
run__anon1d60355b0111::CustomizedPass576   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 
TEST_F(PassManagerTest,CustomizedPassManagerArgs)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 {
Result__anon1d60355b0111::TestIndirectFunctionAnalysis::Result611     Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep)
612         : FDep(FDep), MDep(MDep) {}
613     TestFunctionAnalysis::Result &FDep;
614     TestModuleAnalysis::Result &MDep;
615 
invalidate__anon1d60355b0111::TestIndirectFunctionAnalysis::Result616     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 
TestIndirectFunctionAnalysis__anon1d60355b0111::TestIndirectFunctionAnalysis625   TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM)
626       : Runs(Runs), MAM(MAM) {}
627 
628   /// Run the analysis pass over the function and return a result.
run__anon1d60355b0111::TestIndirectFunctionAnalysis629   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 {
Result__anon1d60355b0111::TestDoublyIndirectFunctionAnalysis::Result664     Result(TestIndirectFunctionAnalysis::Result &IDep) : IDep(IDep) {}
665     TestIndirectFunctionAnalysis::Result &IDep;
666 
invalidate__anon1d60355b0111::TestDoublyIndirectFunctionAnalysis::Result667     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 
TestDoublyIndirectFunctionAnalysis__anon1d60355b0111::TestDoublyIndirectFunctionAnalysis676   TestDoublyIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
677 
678   /// Run the analysis pass over the function and return a result.
run__anon1d60355b0111::TestDoublyIndirectFunctionAnalysis679   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 
LambdaPass__anon1d60355b0111::LambdaPass697   LambdaPass(FuncT Func) : Func(std::move(Func)) {}
698 
run__anon1d60355b0111::LambdaPass699   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
700     return Func(F, AM);
701   }
702 
703   FuncT Func;
704 };
705 
TEST_F(PassManagerTest,IndirectAnalysisInvalidation)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.
TEST_F(PassManagerTest,FunctionPassCFGChecker)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> {
run__anon1d60355b0111::TestSimplifyCFGInvalidatingAnalysisPass847   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.
TEST_F(PassManagerTest,FunctionPassCFGCheckerInvalidateAnalysis)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> {
TestSimplifyCFGWrapperPass__anon1d60355b0111::TestSimplifyCFGWrapperPass895   TestSimplifyCFGWrapperPass(FunctionPassManager &InnerPM) : InnerPM(InnerPM) {}
896 
run__anon1d60355b0111::TestSimplifyCFGWrapperPass897   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).
TEST_F(PassManagerTest,FunctionPassCFGCheckerWrapped)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> {
run__anon1d60355b0111::WrongFunctionPass966   PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
967     F.getEntryBlock().begin()->eraseFromParent();
968     return PreservedAnalyses::all();
969   }
name__anon1d60355b0111::WrongFunctionPass970   static StringRef name() { return "WrongFunctionPass"; }
971 };
972 
TEST_F(PassManagerTest,FunctionPassMissedFunctionAnalysisInvalidation)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   FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
989 
990   FunctionPassManager FPM;
991   FPM.addPass(WrongFunctionPass());
992 
993   auto *F = M->getFunction("foo");
994   EXPECT_DEATH(FPM.run(*F, FAM), "Function @foo changed by WrongFunctionPass without invalidating analyses");
995 }
996 
997 struct WrongModulePass : PassInfoMixin<WrongModulePass> {
run__anon1d60355b0111::WrongModulePass998   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM) {
999     for (Function &F : M)
1000       F.getEntryBlock().begin()->eraseFromParent();
1001 
1002     PreservedAnalyses PA;
1003     PA.preserveSet<AllAnalysesOn<Function>>();
1004     PA.preserve<FunctionAnalysisManagerModuleProxy>();
1005     return PA;
1006   }
name__anon1d60355b0111::WrongModulePass1007   static StringRef name() { return "WrongModulePass"; }
1008 };
1009 
TEST_F(PassManagerTest,ModulePassMissedFunctionAnalysisInvalidation)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");
1016 
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); });
1026 
1027   ModulePassManager MPM;
1028   MPM.addPass(WrongModulePass());
1029 
1030   EXPECT_DEATH(
1031       MPM.run(*M, MAM),
1032       "Function @foo changed by WrongModulePass without invalidating analyses");
1033 }
1034 
1035 struct WrongModulePass2 : PassInfoMixin<WrongModulePass2> {
run__anon1d60355b0111::WrongModulePass21036   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM) {
1037     for (Function &F : M)
1038       F.getEntryBlock().begin()->eraseFromParent();
1039 
1040     PreservedAnalyses PA;
1041     PA.preserveSet<AllAnalysesOn<Module>>();
1042     PA.abandon<FunctionAnalysisManagerModuleProxy>();
1043     return PA;
1044   }
name__anon1d60355b0111::WrongModulePass21045   static StringRef name() { return "WrongModulePass2"; }
1046 };
1047 
TEST_F(PassManagerTest,ModulePassMissedModuleAnalysisInvalidation)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");
1054 
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); });
1064 
1065   ModulePassManager MPM;
1066   MPM.addPass(WrongModulePass2());
1067 
1068   EXPECT_DEATH(
1069       MPM.run(*M, MAM),
1070       "Module changed by WrongModulePass2 without invalidating analyses");
1071 }
1072 
1073 #endif
1074 }
1075