1 //===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
22 class TestFunctionAnalysis
{
25 Result(int Count
) : InstructionCount(Count
) {}
29 /// \brief Returns an opaque, unique ID for this pass type.
30 static void *ID() { return (void *)&PassID
; }
32 /// \brief Returns the name of the analysis.
33 static StringRef
name() { return "TestFunctionAnalysis"; }
35 TestFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
37 /// \brief Run the analysis pass over the function and return a result.
38 Result
run(Function
&F
, FunctionAnalysisManager
*AM
) {
41 for (Function::iterator BBI
= F
.begin(), BBE
= F
.end(); BBI
!= BBE
; ++BBI
)
42 for (BasicBlock::iterator II
= BBI
->begin(), IE
= BBI
->end(); II
!= IE
;
49 /// \brief Private static data to provide unique ID.
55 char TestFunctionAnalysis::PassID
;
57 class TestModuleAnalysis
{
60 Result(int Count
) : FunctionCount(Count
) {}
64 static void *ID() { return (void *)&PassID
; }
66 static StringRef
name() { return "TestModuleAnalysis"; }
68 TestModuleAnalysis(int &Runs
) : Runs(Runs
) {}
70 Result
run(Module
&M
, ModuleAnalysisManager
*AM
) {
73 for (Module::iterator I
= M
.begin(), E
= M
.end(); I
!= E
; ++I
)
84 char TestModuleAnalysis::PassID
;
86 struct TestModulePass
{
87 TestModulePass(int &RunCount
) : RunCount(RunCount
) {}
89 PreservedAnalyses
run(Module
&M
) {
91 return PreservedAnalyses::none();
94 static StringRef
name() { return "TestModulePass"; }
99 struct TestPreservingModulePass
{
100 PreservedAnalyses
run(Module
&M
) { return PreservedAnalyses::all(); }
102 static StringRef
name() { return "TestPreservingModulePass"; }
105 struct TestMinPreservingModulePass
{
106 PreservedAnalyses
run(Module
&M
, ModuleAnalysisManager
*AM
) {
107 PreservedAnalyses PA
;
109 // Force running an analysis.
110 (void)AM
->getResult
<TestModuleAnalysis
>(M
);
112 PA
.preserve
<FunctionAnalysisManagerModuleProxy
>();
116 static StringRef
name() { return "TestMinPreservingModulePass"; }
119 struct TestFunctionPass
{
120 TestFunctionPass(int &RunCount
, int &AnalyzedInstrCount
,
121 int &AnalyzedFunctionCount
,
122 bool OnlyUseCachedResults
= false)
123 : RunCount(RunCount
), AnalyzedInstrCount(AnalyzedInstrCount
),
124 AnalyzedFunctionCount(AnalyzedFunctionCount
),
125 OnlyUseCachedResults(OnlyUseCachedResults
) {}
127 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
*AM
) {
130 const ModuleAnalysisManager
&MAM
=
131 AM
->getResult
<ModuleAnalysisManagerFunctionProxy
>(F
).getManager();
132 if (TestModuleAnalysis::Result
*TMA
=
133 MAM
.getCachedResult
<TestModuleAnalysis
>(*F
.getParent()))
134 AnalyzedFunctionCount
+= TMA
->FunctionCount
;
136 if (OnlyUseCachedResults
) {
137 // Hack to force the use of the cached interface.
138 if (TestFunctionAnalysis::Result
*AR
=
139 AM
->getCachedResult
<TestFunctionAnalysis
>(F
))
140 AnalyzedInstrCount
+= AR
->InstructionCount
;
142 // Typical path just runs the analysis as needed.
143 TestFunctionAnalysis::Result
&AR
= AM
->getResult
<TestFunctionAnalysis
>(F
);
144 AnalyzedInstrCount
+= AR
.InstructionCount
;
147 return PreservedAnalyses::all();
150 static StringRef
name() { return "TestFunctionPass"; }
153 int &AnalyzedInstrCount
;
154 int &AnalyzedFunctionCount
;
155 bool OnlyUseCachedResults
;
158 // A test function pass that invalidates all function analyses for a function
159 // with a specific name.
160 struct TestInvalidationFunctionPass
{
161 TestInvalidationFunctionPass(StringRef FunctionName
) : Name(FunctionName
) {}
163 PreservedAnalyses
run(Function
&F
) {
164 return F
.getName() == Name
? PreservedAnalyses::none()
165 : PreservedAnalyses::all();
168 static StringRef
name() { return "TestInvalidationFunctionPass"; }
173 std::unique_ptr
<Module
> parseIR(const char *IR
) {
174 LLVMContext
&C
= getGlobalContext();
176 return parseAssemblyString(IR
, Err
, C
);
179 class PassManagerTest
: public ::testing::Test
{
181 std::unique_ptr
<Module
> M
;
185 : M(parseIR("define void @f() {\n"
191 "define void @g() {\n"
194 "define void @h() {\n"
199 TEST_F(PassManagerTest
, BasicPreservedAnalyses
) {
200 PreservedAnalyses PA1
= PreservedAnalyses();
201 EXPECT_FALSE(PA1
.preserved
<TestFunctionAnalysis
>());
202 EXPECT_FALSE(PA1
.preserved
<TestModuleAnalysis
>());
203 PreservedAnalyses PA2
= PreservedAnalyses::none();
204 EXPECT_FALSE(PA2
.preserved
<TestFunctionAnalysis
>());
205 EXPECT_FALSE(PA2
.preserved
<TestModuleAnalysis
>());
206 PreservedAnalyses PA3
= PreservedAnalyses::all();
207 EXPECT_TRUE(PA3
.preserved
<TestFunctionAnalysis
>());
208 EXPECT_TRUE(PA3
.preserved
<TestModuleAnalysis
>());
209 PreservedAnalyses PA4
= PA1
;
210 EXPECT_FALSE(PA4
.preserved
<TestFunctionAnalysis
>());
211 EXPECT_FALSE(PA4
.preserved
<TestModuleAnalysis
>());
213 EXPECT_TRUE(PA4
.preserved
<TestFunctionAnalysis
>());
214 EXPECT_TRUE(PA4
.preserved
<TestModuleAnalysis
>());
215 PA4
= std::move(PA2
);
216 EXPECT_FALSE(PA4
.preserved
<TestFunctionAnalysis
>());
217 EXPECT_FALSE(PA4
.preserved
<TestModuleAnalysis
>());
218 PA4
.preserve
<TestFunctionAnalysis
>();
219 EXPECT_TRUE(PA4
.preserved
<TestFunctionAnalysis
>());
220 EXPECT_FALSE(PA4
.preserved
<TestModuleAnalysis
>());
221 PA1
.preserve
<TestModuleAnalysis
>();
222 EXPECT_FALSE(PA1
.preserved
<TestFunctionAnalysis
>());
223 EXPECT_TRUE(PA1
.preserved
<TestModuleAnalysis
>());
224 PA1
.preserve
<TestFunctionAnalysis
>();
225 EXPECT_TRUE(PA1
.preserved
<TestFunctionAnalysis
>());
226 EXPECT_TRUE(PA1
.preserved
<TestModuleAnalysis
>());
228 EXPECT_TRUE(PA1
.preserved
<TestFunctionAnalysis
>());
229 EXPECT_FALSE(PA1
.preserved
<TestModuleAnalysis
>());
232 TEST_F(PassManagerTest
, Basic
) {
233 FunctionAnalysisManager FAM
;
234 int FunctionAnalysisRuns
= 0;
235 FAM
.registerPass(TestFunctionAnalysis(FunctionAnalysisRuns
));
237 ModuleAnalysisManager MAM
;
238 int ModuleAnalysisRuns
= 0;
239 MAM
.registerPass(TestModuleAnalysis(ModuleAnalysisRuns
));
240 MAM
.registerPass(FunctionAnalysisManagerModuleProxy(FAM
));
241 FAM
.registerPass(ModuleAnalysisManagerFunctionProxy(MAM
));
243 ModulePassManager MPM
;
245 // Count the runs over a Function.
246 int FunctionPassRunCount1
= 0;
247 int AnalyzedInstrCount1
= 0;
248 int AnalyzedFunctionCount1
= 0;
250 // Pointless scoped copy to test move assignment.
251 ModulePassManager NestedMPM
;
252 FunctionPassManager FPM
;
254 // Pointless scope to test move assignment.
255 FunctionPassManager NestedFPM
;
256 NestedFPM
.addPass(TestFunctionPass(FunctionPassRunCount1
, AnalyzedInstrCount1
,
257 AnalyzedFunctionCount1
));
258 FPM
= std::move(NestedFPM
);
260 NestedMPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
261 MPM
= std::move(NestedMPM
);
264 // Count the runs over a module.
265 int ModulePassRunCount
= 0;
266 MPM
.addPass(TestModulePass(ModulePassRunCount
));
268 // Count the runs over a Function in a separate manager.
269 int FunctionPassRunCount2
= 0;
270 int AnalyzedInstrCount2
= 0;
271 int AnalyzedFunctionCount2
= 0;
273 FunctionPassManager FPM
;
274 FPM
.addPass(TestFunctionPass(FunctionPassRunCount2
, AnalyzedInstrCount2
,
275 AnalyzedFunctionCount2
));
276 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
279 // A third function pass manager but with only preserving intervening passes
280 // and with a function pass that invalidates exactly one analysis.
281 MPM
.addPass(TestPreservingModulePass());
282 int FunctionPassRunCount3
= 0;
283 int AnalyzedInstrCount3
= 0;
284 int AnalyzedFunctionCount3
= 0;
286 FunctionPassManager FPM
;
287 FPM
.addPass(TestFunctionPass(FunctionPassRunCount3
, AnalyzedInstrCount3
,
288 AnalyzedFunctionCount3
));
289 FPM
.addPass(TestInvalidationFunctionPass("f"));
290 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
293 // A fourth function pass manager but with a minimal intervening passes.
294 MPM
.addPass(TestMinPreservingModulePass());
295 int FunctionPassRunCount4
= 0;
296 int AnalyzedInstrCount4
= 0;
297 int AnalyzedFunctionCount4
= 0;
299 FunctionPassManager FPM
;
300 FPM
.addPass(TestFunctionPass(FunctionPassRunCount4
, AnalyzedInstrCount4
,
301 AnalyzedFunctionCount4
));
302 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
305 // A fifth function pass manager but which uses only cached results.
306 int FunctionPassRunCount5
= 0;
307 int AnalyzedInstrCount5
= 0;
308 int AnalyzedFunctionCount5
= 0;
310 FunctionPassManager FPM
;
311 FPM
.addPass(TestInvalidationFunctionPass("f"));
312 FPM
.addPass(TestFunctionPass(FunctionPassRunCount5
, AnalyzedInstrCount5
,
313 AnalyzedFunctionCount5
,
314 /*OnlyUseCachedResults=*/true));
315 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
320 // Validate module pass counters.
321 EXPECT_EQ(1, ModulePassRunCount
);
323 // Validate all function pass counter sets are the same.
324 EXPECT_EQ(3, FunctionPassRunCount1
);
325 EXPECT_EQ(5, AnalyzedInstrCount1
);
326 EXPECT_EQ(0, AnalyzedFunctionCount1
);
327 EXPECT_EQ(3, FunctionPassRunCount2
);
328 EXPECT_EQ(5, AnalyzedInstrCount2
);
329 EXPECT_EQ(0, AnalyzedFunctionCount2
);
330 EXPECT_EQ(3, FunctionPassRunCount3
);
331 EXPECT_EQ(5, AnalyzedInstrCount3
);
332 EXPECT_EQ(0, AnalyzedFunctionCount3
);
333 EXPECT_EQ(3, FunctionPassRunCount4
);
334 EXPECT_EQ(5, AnalyzedInstrCount4
);
335 EXPECT_EQ(0, AnalyzedFunctionCount4
);
336 EXPECT_EQ(3, FunctionPassRunCount5
);
337 EXPECT_EQ(2, AnalyzedInstrCount5
); // Only 'g' and 'h' were cached.
338 EXPECT_EQ(0, AnalyzedFunctionCount5
);
340 // Validate the analysis counters:
341 // first run over 3 functions, then module pass invalidates
342 // second run over 3 functions, nothing invalidates
343 // third run over 0 functions, but 1 function invalidated
344 // fourth run over 1 function
345 EXPECT_EQ(7, FunctionAnalysisRuns
);
347 EXPECT_EQ(1, ModuleAnalysisRuns
);