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