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
18using namespace llvm;
19
20namespace {
21
22class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
23public:
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
42private:
43  friend AnalysisInfoMixin<TestFunctionAnalysis>;
44  static char PassID;
45
46  int &Runs;
47};
48
49char TestFunctionAnalysis::PassID;
50
51class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
52public:
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
68private:
69  friend AnalysisInfoMixin<TestModuleAnalysis>;
70  static char PassID;
71
72  int &Runs;
73};
74
75char TestModuleAnalysis::PassID;
76
77struct 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
88struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> {
89  PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
90    return PreservedAnalyses::all();
91  }
92};
93
94struct TestMinPreservingModulePass
95    : PassInfoMixin<TestMinPreservingModulePass> {
96  PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
97    PreservedAnalyses PA;
98
99    // Force running an analysis.
100    (void)AM.getResult<TestModuleAnalysis>(M);
101
102    PA.preserve<FunctionAnalysisManagerModuleProxy>();
103    return PA;
104  }
105};
106
107struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
108  TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
109                   int &AnalyzedFunctionCount,
110                   bool OnlyUseCachedResults = false)
111      : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
112        AnalyzedFunctionCount(AnalyzedFunctionCount),
113        OnlyUseCachedResults(OnlyUseCachedResults) {}
114
115  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
116    ++RunCount;
117
118    const ModuleAnalysisManager &MAM =
119        AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
120    if (TestModuleAnalysis::Result *TMA =
121            MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()))
122      AnalyzedFunctionCount += TMA->FunctionCount;
123
124    if (OnlyUseCachedResults) {
125      // Hack to force the use of the cached interface.
126      if (TestFunctionAnalysis::Result *AR =
127              AM.getCachedResult<TestFunctionAnalysis>(F))
128        AnalyzedInstrCount += AR->InstructionCount;
129    } else {
130      // Typical path just runs the analysis as needed.
131      TestFunctionAnalysis::Result &AR = AM.getResult<TestFunctionAnalysis>(F);
132      AnalyzedInstrCount += AR.InstructionCount;
133    }
134
135    return PreservedAnalyses::all();
136  }
137
138  int &RunCount;
139  int &AnalyzedInstrCount;
140  int &AnalyzedFunctionCount;
141  bool OnlyUseCachedResults;
142};
143
144// A test function pass that invalidates all function analyses for a function
145// with a specific name.
146struct TestInvalidationFunctionPass
147    : PassInfoMixin<TestInvalidationFunctionPass> {
148  TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
149
150  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
151    return F.getName() == Name ? PreservedAnalyses::none()
152                               : PreservedAnalyses::all();
153  }
154
155  StringRef Name;
156};
157
158std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
159  SMDiagnostic Err;
160  return parseAssemblyString(IR, Err, Context);
161}
162
163class PassManagerTest : public ::testing::Test {
164protected:
165  LLVMContext Context;
166  std::unique_ptr<Module> M;
167
168public:
169  PassManagerTest()
170      : M(parseIR(Context, "define void @f() {\n"
171                           "entry:\n"
172                           "  call void @g()\n"
173                           "  call void @h()\n"
174                           "  ret void\n"
175                           "}\n"
176                           "define void @g() {\n"
177                           "  ret void\n"
178                           "}\n"
179                           "define void @h() {\n"
180                           "  ret void\n"
181                           "}\n")) {}
182};
183
184TEST_F(PassManagerTest, BasicPreservedAnalyses) {
185  PreservedAnalyses PA1 = PreservedAnalyses();
186  EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
187  EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
188  PreservedAnalyses PA2 = PreservedAnalyses::none();
189  EXPECT_FALSE(PA2.preserved<TestFunctionAnalysis>());
190  EXPECT_FALSE(PA2.preserved<TestModuleAnalysis>());
191  PreservedAnalyses PA3 = PreservedAnalyses::all();
192  EXPECT_TRUE(PA3.preserved<TestFunctionAnalysis>());
193  EXPECT_TRUE(PA3.preserved<TestModuleAnalysis>());
194  PreservedAnalyses PA4 = PA1;
195  EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
196  EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
197  PA4 = PA3;
198  EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
199  EXPECT_TRUE(PA4.preserved<TestModuleAnalysis>());
200  PA4 = std::move(PA2);
201  EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
202  EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
203  PA4.preserve<TestFunctionAnalysis>();
204  EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
205  EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
206  PA1.preserve<TestModuleAnalysis>();
207  EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
208  EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
209  PA1.preserve<TestFunctionAnalysis>();
210  EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
211  EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
212  PA1.intersect(PA4);
213  EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
214  EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
215}
216
217TEST_F(PassManagerTest, Basic) {
218  FunctionAnalysisManager FAM;
219  int FunctionAnalysisRuns = 0;
220  FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
221
222  ModuleAnalysisManager MAM;
223  int ModuleAnalysisRuns = 0;
224  MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
225  MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
226  FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
227
228  ModulePassManager MPM;
229
230  // Count the runs over a Function.
231  int FunctionPassRunCount1 = 0;
232  int AnalyzedInstrCount1 = 0;
233  int AnalyzedFunctionCount1 = 0;
234  {
235    // Pointless scoped copy to test move assignment.
236    ModulePassManager NestedMPM;
237    FunctionPassManager FPM;
238    {
239      // Pointless scope to test move assignment.
240      FunctionPassManager NestedFPM;
241      NestedFPM.addPass(TestFunctionPass(
242          FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1));
243      FPM = std::move(NestedFPM);
244    }
245    NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
246    MPM = std::move(NestedMPM);
247  }
248
249  // Count the runs over a module.
250  int ModulePassRunCount = 0;
251  MPM.addPass(TestModulePass(ModulePassRunCount));
252
253  // Count the runs over a Function in a separate manager.
254  int FunctionPassRunCount2 = 0;
255  int AnalyzedInstrCount2 = 0;
256  int AnalyzedFunctionCount2 = 0;
257  {
258    FunctionPassManager FPM;
259    FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
260                                 AnalyzedFunctionCount2));
261    MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
262  }
263
264  // A third function pass manager but with only preserving intervening passes
265  // and with a function pass that invalidates exactly one analysis.
266  MPM.addPass(TestPreservingModulePass());
267  int FunctionPassRunCount3 = 0;
268  int AnalyzedInstrCount3 = 0;
269  int AnalyzedFunctionCount3 = 0;
270  {
271    FunctionPassManager FPM;
272    FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
273                                 AnalyzedFunctionCount3));
274    FPM.addPass(TestInvalidationFunctionPass("f"));
275    MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
276  }
277
278  // A fourth function pass manager but with a minimal intervening passes.
279  MPM.addPass(TestMinPreservingModulePass());
280  int FunctionPassRunCount4 = 0;
281  int AnalyzedInstrCount4 = 0;
282  int AnalyzedFunctionCount4 = 0;
283  {
284    FunctionPassManager FPM;
285    FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
286                                 AnalyzedFunctionCount4));
287    MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
288  }
289
290  // A fifth function pass manager but which uses only cached results.
291  int FunctionPassRunCount5 = 0;
292  int AnalyzedInstrCount5 = 0;
293  int AnalyzedFunctionCount5 = 0;
294  {
295    FunctionPassManager FPM;
296    FPM.addPass(TestInvalidationFunctionPass("f"));
297    FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
298                                 AnalyzedFunctionCount5,
299                                 /*OnlyUseCachedResults=*/true));
300    MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
301  }
302
303  MPM.run(*M, MAM);
304
305  // Validate module pass counters.
306  EXPECT_EQ(1, ModulePassRunCount);
307
308  // Validate all function pass counter sets are the same.
309  EXPECT_EQ(3, FunctionPassRunCount1);
310  EXPECT_EQ(5, AnalyzedInstrCount1);
311  EXPECT_EQ(0, AnalyzedFunctionCount1);
312  EXPECT_EQ(3, FunctionPassRunCount2);
313  EXPECT_EQ(5, AnalyzedInstrCount2);
314  EXPECT_EQ(0, AnalyzedFunctionCount2);
315  EXPECT_EQ(3, FunctionPassRunCount3);
316  EXPECT_EQ(5, AnalyzedInstrCount3);
317  EXPECT_EQ(0, AnalyzedFunctionCount3);
318  EXPECT_EQ(3, FunctionPassRunCount4);
319  EXPECT_EQ(5, AnalyzedInstrCount4);
320  EXPECT_EQ(0, AnalyzedFunctionCount4);
321  EXPECT_EQ(3, FunctionPassRunCount5);
322  EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
323  EXPECT_EQ(0, AnalyzedFunctionCount5);
324
325  // Validate the analysis counters:
326  //   first run over 3 functions, then module pass invalidates
327  //   second run over 3 functions, nothing invalidates
328  //   third run over 0 functions, but 1 function invalidated
329  //   fourth run over 1 function
330  EXPECT_EQ(7, FunctionAnalysisRuns);
331
332  EXPECT_EQ(1, ModuleAnalysisRuns);
333}
334}
335