blob: 49611d6dd3da9668a088022219af8926296e725b [file] [log] [blame]
Chandler Carruth74319922016-02-23 10:02:02 +00001//===- CGSCCPassManagerTest.cpp -------------------------------------------===//
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/Analysis/CGSCCPassManager.h"
11#include "llvm/Analysis/LazyCallGraph.h"
12#include "llvm/AsmParser/Parser.h"
13#include "llvm/IR/Function.h"
14#include "llvm/IR/InstIterator.h"
15#include "llvm/IR/LLVMContext.h"
16#include "llvm/IR/Module.h"
17#include "llvm/IR/PassManager.h"
18#include "llvm/Support/SourceMgr.h"
19#include "gtest/gtest.h"
20
21using namespace llvm;
22
23namespace {
24
25class TestModuleAnalysis {
26public:
27 struct Result {
28 Result(int Count) : FunctionCount(Count) {}
29 int FunctionCount;
30 };
31
32 static void *ID() { return (void *)&PassID; }
33 static StringRef name() { return "TestModuleAnalysis"; }
34
35 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
36
37 Result run(Module &M, ModuleAnalysisManager *AM) {
38 ++Runs;
39 return Result(M.size());
40 }
41
42private:
43 static char PassID;
44
45 int &Runs;
46};
47
48char TestModuleAnalysis::PassID;
49
50class TestSCCAnalysis {
51public:
52 struct Result {
53 Result(int Count) : FunctionCount(Count) {}
54 int FunctionCount;
55 };
56
57 static void *ID() { return (void *)&PassID; }
58 static StringRef name() { return "TestSCCAnalysis"; }
59
60 TestSCCAnalysis(int &Runs) : Runs(Runs) {}
61
62 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) {
63 ++Runs;
64 return Result(C.size());
65 }
66
67private:
68 static char PassID;
69
70 int &Runs;
71};
72
73char TestSCCAnalysis::PassID;
74
75class TestFunctionAnalysis {
76public:
77 struct Result {
78 Result(int Count) : InstructionCount(Count) {}
79 int InstructionCount;
80 };
81
82 static void *ID() { return (void *)&PassID; }
83 static StringRef name() { return "TestFunctionAnalysis"; }
84
85 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
86
87 Result run(Function &F, FunctionAnalysisManager *AM) {
88 ++Runs;
89 int Count = 0;
90 for (Instruction &I : instructions(F)) {
91 (void)I;
92 ++Count;
93 }
94 return Result(Count);
95 }
96
97private:
98 static char PassID;
99
100 int &Runs;
101};
102
103char TestFunctionAnalysis::PassID;
104
105struct TestModulePass {
106 TestModulePass(int &RunCount) : RunCount(RunCount) {}
107
108 PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) {
109 ++RunCount;
110 (void)AM->getResult<TestModuleAnalysis>(M);
111 return PreservedAnalyses::all();
112 }
113
114 static StringRef name() { return "TestModulePass"; }
115
116 int &RunCount;
117};
118
119struct TestSCCPass {
120 TestSCCPass(int &RunCount, int &AnalyzedInstrCount,
121 int &AnalyzedSCCFunctionCount,
122 int &AnalyzedModuleFunctionCount,
123 bool OnlyUseCachedResults = false)
124 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
125 AnalyzedSCCFunctionCount(AnalyzedSCCFunctionCount),
126 AnalyzedModuleFunctionCount(AnalyzedModuleFunctionCount),
127 OnlyUseCachedResults(OnlyUseCachedResults) {}
128
129 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) {
130 ++RunCount;
131
132 const ModuleAnalysisManager &MAM =
133 AM->getResult<ModuleAnalysisManagerCGSCCProxy>(C).getManager();
134 FunctionAnalysisManager &FAM =
135 AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
136 if (TestModuleAnalysis::Result *TMA =
137 MAM.getCachedResult<TestModuleAnalysis>(
138 *C.begin()->getFunction().getParent()))
139 AnalyzedModuleFunctionCount += TMA->FunctionCount;
140
141 if (OnlyUseCachedResults) {
142 // Hack to force the use of the cached interface.
143 if (TestSCCAnalysis::Result *AR =
144 AM->getCachedResult<TestSCCAnalysis>(C))
145 AnalyzedSCCFunctionCount += AR->FunctionCount;
146 for (LazyCallGraph::Node &N : C)
147 if (TestFunctionAnalysis::Result *FAR =
148 FAM.getCachedResult<TestFunctionAnalysis>(N.getFunction()))
149 AnalyzedInstrCount += FAR->InstructionCount;
150 } else {
151 // Typical path just runs the analysis as needed.
152 TestSCCAnalysis::Result &AR = AM->getResult<TestSCCAnalysis>(C);
153 AnalyzedSCCFunctionCount += AR.FunctionCount;
154 for (LazyCallGraph::Node &N : C) {
155 TestFunctionAnalysis::Result &FAR =
156 FAM.getResult<TestFunctionAnalysis>(N.getFunction());
157 AnalyzedInstrCount += FAR.InstructionCount;
158 }
159 }
160
161 return PreservedAnalyses::all();
162 }
163
164 static StringRef name() { return "TestSCCPass"; }
165
166 int &RunCount;
167 int &AnalyzedInstrCount;
168 int &AnalyzedSCCFunctionCount;
169 int &AnalyzedModuleFunctionCount;
170 bool OnlyUseCachedResults;
171};
172
173struct TestFunctionPass {
174 TestFunctionPass(int &RunCount) : RunCount(RunCount) {}
175
176 PreservedAnalyses run(Function &M) {
177 ++RunCount;
178 return PreservedAnalyses::none();
179 }
180
181 static StringRef name() { return "TestFunctionPass"; }
182
183 int &RunCount;
184};
185
186std::unique_ptr<Module> parseIR(const char *IR) {
187 LLVMContext &C = getGlobalContext();
188 SMDiagnostic Err;
189 return parseAssemblyString(IR, Err, C);
190}
191
192class CGSCCPassManagerTest : public ::testing::Test {
193protected:
194 std::unique_ptr<Module> M;
195
196public:
197 CGSCCPassManagerTest()
198 : M(parseIR("define void @f() {\n"
199 "entry:\n"
200 " call void @g()\n"
201 " call void @h1()\n"
202 " ret void\n"
203 "}\n"
204 "define void @g() {\n"
205 "entry:\n"
206 " call void @g()\n"
207 " call void @x()\n"
208 " ret void\n"
209 "}\n"
210 "define void @h1() {\n"
211 "entry:\n"
212 " call void @h2()\n"
213 " ret void\n"
214 "}\n"
215 "define void @h2() {\n"
216 "entry:\n"
217 " call void @h3()\n"
218 " call void @x()\n"
219 " ret void\n"
220 "}\n"
221 "define void @h3() {\n"
222 "entry:\n"
223 " call void @h1()\n"
224 " ret void\n"
225 "}\n"
226 "define void @x() {\n"
227 "entry:\n"
228 " ret void\n"
229 "}\n"
230 )) {}
231};
232
233TEST_F(CGSCCPassManagerTest, Basic) {
234 FunctionAnalysisManager FAM(/*DebugLogging*/ true);
235 int FunctionAnalysisRuns = 0;
236 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
237
238 CGSCCAnalysisManager CGAM(/*DebugLogging*/ true);
239 int SCCAnalysisRuns = 0;
240 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
241
242 ModuleAnalysisManager MAM(/*DebugLogging*/ true);
243 int ModuleAnalysisRuns = 0;
244 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
245 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
246
247 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
248 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
249 CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); });
250 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
251 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
252 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
253
254 ModulePassManager MPM(/*DebugLogging*/ true);
255 int ModulePassRunCount1 = 0;
256 MPM.addPass(TestModulePass(ModulePassRunCount1));
257
258 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
259 int SCCPassRunCount1 = 0;
260 int AnalyzedInstrCount1 = 0;
261 int AnalyzedSCCFunctionCount1 = 0;
262 int AnalyzedModuleFunctionCount1 = 0;
263 CGPM1.addPass(TestSCCPass(SCCPassRunCount1, AnalyzedInstrCount1,
264 AnalyzedSCCFunctionCount1,
265 AnalyzedModuleFunctionCount1));
266
267 FunctionPassManager FPM1(/*DebugLogging*/ true);
268 int FunctionPassRunCount1 = 0;
269 FPM1.addPass(TestFunctionPass(FunctionPassRunCount1));
270 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
271 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
272
273 MPM.run(*M, &MAM);
274
275 EXPECT_EQ(1, ModulePassRunCount1);
276
277 EXPECT_EQ(1, ModuleAnalysisRuns);
278 EXPECT_EQ(4, SCCAnalysisRuns);
279 EXPECT_EQ(6, FunctionAnalysisRuns);
280
281 EXPECT_EQ(4, SCCPassRunCount1);
282 EXPECT_EQ(14, AnalyzedInstrCount1);
283 EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
284 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
285}
286
287}