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/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"
22 class TestFunctionAnalysis
: public AnalysisInfoMixin
<TestFunctionAnalysis
> {
25 Result(int Count
) : InstructionCount(Count
) {}
29 TestFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
31 /// Run the analysis pass over the function and return a result.
32 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
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
;
43 friend AnalysisInfoMixin
<TestFunctionAnalysis
>;
44 static AnalysisKey Key
;
49 AnalysisKey
TestFunctionAnalysis::Key
;
51 class TestModuleAnalysis
: public AnalysisInfoMixin
<TestModuleAnalysis
> {
54 Result(int Count
) : FunctionCount(Count
) {}
58 TestModuleAnalysis(int &Runs
) : Runs(Runs
) {}
60 Result
run(Module
&M
, ModuleAnalysisManager
&AM
) {
63 for (Module::iterator I
= M
.begin(), E
= M
.end(); I
!= E
; ++I
)
69 friend AnalysisInfoMixin
<TestModuleAnalysis
>;
70 static AnalysisKey Key
;
75 AnalysisKey
TestModuleAnalysis::Key
;
77 struct TestModulePass
: PassInfoMixin
<TestModulePass
> {
78 TestModulePass(int &RunCount
) : RunCount(RunCount
) {}
80 PreservedAnalyses
run(Module
&M
, ModuleAnalysisManager
&) {
82 return PreservedAnalyses::none();
88 struct TestPreservingModulePass
: PassInfoMixin
<TestPreservingModulePass
> {
89 PreservedAnalyses
run(Module
&M
, ModuleAnalysisManager
&) {
90 return PreservedAnalyses::all();
94 struct TestFunctionPass
: PassInfoMixin
<TestFunctionPass
> {
95 TestFunctionPass(int &RunCount
, int &AnalyzedInstrCount
,
96 int &AnalyzedFunctionCount
,
97 bool OnlyUseCachedResults
= false)
98 : RunCount(RunCount
), AnalyzedInstrCount(AnalyzedInstrCount
),
99 AnalyzedFunctionCount(AnalyzedFunctionCount
),
100 OnlyUseCachedResults(OnlyUseCachedResults
) {}
102 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
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
;
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
;
117 // Typical path just runs the analysis as needed.
118 TestFunctionAnalysis::Result
&AR
= AM
.getResult
<TestFunctionAnalysis
>(F
);
119 AnalyzedInstrCount
+= AR
.InstructionCount
;
122 return PreservedAnalyses::all();
126 int &AnalyzedInstrCount
;
127 int &AnalyzedFunctionCount
;
128 bool OnlyUseCachedResults
;
131 // A test function pass that invalidates all function analyses for a function
132 // with a specific name.
133 struct TestInvalidationFunctionPass
134 : PassInfoMixin
<TestInvalidationFunctionPass
> {
135 TestInvalidationFunctionPass(StringRef FunctionName
) : Name(FunctionName
) {}
137 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
138 return F
.getName() == Name
? PreservedAnalyses::none()
139 : PreservedAnalyses::all();
145 std::unique_ptr
<Module
> parseIR(LLVMContext
&Context
, const char *IR
) {
147 return parseAssemblyString(IR
, Err
, Context
);
150 class PassManagerTest
: public ::testing::Test
{
153 std::unique_ptr
<Module
> M
;
157 : M(parseIR(Context
, "define void @f() {\n"
163 "define void @g() {\n"
166 "define void @h() {\n"
171 TEST(PreservedAnalysesTest
, Basic
) {
172 PreservedAnalyses PA1
= PreservedAnalyses();
174 auto PAC
= PA1
.getChecker
<TestFunctionAnalysis
>();
175 EXPECT_FALSE(PAC
.preserved());
176 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
179 auto PAC
= PA1
.getChecker
<TestModuleAnalysis
>();
180 EXPECT_FALSE(PAC
.preserved());
181 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Module
>>());
183 auto PA2
= PreservedAnalyses::none();
185 auto PAC
= PA2
.getChecker
<TestFunctionAnalysis
>();
186 EXPECT_FALSE(PAC
.preserved());
187 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
189 auto PA3
= PreservedAnalyses::all();
191 auto PAC
= PA3
.getChecker
<TestFunctionAnalysis
>();
192 EXPECT_TRUE(PAC
.preserved());
193 EXPECT_TRUE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
195 PreservedAnalyses PA4
= PA1
;
197 auto PAC
= PA4
.getChecker
<TestFunctionAnalysis
>();
198 EXPECT_FALSE(PAC
.preserved());
199 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
203 auto PAC
= PA4
.getChecker
<TestFunctionAnalysis
>();
204 EXPECT_TRUE(PAC
.preserved());
205 EXPECT_TRUE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
207 PA4
= std::move(PA2
);
209 auto PAC
= PA4
.getChecker
<TestFunctionAnalysis
>();
210 EXPECT_FALSE(PAC
.preserved());
211 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
213 auto PA5
= PreservedAnalyses::allInSet
<AllAnalysesOn
<Function
>>();
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
>>());
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());
231 // Redundant calls are fine.
232 PA
.preserve
<TestFunctionAnalysis
>();
233 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
234 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>().preserved());
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
>>());
251 PA
.preserve
<TestFunctionAnalysis
>();
252 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>()
253 .preservedSet
<AllAnalysesOn
<Function
>>());
254 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>()
255 .preservedSet
<AllAnalysesOn
<Module
>>());
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
>>());
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
>>();
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
>>());
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
>>());
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
>>());
307 // Intersecting a broad set with a more narrow set is the narrow set.
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
>>());
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
>>());
326 // Intersecting non-overlapping clears.
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
>>());
336 // Intersecting with moves works in when there is storage on both sides.
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
>>());
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();
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
>>());
367 TEST(PreservedAnalysisTest
, Abandon
) {
368 auto PA
= PreservedAnalyses::none();
370 // We can abandon things after they are preserved.
371 PA
.preserve
<TestFunctionAnalysis
>();
372 PA
.abandon
<TestFunctionAnalysis
>();
373 EXPECT_FALSE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
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());
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
>>());
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
393 AnalysisKey FakeKey
, *FakeID
= &FakeKey
;
394 EXPECT_TRUE(PA
.getChecker(FakeID
).preservedSet
<AllAnalysesOn
<Function
>>());
395 EXPECT_TRUE(PA
.getChecker(FakeID
).preservedSet
<AllAnalysesOn
<Module
>>());
398 TEST_F(PassManagerTest
, Basic
) {
399 FunctionAnalysisManager
FAM(/*DebugLogging*/ true);
400 int FunctionAnalysisRuns
= 0;
401 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
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
); });
409 MAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
410 FAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
412 ModulePassManager MPM
;
414 // Count the runs over a Function.
415 int FunctionPassRunCount1
= 0;
416 int AnalyzedInstrCount1
= 0;
417 int AnalyzedFunctionCount1
= 0;
419 // Pointless scoped copy to test move assignment.
420 ModulePassManager
NestedMPM(/*DebugLogging*/ true);
421 FunctionPassManager FPM
;
423 // Pointless scope to test move assignment.
424 FunctionPassManager
NestedFPM(/*DebugLogging*/ true);
425 NestedFPM
.addPass(TestFunctionPass(
426 FunctionPassRunCount1
, AnalyzedInstrCount1
, AnalyzedFunctionCount1
));
427 FPM
= std::move(NestedFPM
);
429 NestedMPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
430 MPM
= std::move(NestedMPM
);
433 // Count the runs over a module.
434 int ModulePassRunCount
= 0;
435 MPM
.addPass(TestModulePass(ModulePassRunCount
));
437 // Count the runs over a Function in a separate manager.
438 int FunctionPassRunCount2
= 0;
439 int AnalyzedInstrCount2
= 0;
440 int AnalyzedFunctionCount2
= 0;
442 FunctionPassManager
FPM(/*DebugLogging*/ true);
443 FPM
.addPass(TestFunctionPass(FunctionPassRunCount2
, AnalyzedInstrCount2
,
444 AnalyzedFunctionCount2
));
445 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
448 // A third function pass manager but with only preserving intervening passes
449 // and with a function pass that invalidates exactly one analysis.
450 MPM
.addPass(TestPreservingModulePass());
451 int FunctionPassRunCount3
= 0;
452 int AnalyzedInstrCount3
= 0;
453 int AnalyzedFunctionCount3
= 0;
455 FunctionPassManager
FPM(/*DebugLogging*/ true);
456 FPM
.addPass(TestFunctionPass(FunctionPassRunCount3
, AnalyzedInstrCount3
,
457 AnalyzedFunctionCount3
));
458 FPM
.addPass(TestInvalidationFunctionPass("f"));
459 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
462 // A fourth function pass manager but with only preserving intervening
463 // passes but triggering the module analysis.
464 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
465 int FunctionPassRunCount4
= 0;
466 int AnalyzedInstrCount4
= 0;
467 int AnalyzedFunctionCount4
= 0;
469 FunctionPassManager FPM
;
470 FPM
.addPass(TestFunctionPass(FunctionPassRunCount4
, AnalyzedInstrCount4
,
471 AnalyzedFunctionCount4
));
472 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
475 // A fifth function pass manager which invalidates one function first but
476 // uses only cached results.
477 int FunctionPassRunCount5
= 0;
478 int AnalyzedInstrCount5
= 0;
479 int AnalyzedFunctionCount5
= 0;
481 FunctionPassManager
FPM(/*DebugLogging*/ true);
482 FPM
.addPass(TestInvalidationFunctionPass("f"));
483 FPM
.addPass(TestFunctionPass(FunctionPassRunCount5
, AnalyzedInstrCount5
,
484 AnalyzedFunctionCount5
,
485 /*OnlyUseCachedResults=*/true));
486 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
491 // Validate module pass counters.
492 EXPECT_EQ(1, ModulePassRunCount
);
494 // Validate all function pass counter sets are the same.
495 EXPECT_EQ(3, FunctionPassRunCount1
);
496 EXPECT_EQ(5, AnalyzedInstrCount1
);
497 EXPECT_EQ(0, AnalyzedFunctionCount1
);
498 EXPECT_EQ(3, FunctionPassRunCount2
);
499 EXPECT_EQ(5, AnalyzedInstrCount2
);
500 EXPECT_EQ(0, AnalyzedFunctionCount2
);
501 EXPECT_EQ(3, FunctionPassRunCount3
);
502 EXPECT_EQ(5, AnalyzedInstrCount3
);
503 EXPECT_EQ(0, AnalyzedFunctionCount3
);
504 EXPECT_EQ(3, FunctionPassRunCount4
);
505 EXPECT_EQ(5, AnalyzedInstrCount4
);
506 EXPECT_EQ(9, AnalyzedFunctionCount4
);
507 EXPECT_EQ(3, FunctionPassRunCount5
);
508 EXPECT_EQ(2, AnalyzedInstrCount5
); // Only 'g' and 'h' were cached.
509 EXPECT_EQ(9, AnalyzedFunctionCount5
);
511 // Validate the analysis counters:
512 // first run over 3 functions, then module pass invalidates
513 // second run over 3 functions, nothing invalidates
514 // third run over 0 functions, but 1 function invalidated
515 // fourth run over 1 function
516 // fifth run invalidates 1 function first, but runs over 0 functions
517 EXPECT_EQ(7, FunctionAnalysisRuns
);
519 EXPECT_EQ(1, ModuleAnalysisRuns
);
522 // A customized pass manager that passes extra arguments through the
524 typedef AnalysisManager
<Function
, int> CustomizedAnalysisManager
;
525 typedef PassManager
<Function
, CustomizedAnalysisManager
, int, int &>
526 CustomizedPassManager
;
528 class CustomizedAnalysis
: public AnalysisInfoMixin
<CustomizedAnalysis
> {
531 Result(int I
) : I(I
) {}
535 Result
run(Function
&F
, CustomizedAnalysisManager
&AM
, int I
) {
540 friend AnalysisInfoMixin
<CustomizedAnalysis
>;
541 static AnalysisKey Key
;
544 AnalysisKey
CustomizedAnalysis::Key
;
546 struct CustomizedPass
: PassInfoMixin
<CustomizedPass
> {
547 std::function
<void(CustomizedAnalysis::Result
&, int &)> Callback
;
549 template <typename CallbackT
>
550 CustomizedPass(CallbackT Callback
) : Callback(Callback
) {}
552 PreservedAnalyses
run(Function
&F
, CustomizedAnalysisManager
&AM
, int I
,
554 Callback(AM
.getResult
<CustomizedAnalysis
>(F
, I
), O
);
555 return PreservedAnalyses::none();
559 TEST_F(PassManagerTest
, CustomizedPassManagerArgs
) {
560 CustomizedAnalysisManager AM
;
561 AM
.registerPass([&] { return CustomizedAnalysis(); });
562 PassInstrumentationCallbacks PIC
;
563 AM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
565 CustomizedPassManager PM
;
567 // Add an instance of the customized pass that just accumulates the input
568 // after it is round-tripped through the analysis.
571 CustomizedPass([](CustomizedAnalysis::Result
&R
, int &O
) { O
+= R
.I
; }));
573 // Run this over every function with the input of 42.
574 for (Function
&F
: *M
)
575 PM
.run(F
, AM
, 42, Result
);
577 // And ensure that we accumulated the correct result.
578 EXPECT_EQ(42 * (int)M
->size(), Result
);
581 /// A test analysis pass which caches in its result another analysis pass and
582 /// uses it to serve queries. This requires the result to invalidate itself
583 /// when its dependency is invalidated.
584 struct TestIndirectFunctionAnalysis
585 : public AnalysisInfoMixin
<TestIndirectFunctionAnalysis
> {
587 Result(TestFunctionAnalysis::Result
&FDep
, TestModuleAnalysis::Result
&MDep
)
588 : FDep(FDep
), MDep(MDep
) {}
589 TestFunctionAnalysis::Result
&FDep
;
590 TestModuleAnalysis::Result
&MDep
;
592 bool invalidate(Function
&F
, const PreservedAnalyses
&PA
,
593 FunctionAnalysisManager::Invalidator
&Inv
) {
594 auto PAC
= PA
.getChecker
<TestIndirectFunctionAnalysis
>();
595 return !(PAC
.preserved() ||
596 PAC
.preservedSet
<AllAnalysesOn
<Function
>>()) ||
597 Inv
.invalidate
<TestFunctionAnalysis
>(F
, PA
);
601 TestIndirectFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
603 /// Run the analysis pass over the function and return a result.
604 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
606 auto &FDep
= AM
.getResult
<TestFunctionAnalysis
>(F
);
607 auto &Proxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
608 const ModuleAnalysisManager
&MAM
= Proxy
.getManager();
609 // For the test, we insist that the module analysis starts off in the
611 auto &MDep
= *MAM
.getCachedResult
<TestModuleAnalysis
>(*F
.getParent());
612 // And register the dependency as module analysis dependencies have to be
613 // pre-registered on the proxy.
614 Proxy
.registerOuterAnalysisInvalidation
<TestModuleAnalysis
,
615 TestIndirectFunctionAnalysis
>();
616 return Result(FDep
, MDep
);
620 friend AnalysisInfoMixin
<TestIndirectFunctionAnalysis
>;
621 static AnalysisKey Key
;
626 AnalysisKey
TestIndirectFunctionAnalysis::Key
;
628 /// A test analysis pass which chaches in its result the result from the above
629 /// indirect analysis pass.
631 /// This allows us to ensure that whenever an analysis pass is invalidated due
632 /// to dependencies (especially dependencies across IR units that trigger
633 /// asynchronous invalidation) we correctly detect that this may in turn cause
634 /// other analysis to be invalidated.
635 struct TestDoublyIndirectFunctionAnalysis
636 : public AnalysisInfoMixin
<TestDoublyIndirectFunctionAnalysis
> {
638 Result(TestIndirectFunctionAnalysis::Result
&IDep
) : IDep(IDep
) {}
639 TestIndirectFunctionAnalysis::Result
&IDep
;
641 bool invalidate(Function
&F
, const PreservedAnalyses
&PA
,
642 FunctionAnalysisManager::Invalidator
&Inv
) {
643 auto PAC
= PA
.getChecker
<TestDoublyIndirectFunctionAnalysis
>();
644 return !(PAC
.preserved() ||
645 PAC
.preservedSet
<AllAnalysesOn
<Function
>>()) ||
646 Inv
.invalidate
<TestIndirectFunctionAnalysis
>(F
, PA
);
650 TestDoublyIndirectFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
652 /// Run the analysis pass over the function and return a result.
653 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
655 auto &IDep
= AM
.getResult
<TestIndirectFunctionAnalysis
>(F
);
660 friend AnalysisInfoMixin
<TestDoublyIndirectFunctionAnalysis
>;
661 static AnalysisKey Key
;
666 AnalysisKey
TestDoublyIndirectFunctionAnalysis::Key
;
668 struct LambdaPass
: public PassInfoMixin
<LambdaPass
> {
669 using FuncT
= std::function
<PreservedAnalyses(Function
&, FunctionAnalysisManager
&)>;
671 LambdaPass(FuncT Func
) : Func(std::move(Func
)) {}
673 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
680 TEST_F(PassManagerTest
, IndirectAnalysisInvalidation
) {
681 FunctionAnalysisManager
FAM(/*DebugLogging*/ true);
682 int FunctionAnalysisRuns
= 0, ModuleAnalysisRuns
= 0,
683 IndirectAnalysisRuns
= 0, DoublyIndirectAnalysisRuns
= 0;
684 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
686 [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns
); });
687 FAM
.registerPass([&] {
688 return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns
);
691 ModuleAnalysisManager
MAM(/*DebugLogging*/ true);
692 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
693 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
694 FAM
.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM
); });
696 PassInstrumentationCallbacks PIC
;
697 MAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
698 FAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
700 int InstrCount
= 0, FunctionCount
= 0;
701 ModulePassManager
MPM(/*DebugLogging*/ true);
702 FunctionPassManager
FPM(/*DebugLogging*/ true);
703 // First just use the analysis to get the instruction count, and preserve
705 FPM
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
706 auto &DoublyIndirectResult
=
707 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
708 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
709 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
710 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
711 return PreservedAnalyses::all();
714 // - both analyses for "f",
715 // - just the underlying (indirect) analysis for "g", and
716 // - just the direct analysis for "h".
717 FPM
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
718 auto &DoublyIndirectResult
=
719 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
720 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
721 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
722 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
723 auto PA
= PreservedAnalyses::none();
724 if (F
.getName() == "g")
725 PA
.preserve
<TestFunctionAnalysis
>();
726 else if (F
.getName() == "h")
727 PA
.preserve
<TestIndirectFunctionAnalysis
>();
730 // Finally, use the analysis again on each function, forcing re-computation
732 FPM
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
733 auto &DoublyIndirectResult
=
734 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
735 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
736 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
737 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
738 return PreservedAnalyses::all();
741 // Create a second function pass manager. This will cause the module-level
742 // invalidation to occur, which will force yet another invalidation of the
743 // indirect function-level analysis as the module analysis it depends on gets
745 FunctionPassManager
FPM2(/*DebugLogging*/ true);
746 FPM2
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
747 auto &DoublyIndirectResult
=
748 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
749 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
750 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
751 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
752 return PreservedAnalyses::all();
755 // Add a requires pass to populate the module analysis and then our function
757 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
758 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
759 // Now require the module analysis again (it will have been invalidated once)
760 // and then use it again from a function pass manager.
761 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
762 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2
)));
765 // There are generally two possible runs for each of the three functions. But
766 // for one function, we only invalidate the indirect analysis so the base one
767 // only gets run five times.
768 EXPECT_EQ(5, FunctionAnalysisRuns
);
769 // The module analysis pass should be run twice here.
770 EXPECT_EQ(2, ModuleAnalysisRuns
);
771 // The indirect analysis is invalidated for each function (either directly or
772 // indirectly) and run twice for each.
773 EXPECT_EQ(9, IndirectAnalysisRuns
);
774 EXPECT_EQ(9, DoublyIndirectAnalysisRuns
);
776 // There are five instructions in the module and we add the count four
778 EXPECT_EQ(5 * 4, InstrCount
);
780 // There are three functions and we count them four times for each of the
782 EXPECT_EQ(3 * 4 * 3, FunctionCount
);