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