• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
Result__anonb36b4f6b0111::TestFunctionAnalysis::Result25     Result(int Count) : InstructionCount(Count) {}
26     int InstructionCount;
27   };
28 
TestFunctionAnalysis(int & Runs)29   TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
30 
31   /// Run the analysis pass over the function and return a result.
run(Function & F,FunctionAnalysisManager & AM)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 {
Result__anonb36b4f6b0111::TestModuleAnalysis::Result54     Result(int Count) : FunctionCount(Count) {}
55     int FunctionCount;
56   };
57 
TestModuleAnalysis(int & Runs)58   TestModuleAnalysis(int &Runs) : Runs(Runs) {}
59 
run(Module & M,ModuleAnalysisManager & AM)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> {
TestModulePass__anonb36b4f6b0111::TestModulePass78   TestModulePass(int &RunCount) : RunCount(RunCount) {}
79 
run__anonb36b4f6b0111::TestModulePass80   PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
81     ++RunCount;
82     return PreservedAnalyses::none();
83   }
84 
85   int &RunCount;
86 };
87 
88 struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> {
run__anonb36b4f6b0111::TestPreservingModulePass89   PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
90     return PreservedAnalyses::all();
91   }
92 };
93 
94 struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
TestFunctionPass__anonb36b4f6b0111::TestFunctionPass95   TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
96                    int &AnalyzedFunctionCount,
97                    bool OnlyUseCachedResults = false)
98       : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
99         AnalyzedFunctionCount(AnalyzedFunctionCount),
100         OnlyUseCachedResults(OnlyUseCachedResults) {}
101 
run__anonb36b4f6b0111::TestFunctionPass102   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> {
TestInvalidationFunctionPass__anonb36b4f6b0111::TestInvalidationFunctionPass135   TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
136 
run__anonb36b4f6b0111::TestInvalidationFunctionPass137   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
138     return F.getName() == Name ? PreservedAnalyses::none()
139                                : PreservedAnalyses::all();
140   }
141 
142   StringRef Name;
143 };
144 
parseIR(LLVMContext & Context,const char * IR)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:
PassManagerTest()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 
TEST(PreservedAnalysesTest,Basic)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 
TEST(PreservedAnalysesTest,Preserve)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 
TEST(PreservedAnalysesTest,PreserveSets)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 
TEST(PreservedAnalysisTest,Intersect)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 
TEST(PreservedAnalysisTest,Abandon)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 
TEST_F(PassManagerTest,Basic)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   ModulePassManager MPM;
410 
411   // Count the runs over a Function.
412   int FunctionPassRunCount1 = 0;
413   int AnalyzedInstrCount1 = 0;
414   int AnalyzedFunctionCount1 = 0;
415   {
416     // Pointless scoped copy to test move assignment.
417     ModulePassManager NestedMPM(/*DebugLogging*/ true);
418     FunctionPassManager FPM;
419     {
420       // Pointless scope to test move assignment.
421       FunctionPassManager NestedFPM(/*DebugLogging*/ true);
422       NestedFPM.addPass(TestFunctionPass(
423           FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1));
424       FPM = std::move(NestedFPM);
425     }
426     NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
427     MPM = std::move(NestedMPM);
428   }
429 
430   // Count the runs over a module.
431   int ModulePassRunCount = 0;
432   MPM.addPass(TestModulePass(ModulePassRunCount));
433 
434   // Count the runs over a Function in a separate manager.
435   int FunctionPassRunCount2 = 0;
436   int AnalyzedInstrCount2 = 0;
437   int AnalyzedFunctionCount2 = 0;
438   {
439     FunctionPassManager FPM(/*DebugLogging*/ true);
440     FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
441                                  AnalyzedFunctionCount2));
442     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
443   }
444 
445   // A third function pass manager but with only preserving intervening passes
446   // and with a function pass that invalidates exactly one analysis.
447   MPM.addPass(TestPreservingModulePass());
448   int FunctionPassRunCount3 = 0;
449   int AnalyzedInstrCount3 = 0;
450   int AnalyzedFunctionCount3 = 0;
451   {
452     FunctionPassManager FPM(/*DebugLogging*/ true);
453     FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
454                                  AnalyzedFunctionCount3));
455     FPM.addPass(TestInvalidationFunctionPass("f"));
456     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
457   }
458 
459   // A fourth function pass manager but with only preserving intervening
460   // passes but triggering the module analysis.
461   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
462   int FunctionPassRunCount4 = 0;
463   int AnalyzedInstrCount4 = 0;
464   int AnalyzedFunctionCount4 = 0;
465   {
466     FunctionPassManager FPM;
467     FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
468                                  AnalyzedFunctionCount4));
469     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
470   }
471 
472   // A fifth function pass manager which invalidates one function first but
473   // uses only cached results.
474   int FunctionPassRunCount5 = 0;
475   int AnalyzedInstrCount5 = 0;
476   int AnalyzedFunctionCount5 = 0;
477   {
478     FunctionPassManager FPM(/*DebugLogging*/ true);
479     FPM.addPass(TestInvalidationFunctionPass("f"));
480     FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
481                                  AnalyzedFunctionCount5,
482                                  /*OnlyUseCachedResults=*/true));
483     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
484   }
485 
486   MPM.run(*M, MAM);
487 
488   // Validate module pass counters.
489   EXPECT_EQ(1, ModulePassRunCount);
490 
491   // Validate all function pass counter sets are the same.
492   EXPECT_EQ(3, FunctionPassRunCount1);
493   EXPECT_EQ(5, AnalyzedInstrCount1);
494   EXPECT_EQ(0, AnalyzedFunctionCount1);
495   EXPECT_EQ(3, FunctionPassRunCount2);
496   EXPECT_EQ(5, AnalyzedInstrCount2);
497   EXPECT_EQ(0, AnalyzedFunctionCount2);
498   EXPECT_EQ(3, FunctionPassRunCount3);
499   EXPECT_EQ(5, AnalyzedInstrCount3);
500   EXPECT_EQ(0, AnalyzedFunctionCount3);
501   EXPECT_EQ(3, FunctionPassRunCount4);
502   EXPECT_EQ(5, AnalyzedInstrCount4);
503   EXPECT_EQ(9, AnalyzedFunctionCount4);
504   EXPECT_EQ(3, FunctionPassRunCount5);
505   EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
506   EXPECT_EQ(9, AnalyzedFunctionCount5);
507 
508   // Validate the analysis counters:
509   //   first run over 3 functions, then module pass invalidates
510   //   second run over 3 functions, nothing invalidates
511   //   third run over 0 functions, but 1 function invalidated
512   //   fourth run over 1 function
513   //   fifth run invalidates 1 function first, but runs over 0 functions
514   EXPECT_EQ(7, FunctionAnalysisRuns);
515 
516   EXPECT_EQ(1, ModuleAnalysisRuns);
517 }
518 
519 // A customized pass manager that passes extra arguments through the
520 // infrastructure.
521 typedef AnalysisManager<Function, int> CustomizedAnalysisManager;
522 typedef PassManager<Function, CustomizedAnalysisManager, int, int &>
523     CustomizedPassManager;
524 
525 class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> {
526 public:
527   struct Result {
Result__anonb36b4f6b0111::CustomizedAnalysis::Result528     Result(int I) : I(I) {}
529     int I;
530   };
531 
run(Function & F,CustomizedAnalysisManager & AM,int I)532   Result run(Function &F, CustomizedAnalysisManager &AM, int I) {
533     return Result(I);
534   }
535 
536 private:
537   friend AnalysisInfoMixin<CustomizedAnalysis>;
538   static AnalysisKey Key;
539 };
540 
541 AnalysisKey CustomizedAnalysis::Key;
542 
543 struct CustomizedPass : PassInfoMixin<CustomizedPass> {
544   std::function<void(CustomizedAnalysis::Result &, int &)> Callback;
545 
546   template <typename CallbackT>
CustomizedPass__anonb36b4f6b0111::CustomizedPass547   CustomizedPass(CallbackT Callback) : Callback(Callback) {}
548 
run__anonb36b4f6b0111::CustomizedPass549   PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I,
550                         int &O) {
551     Callback(AM.getResult<CustomizedAnalysis>(F, I), O);
552     return PreservedAnalyses::none();
553   }
554 };
555 
TEST_F(PassManagerTest,CustomizedPassManagerArgs)556 TEST_F(PassManagerTest, CustomizedPassManagerArgs) {
557   CustomizedAnalysisManager AM;
558   AM.registerPass([&] { return CustomizedAnalysis(); });
559 
560   CustomizedPassManager PM;
561 
562   // Add an instance of the customized pass that just accumulates the input
563   // after it is round-tripped through the analysis.
564   int Result = 0;
565   PM.addPass(
566       CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; }));
567 
568   // Run this over every function with the input of 42.
569   for (Function &F : *M)
570     PM.run(F, AM, 42, Result);
571 
572   // And ensure that we accumulated the correct result.
573   EXPECT_EQ(42 * (int)M->size(), Result);
574 }
575 
576 /// A test analysis pass which caches in its result another analysis pass and
577 /// uses it to serve queries. This requires the result to invalidate itself
578 /// when its dependency is invalidated.
579 struct TestIndirectFunctionAnalysis
580     : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
581   struct Result {
Result__anonb36b4f6b0111::TestIndirectFunctionAnalysis::Result582     Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep)
583         : FDep(FDep), MDep(MDep) {}
584     TestFunctionAnalysis::Result &FDep;
585     TestModuleAnalysis::Result &MDep;
586 
invalidate__anonb36b4f6b0111::TestIndirectFunctionAnalysis::Result587     bool invalidate(Function &F, const PreservedAnalyses &PA,
588                     FunctionAnalysisManager::Invalidator &Inv) {
589       auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
590       return !(PAC.preserved() ||
591                PAC.preservedSet<AllAnalysesOn<Function>>()) ||
592              Inv.invalidate<TestFunctionAnalysis>(F, PA);
593     }
594   };
595 
TestIndirectFunctionAnalysis__anonb36b4f6b0111::TestIndirectFunctionAnalysis596   TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
597 
598   /// Run the analysis pass over the function and return a result.
run__anonb36b4f6b0111::TestIndirectFunctionAnalysis599   Result run(Function &F, FunctionAnalysisManager &AM) {
600     ++Runs;
601     auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
602     auto &Proxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
603     const ModuleAnalysisManager &MAM = Proxy.getManager();
604     // For the test, we insist that the module analysis starts off in the
605     // cache.
606     auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
607     // And register the dependency as module analysis dependencies have to be
608     // pre-registered on the proxy.
609     Proxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
610                                             TestIndirectFunctionAnalysis>();
611     return Result(FDep, MDep);
612   }
613 
614 private:
615   friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
616   static AnalysisKey Key;
617 
618   int &Runs;
619 };
620 
621 AnalysisKey TestIndirectFunctionAnalysis::Key;
622 
623 /// A test analysis pass which chaches in its result the result from the above
624 /// indirect analysis pass.
625 ///
626 /// This allows us to ensure that whenever an analysis pass is invalidated due
627 /// to dependencies (especially dependencies across IR units that trigger
628 /// asynchronous invalidation) we correctly detect that this may in turn cause
629 /// other analysis to be invalidated.
630 struct TestDoublyIndirectFunctionAnalysis
631     : public AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis> {
632   struct Result {
Result__anonb36b4f6b0111::TestDoublyIndirectFunctionAnalysis::Result633     Result(TestIndirectFunctionAnalysis::Result &IDep) : IDep(IDep) {}
634     TestIndirectFunctionAnalysis::Result &IDep;
635 
invalidate__anonb36b4f6b0111::TestDoublyIndirectFunctionAnalysis::Result636     bool invalidate(Function &F, const PreservedAnalyses &PA,
637                     FunctionAnalysisManager::Invalidator &Inv) {
638       auto PAC = PA.getChecker<TestDoublyIndirectFunctionAnalysis>();
639       return !(PAC.preserved() ||
640                PAC.preservedSet<AllAnalysesOn<Function>>()) ||
641              Inv.invalidate<TestIndirectFunctionAnalysis>(F, PA);
642     }
643   };
644 
TestDoublyIndirectFunctionAnalysis__anonb36b4f6b0111::TestDoublyIndirectFunctionAnalysis645   TestDoublyIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
646 
647   /// Run the analysis pass over the function and return a result.
run__anonb36b4f6b0111::TestDoublyIndirectFunctionAnalysis648   Result run(Function &F, FunctionAnalysisManager &AM) {
649     ++Runs;
650     auto &IDep = AM.getResult<TestIndirectFunctionAnalysis>(F);
651     return Result(IDep);
652   }
653 
654 private:
655   friend AnalysisInfoMixin<TestDoublyIndirectFunctionAnalysis>;
656   static AnalysisKey Key;
657 
658   int &Runs;
659 };
660 
661 AnalysisKey TestDoublyIndirectFunctionAnalysis::Key;
662 
663 struct LambdaPass : public PassInfoMixin<LambdaPass> {
664   using FuncT = std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)>;
665 
LambdaPass__anonb36b4f6b0111::LambdaPass666   LambdaPass(FuncT Func) : Func(std::move(Func)) {}
667 
run__anonb36b4f6b0111::LambdaPass668   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
669     return Func(F, AM);
670   }
671 
672   FuncT Func;
673 };
674 
TEST_F(PassManagerTest,IndirectAnalysisInvalidation)675 TEST_F(PassManagerTest, IndirectAnalysisInvalidation) {
676   FunctionAnalysisManager FAM(/*DebugLogging*/ true);
677   int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0,
678       IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0;
679   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
680   FAM.registerPass(
681       [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns); });
682   FAM.registerPass([&] {
683     return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns);
684   });
685 
686   ModuleAnalysisManager MAM(/*DebugLogging*/ true);
687   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
688   MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
689   FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
690 
691   int InstrCount = 0, FunctionCount = 0;
692   ModulePassManager MPM(/*DebugLogging*/ true);
693   FunctionPassManager FPM(/*DebugLogging*/ true);
694   // First just use the analysis to get the instruction count, and preserve
695   // everything.
696   FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
697     auto &DoublyIndirectResult =
698         AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
699     auto &IndirectResult = DoublyIndirectResult.IDep;
700     InstrCount += IndirectResult.FDep.InstructionCount;
701     FunctionCount += IndirectResult.MDep.FunctionCount;
702     return PreservedAnalyses::all();
703   }));
704   // Next, invalidate
705   //   - both analyses for "f",
706   //   - just the underlying (indirect) analysis for "g", and
707   //   - just the direct analysis for "h".
708   FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
709     auto &DoublyIndirectResult =
710         AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
711     auto &IndirectResult = DoublyIndirectResult.IDep;
712     InstrCount += IndirectResult.FDep.InstructionCount;
713     FunctionCount += IndirectResult.MDep.FunctionCount;
714     auto PA = PreservedAnalyses::none();
715     if (F.getName() == "g")
716       PA.preserve<TestFunctionAnalysis>();
717     else if (F.getName() == "h")
718       PA.preserve<TestIndirectFunctionAnalysis>();
719     return PA;
720   }));
721   // Finally, use the analysis again on each function, forcing re-computation
722   // for all of them.
723   FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
724     auto &DoublyIndirectResult =
725         AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
726     auto &IndirectResult = DoublyIndirectResult.IDep;
727     InstrCount += IndirectResult.FDep.InstructionCount;
728     FunctionCount += IndirectResult.MDep.FunctionCount;
729     return PreservedAnalyses::all();
730   }));
731 
732   // Create a second function pass manager. This will cause the module-level
733   // invalidation to occur, which will force yet another invalidation of the
734   // indirect function-level analysis as the module analysis it depends on gets
735   // invalidated.
736   FunctionPassManager FPM2(/*DebugLogging*/ true);
737   FPM2.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
738     auto &DoublyIndirectResult =
739         AM.getResult<TestDoublyIndirectFunctionAnalysis>(F);
740     auto &IndirectResult = DoublyIndirectResult.IDep;
741     InstrCount += IndirectResult.FDep.InstructionCount;
742     FunctionCount += IndirectResult.MDep.FunctionCount;
743     return PreservedAnalyses::all();
744   }));
745 
746   // Add a requires pass to populate the module analysis and then our function
747   // pass pipeline.
748   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
749   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
750   // Now require the module analysis again (it will have been invalidated once)
751   // and then use it again from a function pass manager.
752   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
753   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2)));
754   MPM.run(*M, MAM);
755 
756   // There are generally two possible runs for each of the three functions. But
757   // for one function, we only invalidate the indirect analysis so the base one
758   // only gets run five times.
759   EXPECT_EQ(5, FunctionAnalysisRuns);
760   // The module analysis pass should be run twice here.
761   EXPECT_EQ(2, ModuleAnalysisRuns);
762   // The indirect analysis is invalidated for each function (either directly or
763   // indirectly) and run twice for each.
764   EXPECT_EQ(9, IndirectAnalysisRuns);
765   EXPECT_EQ(9, DoublyIndirectAnalysisRuns);
766 
767   // There are five instructions in the module and we add the count four
768   // times.
769   EXPECT_EQ(5 * 4, InstrCount);
770 
771   // There are three functions and we count them four times for each of the
772   // three functions.
773   EXPECT_EQ(3 * 4 * 3, FunctionCount);
774 }
775 }
776