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