xref: /llvm-project/llvm/unittests/IR/PassManagerTest.cpp (revision ba90ae969cc770bd132cc22049de7910c0e02fd3)
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/AsmParser/Parser.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/LLVMContext.h"
13 #include "llvm/IR/Module.h"
14 #include "llvm/IR/PassManager.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   /// \brief 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 }
214 
215 TEST(PreservedAnalysesTest, Preserve) {
216   auto PA = PreservedAnalyses::none();
217   PA.preserve<TestFunctionAnalysis>();
218   EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
219   EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>().preserved());
220   PA.preserve<TestModuleAnalysis>();
221   EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
222   EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved());
223 
224   // Redundant calls are fine.
225   PA.preserve<TestFunctionAnalysis>();
226   EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>().preserved());
227   EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>().preserved());
228 }
229 
230 TEST(PreservedAnalysesTest, PreserveSets) {
231   auto PA = PreservedAnalyses::none();
232   PA.preserveSet<AllAnalysesOn<Function>>();
233   EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
234                   .preservedSet<AllAnalysesOn<Function>>());
235   EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>()
236                    .preservedSet<AllAnalysesOn<Module>>());
237   PA.preserveSet<AllAnalysesOn<Module>>();
238   EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
239                   .preservedSet<AllAnalysesOn<Function>>());
240   EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>()
241                   .preservedSet<AllAnalysesOn<Module>>());
242 
243   // Mixing is fine.
244   PA.preserve<TestFunctionAnalysis>();
245   EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
246                   .preservedSet<AllAnalysesOn<Function>>());
247   EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>()
248                   .preservedSet<AllAnalysesOn<Module>>());
249 
250   // Redundant calls are fine.
251   PA.preserveSet<AllAnalysesOn<Module>>();
252   EXPECT_TRUE(PA.getChecker<TestFunctionAnalysis>()
253                   .preservedSet<AllAnalysesOn<Function>>());
254   EXPECT_TRUE(PA.getChecker<TestModuleAnalysis>()
255                   .preservedSet<AllAnalysesOn<Module>>());
256 }
257 
258 TEST(PreservedAnalysisTest, Intersect) {
259   // Setup the initial sets.
260   auto PA1 = PreservedAnalyses::none();
261   PA1.preserve<TestFunctionAnalysis>();
262   PA1.preserveSet<AllAnalysesOn<Module>>();
263   auto PA2 = PreservedAnalyses::none();
264   PA2.preserve<TestFunctionAnalysis>();
265   PA2.preserveSet<AllAnalysesOn<Function>>();
266   PA2.preserve<TestModuleAnalysis>();
267   PA2.preserveSet<AllAnalysesOn<Module>>();
268   auto PA3 = PreservedAnalyses::none();
269   PA3.preserve<TestModuleAnalysis>();
270   PA3.preserveSet<AllAnalysesOn<Function>>();
271 
272   // Self intersection is a no-op.
273   auto Intersected = PA1;
274   Intersected.intersect(PA1);
275   EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
276   EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
277                    .preservedSet<AllAnalysesOn<Function>>());
278   EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
279   EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
280                   .preservedSet<AllAnalysesOn<Module>>());
281 
282   // Intersecting with all is a no-op.
283   Intersected.intersect(PreservedAnalyses::all());
284   EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
285   EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
286                    .preservedSet<AllAnalysesOn<Function>>());
287   EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
288   EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
289                   .preservedSet<AllAnalysesOn<Module>>());
290 
291   // Intersecting a narrow set with a more broad set is the narrow set.
292   Intersected.intersect(PA2);
293   EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
294   EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
295                    .preservedSet<AllAnalysesOn<Function>>());
296   EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
297   EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
298                   .preservedSet<AllAnalysesOn<Module>>());
299 
300   // Intersecting a broad set with a more narrow set is the narrow set.
301   Intersected = PA2;
302   Intersected.intersect(PA1);
303   EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
304   EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
305                    .preservedSet<AllAnalysesOn<Function>>());
306   EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
307   EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
308                   .preservedSet<AllAnalysesOn<Module>>());
309 
310   // Intersecting with empty clears.
311   Intersected.intersect(PreservedAnalyses::none());
312   EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
313   EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
314                    .preservedSet<AllAnalysesOn<Function>>());
315   EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
316   EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>()
317                    .preservedSet<AllAnalysesOn<Module>>());
318 
319   // Intersecting non-overlapping clears.
320   Intersected = PA1;
321   Intersected.intersect(PA3);
322   EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
323   EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
324                    .preservedSet<AllAnalysesOn<Function>>());
325   EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
326   EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>()
327                    .preservedSet<AllAnalysesOn<Module>>());
328 
329   // Intersecting with moves works in when there is storage on both sides.
330   Intersected = PA1;
331   auto Tmp = PA2;
332   Intersected.intersect(std::move(Tmp));
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 move works for incoming all and existing all.
341   auto Tmp2 = PreservedAnalyses::all();
342   Intersected.intersect(std::move(Tmp2));
343   EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
344   EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
345                    .preservedSet<AllAnalysesOn<Function>>());
346   EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
347   EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
348                   .preservedSet<AllAnalysesOn<Module>>());
349   Intersected = PreservedAnalyses::all();
350   auto Tmp3 = PA1;
351   Intersected.intersect(std::move(Tmp3));
352   EXPECT_TRUE(Intersected.getChecker<TestFunctionAnalysis>().preserved());
353   EXPECT_FALSE(Intersected.getChecker<TestFunctionAnalysis>()
354                    .preservedSet<AllAnalysesOn<Function>>());
355   EXPECT_FALSE(Intersected.getChecker<TestModuleAnalysis>().preserved());
356   EXPECT_TRUE(Intersected.getChecker<TestModuleAnalysis>()
357                   .preservedSet<AllAnalysesOn<Module>>());
358 }
359 
360 TEST(PreservedAnalysisTest, Abandon) {
361   auto PA = PreservedAnalyses::none();
362 
363   // We can abandon things after they are preserved.
364   PA.preserve<TestFunctionAnalysis>();
365   PA.abandon<TestFunctionAnalysis>();
366   EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved());
367 
368   // Repeated is fine, and abandoning if they were never preserved is fine.
369   PA.abandon<TestFunctionAnalysis>();
370   EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>().preserved());
371   PA.abandon<TestModuleAnalysis>();
372   EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>().preserved());
373 
374   // Even if the sets are preserved, the abandoned analyses' checker won't
375   // return true for those sets.
376   PA.preserveSet<AllAnalysesOn<Function>>();
377   PA.preserveSet<AllAnalysesOn<Module>>();
378   EXPECT_FALSE(PA.getChecker<TestFunctionAnalysis>()
379                    .preservedSet<AllAnalysesOn<Function>>());
380   EXPECT_FALSE(PA.getChecker<TestModuleAnalysis>()
381                    .preservedSet<AllAnalysesOn<Module>>());
382 
383   // But an arbitrary (opaque) analysis will still observe the sets as
384   // preserved. This also checks that we can use an explicit ID rather than
385   // a type.
386   AnalysisKey FakeKey, *FakeID = &FakeKey;
387   EXPECT_TRUE(PA.getChecker(FakeID).preservedSet<AllAnalysesOn<Function>>());
388   EXPECT_TRUE(PA.getChecker(FakeID).preservedSet<AllAnalysesOn<Module>>());
389 }
390 
391 TEST_F(PassManagerTest, Basic) {
392   FunctionAnalysisManager FAM(/*DebugLogging*/ true);
393   int FunctionAnalysisRuns = 0;
394   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
395 
396   ModuleAnalysisManager MAM(/*DebugLogging*/ true);
397   int ModuleAnalysisRuns = 0;
398   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
399   MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
400   FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
401 
402   ModulePassManager MPM;
403 
404   // Count the runs over a Function.
405   int FunctionPassRunCount1 = 0;
406   int AnalyzedInstrCount1 = 0;
407   int AnalyzedFunctionCount1 = 0;
408   {
409     // Pointless scoped copy to test move assignment.
410     ModulePassManager NestedMPM(/*DebugLogging*/ true);
411     FunctionPassManager FPM;
412     {
413       // Pointless scope to test move assignment.
414       FunctionPassManager NestedFPM(/*DebugLogging*/ true);
415       NestedFPM.addPass(TestFunctionPass(
416           FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1));
417       FPM = std::move(NestedFPM);
418     }
419     NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
420     MPM = std::move(NestedMPM);
421   }
422 
423   // Count the runs over a module.
424   int ModulePassRunCount = 0;
425   MPM.addPass(TestModulePass(ModulePassRunCount));
426 
427   // Count the runs over a Function in a separate manager.
428   int FunctionPassRunCount2 = 0;
429   int AnalyzedInstrCount2 = 0;
430   int AnalyzedFunctionCount2 = 0;
431   {
432     FunctionPassManager FPM(/*DebugLogging*/ true);
433     FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
434                                  AnalyzedFunctionCount2));
435     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
436   }
437 
438   // A third function pass manager but with only preserving intervening passes
439   // and with a function pass that invalidates exactly one analysis.
440   MPM.addPass(TestPreservingModulePass());
441   int FunctionPassRunCount3 = 0;
442   int AnalyzedInstrCount3 = 0;
443   int AnalyzedFunctionCount3 = 0;
444   {
445     FunctionPassManager FPM(/*DebugLogging*/ true);
446     FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
447                                  AnalyzedFunctionCount3));
448     FPM.addPass(TestInvalidationFunctionPass("f"));
449     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
450   }
451 
452   // A fourth function pass manager but with only preserving intervening
453   // passes but triggering the module analysis.
454   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
455   int FunctionPassRunCount4 = 0;
456   int AnalyzedInstrCount4 = 0;
457   int AnalyzedFunctionCount4 = 0;
458   {
459     FunctionPassManager FPM;
460     FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
461                                  AnalyzedFunctionCount4));
462     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
463   }
464 
465   // A fifth function pass manager which invalidates one function first but
466   // uses only cached results.
467   int FunctionPassRunCount5 = 0;
468   int AnalyzedInstrCount5 = 0;
469   int AnalyzedFunctionCount5 = 0;
470   {
471     FunctionPassManager FPM(/*DebugLogging*/ true);
472     FPM.addPass(TestInvalidationFunctionPass("f"));
473     FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
474                                  AnalyzedFunctionCount5,
475                                  /*OnlyUseCachedResults=*/true));
476     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
477   }
478 
479   MPM.run(*M, MAM);
480 
481   // Validate module pass counters.
482   EXPECT_EQ(1, ModulePassRunCount);
483 
484   // Validate all function pass counter sets are the same.
485   EXPECT_EQ(3, FunctionPassRunCount1);
486   EXPECT_EQ(5, AnalyzedInstrCount1);
487   EXPECT_EQ(0, AnalyzedFunctionCount1);
488   EXPECT_EQ(3, FunctionPassRunCount2);
489   EXPECT_EQ(5, AnalyzedInstrCount2);
490   EXPECT_EQ(0, AnalyzedFunctionCount2);
491   EXPECT_EQ(3, FunctionPassRunCount3);
492   EXPECT_EQ(5, AnalyzedInstrCount3);
493   EXPECT_EQ(0, AnalyzedFunctionCount3);
494   EXPECT_EQ(3, FunctionPassRunCount4);
495   EXPECT_EQ(5, AnalyzedInstrCount4);
496   EXPECT_EQ(9, AnalyzedFunctionCount4);
497   EXPECT_EQ(3, FunctionPassRunCount5);
498   EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
499   EXPECT_EQ(9, AnalyzedFunctionCount5);
500 
501   // Validate the analysis counters:
502   //   first run over 3 functions, then module pass invalidates
503   //   second run over 3 functions, nothing invalidates
504   //   third run over 0 functions, but 1 function invalidated
505   //   fourth run over 1 function
506   //   fifth run invalidates 1 function first, but runs over 0 functions
507   EXPECT_EQ(7, FunctionAnalysisRuns);
508 
509   EXPECT_EQ(1, ModuleAnalysisRuns);
510 }
511 
512 // A customized pass manager that passes extra arguments through the
513 // infrastructure.
514 typedef AnalysisManager<Function, int> CustomizedAnalysisManager;
515 typedef PassManager<Function, CustomizedAnalysisManager, int, int &>
516     CustomizedPassManager;
517 
518 class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> {
519 public:
520   struct Result {
521     Result(int I) : I(I) {}
522     int I;
523   };
524 
525   Result run(Function &F, CustomizedAnalysisManager &AM, int I) {
526     return Result(I);
527   }
528 
529 private:
530   friend AnalysisInfoMixin<CustomizedAnalysis>;
531   static AnalysisKey Key;
532 };
533 
534 AnalysisKey CustomizedAnalysis::Key;
535 
536 struct CustomizedPass : PassInfoMixin<CustomizedPass> {
537   std::function<void(CustomizedAnalysis::Result &, int &)> Callback;
538 
539   template <typename CallbackT>
540   CustomizedPass(CallbackT Callback) : Callback(Callback) {}
541 
542   PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I,
543                         int &O) {
544     Callback(AM.getResult<CustomizedAnalysis>(F, I), O);
545     return PreservedAnalyses::none();
546   }
547 };
548 
549 TEST_F(PassManagerTest, CustomizedPassManagerArgs) {
550   CustomizedAnalysisManager AM;
551   AM.registerPass([&] { return CustomizedAnalysis(); });
552 
553   CustomizedPassManager PM;
554 
555   // Add an instance of the customized pass that just accumulates the input
556   // after it is round-tripped through the analysis.
557   int Result = 0;
558   PM.addPass(
559       CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; }));
560 
561   // Run this over every function with the input of 42.
562   for (Function &F : *M)
563     PM.run(F, AM, 42, Result);
564 
565   // And ensure that we accumulated the correct result.
566   EXPECT_EQ(42 * (int)M->size(), Result);
567 }
568 
569 /// A test analysis pass which caches in its result another analysis pass and
570 /// uses it to serve queries. This requires the result to invalidate itself
571 /// when its dependency is invalidated.
572 struct TestIndirectFunctionAnalysis
573     : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
574   struct Result {
575     Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep)
576         : FDep(FDep), MDep(MDep) {}
577     TestFunctionAnalysis::Result &FDep;
578     TestModuleAnalysis::Result &MDep;
579 
580     bool invalidate(Function &F, const PreservedAnalyses &PA,
581                     FunctionAnalysisManager::Invalidator &Inv) {
582       auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
583       return !(PAC.preserved() ||
584                PAC.preservedSet<AllAnalysesOn<Function>>()) ||
585              Inv.invalidate<TestFunctionAnalysis>(F, PA);
586     }
587   };
588 
589   TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
590 
591   /// Run the analysis pass over the function and return a result.
592   Result run(Function &F, FunctionAnalysisManager &AM) {
593     ++Runs;
594     auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
595     auto &Proxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
596     const ModuleAnalysisManager &MAM = Proxy.getManager();
597     // For the test, we insist that the module analysis starts off in the
598     // cache.
599     auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
600     // And register the dependency as module analysis dependencies have to be
601     // pre-registered on the proxy.
602     Proxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
603                                             TestIndirectFunctionAnalysis>();
604     return Result(FDep, MDep);
605   }
606 
607 private:
608   friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
609   static AnalysisKey Key;
610 
611   int &Runs;
612 };
613 
614 AnalysisKey TestIndirectFunctionAnalysis::Key;
615 
616 /// A test analysis pass which chaches in its result the result from the above
617 /// indirect analysis pass.
618 ///
619 /// This allows us to ensure that whenever an analysis pass is invalidated due
620 /// to dependencies (especially dependencies across IR units that trigger
621 /// asynchronous invalidation) we correctly detect that this may in turn cause
622 /// other analysis to be invalidated.
623 struct TestDoublyIndirectFunctionAnalysis
624     : public AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis> {
625   struct Result {
626     Result(TestIndirectFunctionAnalysis::Result &IDep) : IDep(IDep) {}
627     TestIndirectFunctionAnalysis::Result &IDep;
628 
629     bool invalidate(Function &F, const PreservedAnalyses &PA,
630                     FunctionAnalysisManager::Invalidator &Inv) {
631       auto PAC = PA.getChecker<TestDoublyIndirectFunctionAnalysis>();
632       return !(PAC.preserved() ||
633                PAC.preservedSet<AllAnalysesOn<Function>>()) ||
634              Inv.invalidate<TestIndirectFunctionAnalysis>(F, PA);
635     }
636   };
637 
638   TestDoublyIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
639 
640   /// Run the analysis pass over the function and return a result.
641   Result run(Function &F, FunctionAnalysisManager &AM) {
642     ++Runs;
643     auto &IDep = AM.getResult<TestIndirectFunctionAnalysis>(F);
644     return Result(IDep);
645   }
646 
647 private:
648   friend AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis>;
649   static AnalysisKey Key;
650 
651   int &Runs;
652 };
653 
654 AnalysisKey TestDoublyIndirectFunctionAnalysis::Key;
655 
656 struct LambdaPass : public PassInfoMixin<LambdaPass> {
657   using FuncT = std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)>;
658 
659   LambdaPass(FuncT Func) : Func(std::move(Func)) {}
660 
661   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
662     return Func(F, AM);
663   }
664 
665   FuncT Func;
666 };
667 
668 TEST_F(PassManagerTest, IndirectAnalysisInvalidation) {
669   FunctionAnalysisManager FAM(/*DebugLogging*/ true);
670   int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0,
671       IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0;
672   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
673   FAM.registerPass(
674       [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns); });
675   FAM.registerPass([&] {
676     return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns);
677   });
678 
679   ModuleAnalysisManager MAM(/*DebugLogging*/ true);
680   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
681   MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
682   FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
683 
684   int InstrCount = 0, FunctionCount = 0;
685   ModulePassManager MPM(/*DebugLogging*/ true);
686   FunctionPassManager FPM(/*DebugLogging*/ true);
687   // First just use the analysis to get the instruction count, and preserve
688   // everything.
689   FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
690     auto &DoublyIndirectResult =
691         AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
692     auto &IndirectResult = DoublyIndirectResult.IDep;
693     InstrCount += IndirectResult.FDep.InstructionCount;
694     FunctionCount += IndirectResult.MDep.FunctionCount;
695     return PreservedAnalyses::all();
696   }));
697   // Next, invalidate
698   //   - both analyses for "f",
699   //   - just the underlying (indirect) analysis for "g", and
700   //   - just the direct analysis for "h".
701   FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
702     auto &DoublyIndirectResult =
703         AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
704     auto &IndirectResult = DoublyIndirectResult.IDep;
705     InstrCount += IndirectResult.FDep.InstructionCount;
706     FunctionCount += IndirectResult.MDep.FunctionCount;
707     auto PA = PreservedAnalyses::none();
708     if (F.getName() == "g")
709       PA.preserve<TestFunctionAnalysis>();
710     else if (F.getName() == "h")
711       PA.preserve<TestIndirectFunctionAnalysis>();
712     return PA;
713   }));
714   // Finally, use the analysis again on each function, forcing re-computation
715   // for all of them.
716   FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
717     auto &DoublyIndirectResult =
718         AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
719     auto &IndirectResult = DoublyIndirectResult.IDep;
720     InstrCount += IndirectResult.FDep.InstructionCount;
721     FunctionCount += IndirectResult.MDep.FunctionCount;
722     return PreservedAnalyses::all();
723   }));
724 
725   // Create a second function pass manager. This will cause the module-level
726   // invalidation to occur, which will force yet another invalidation of the
727   // indirect function-level analysis as the module analysis it depends on gets
728   // invalidated.
729   FunctionPassManager FPM2(/*DebugLogging*/ true);
730   FPM2.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 
739   // Add a requires pass to populate the module analysis and then our function
740   // pass pipeline.
741   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
742   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
743   // Now require the module analysis again (it will have been invalidated once)
744   // and then use it again from a function pass manager.
745   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
746   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2)));
747   MPM.run(*M, MAM);
748 
749   // There are generally two possible runs for each of the three functions. But
750   // for one function, we only invalidate the indirect analysis so the base one
751   // only gets run five times.
752   EXPECT_EQ(5, FunctionAnalysisRuns);
753   // The module analysis pass should be run twice here.
754   EXPECT_EQ(2, ModuleAnalysisRuns);
755   // The indirect analysis is invalidated for each function (either directly or
756   // indirectly) and run twice for each.
757   EXPECT_EQ(9, IndirectAnalysisRuns);
758   EXPECT_EQ(9, DoublyIndirectAnalysisRuns);
759 
760   // There are five instructions in the module and we add the count four
761   // times.
762   EXPECT_EQ(5 * 4, InstrCount);
763 
764   // There are three functions and we count them four times for each of the
765   // three functions.
766   EXPECT_EQ(3 * 4 * 3, FunctionCount);
767 }
768 }
769