1 //===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//
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
7 //===----------------------------------------------------------------------===//
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/Support/SourceMgr.h"
15 #include "gtest/gtest.h"
21 class TestFunctionAnalysis
: public AnalysisInfoMixin
<TestFunctionAnalysis
> {
24 Result(int Count
) : InstructionCount(Count
) {}
28 TestFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
30 /// Run the analysis pass over the function and return a result.
31 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
34 for (Function::iterator BBI
= F
.begin(), BBE
= F
.end(); BBI
!= BBE
; ++BBI
)
35 for (BasicBlock::iterator II
= BBI
->begin(), IE
= BBI
->end(); II
!= IE
;
42 friend AnalysisInfoMixin
<TestFunctionAnalysis
>;
43 static AnalysisKey Key
;
48 AnalysisKey
TestFunctionAnalysis::Key
;
50 class TestModuleAnalysis
: public AnalysisInfoMixin
<TestModuleAnalysis
> {
53 Result(int Count
) : FunctionCount(Count
) {}
57 TestModuleAnalysis(int &Runs
) : Runs(Runs
) {}
59 Result
run(Module
&M
, ModuleAnalysisManager
&AM
) {
62 for (Module::iterator I
= M
.begin(), E
= M
.end(); I
!= E
; ++I
)
68 friend AnalysisInfoMixin
<TestModuleAnalysis
>;
69 static AnalysisKey Key
;
74 AnalysisKey
TestModuleAnalysis::Key
;
76 struct TestModulePass
: PassInfoMixin
<TestModulePass
> {
77 TestModulePass(int &RunCount
) : RunCount(RunCount
) {}
79 PreservedAnalyses
run(Module
&M
, ModuleAnalysisManager
&) {
81 return PreservedAnalyses::none();
87 struct TestPreservingModulePass
: PassInfoMixin
<TestPreservingModulePass
> {
88 PreservedAnalyses
run(Module
&M
, ModuleAnalysisManager
&) {
89 return PreservedAnalyses::all();
93 struct TestFunctionPass
: PassInfoMixin
<TestFunctionPass
> {
94 TestFunctionPass(int &RunCount
, int &AnalyzedInstrCount
,
95 int &AnalyzedFunctionCount
,
96 bool OnlyUseCachedResults
= false)
97 : RunCount(RunCount
), AnalyzedInstrCount(AnalyzedInstrCount
),
98 AnalyzedFunctionCount(AnalyzedFunctionCount
),
99 OnlyUseCachedResults(OnlyUseCachedResults
) {}
101 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
104 const ModuleAnalysisManager
&MAM
=
105 AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
).getManager();
106 if (TestModuleAnalysis::Result
*TMA
=
107 MAM
.getCachedResult
<TestModuleAnalysis
>(*F
.getParent()))
108 AnalyzedFunctionCount
+= TMA
->FunctionCount
;
110 if (OnlyUseCachedResults
) {
111 // Hack to force the use of the cached interface.
112 if (TestFunctionAnalysis::Result
*AR
=
113 AM
.getCachedResult
<TestFunctionAnalysis
>(F
))
114 AnalyzedInstrCount
+= AR
->InstructionCount
;
116 // Typical path just runs the analysis as needed.
117 TestFunctionAnalysis::Result
&AR
= AM
.getResult
<TestFunctionAnalysis
>(F
);
118 AnalyzedInstrCount
+= AR
.InstructionCount
;
121 return PreservedAnalyses::all();
125 int &AnalyzedInstrCount
;
126 int &AnalyzedFunctionCount
;
127 bool OnlyUseCachedResults
;
130 // A test function pass that invalidates all function analyses for a function
131 // with a specific name.
132 struct TestInvalidationFunctionPass
133 : PassInfoMixin
<TestInvalidationFunctionPass
> {
134 TestInvalidationFunctionPass(StringRef FunctionName
) : Name(FunctionName
) {}
136 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
137 return F
.getName() == Name
? PreservedAnalyses::none()
138 : PreservedAnalyses::all();
144 std::unique_ptr
<Module
> parseIR(LLVMContext
&Context
, const char *IR
) {
146 return parseAssemblyString(IR
, Err
, Context
);
149 class PassManagerTest
: public ::testing::Test
{
152 std::unique_ptr
<Module
> M
;
156 : M(parseIR(Context
, "define void @f() {\n"
162 "define void @g() {\n"
165 "define void @h() {\n"
170 TEST(PreservedAnalysesTest
, Basic
) {
171 PreservedAnalyses PA1
= PreservedAnalyses();
173 auto PAC
= PA1
.getChecker
<TestFunctionAnalysis
>();
174 EXPECT_FALSE(PAC
.preserved());
175 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
178 auto PAC
= PA1
.getChecker
<TestModuleAnalysis
>();
179 EXPECT_FALSE(PAC
.preserved());
180 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Module
>>());
182 auto PA2
= PreservedAnalyses::none();
184 auto PAC
= PA2
.getChecker
<TestFunctionAnalysis
>();
185 EXPECT_FALSE(PAC
.preserved());
186 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
188 auto PA3
= PreservedAnalyses::all();
190 auto PAC
= PA3
.getChecker
<TestFunctionAnalysis
>();
191 EXPECT_TRUE(PAC
.preserved());
192 EXPECT_TRUE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
194 PreservedAnalyses PA4
= PA1
;
196 auto PAC
= PA4
.getChecker
<TestFunctionAnalysis
>();
197 EXPECT_FALSE(PAC
.preserved());
198 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
202 auto PAC
= PA4
.getChecker
<TestFunctionAnalysis
>();
203 EXPECT_TRUE(PAC
.preserved());
204 EXPECT_TRUE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
206 PA4
= std::move(PA2
);
208 auto PAC
= PA4
.getChecker
<TestFunctionAnalysis
>();
209 EXPECT_FALSE(PAC
.preserved());
210 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
212 auto PA5
= PreservedAnalyses::allInSet
<AllAnalysesOn
<Function
>>();
214 auto PAC
= PA5
.getChecker
<TestFunctionAnalysis
>();
215 EXPECT_FALSE(PAC
.preserved());
216 EXPECT_TRUE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
217 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Module
>>());
221 TEST(PreservedAnalysesTest
, Preserve
) {
222 auto PA
= PreservedAnalyses::none();
223 PA
.preserve
<TestFunctionAnalysis
>();
224 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
225 EXPECT_FALSE(PA
.getChecker
<TestModuleAnalysis
>().preserved());
226 PA
.preserve
<TestModuleAnalysis
>();
227 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
228 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>().preserved());
230 // Redundant calls are fine.
231 PA
.preserve
<TestFunctionAnalysis
>();
232 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
233 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>().preserved());
236 TEST(PreservedAnalysesTest
, PreserveSets
) {
237 auto PA
= PreservedAnalyses::none();
238 PA
.preserveSet
<AllAnalysesOn
<Function
>>();
239 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>()
240 .preservedSet
<AllAnalysesOn
<Function
>>());
241 EXPECT_FALSE(PA
.getChecker
<TestModuleAnalysis
>()
242 .preservedSet
<AllAnalysesOn
<Module
>>());
243 PA
.preserveSet
<AllAnalysesOn
<Module
>>();
244 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>()
245 .preservedSet
<AllAnalysesOn
<Function
>>());
246 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>()
247 .preservedSet
<AllAnalysesOn
<Module
>>());
250 PA
.preserve
<TestFunctionAnalysis
>();
251 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>()
252 .preservedSet
<AllAnalysesOn
<Function
>>());
253 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>()
254 .preservedSet
<AllAnalysesOn
<Module
>>());
256 // Redundant calls are fine.
257 PA
.preserveSet
<AllAnalysesOn
<Module
>>();
258 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>()
259 .preservedSet
<AllAnalysesOn
<Function
>>());
260 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>()
261 .preservedSet
<AllAnalysesOn
<Module
>>());
264 TEST(PreservedAnalysisTest
, Intersect
) {
265 // Setup the initial sets.
266 auto PA1
= PreservedAnalyses::none();
267 PA1
.preserve
<TestFunctionAnalysis
>();
268 PA1
.preserveSet
<AllAnalysesOn
<Module
>>();
269 auto PA2
= PreservedAnalyses::none();
270 PA2
.preserve
<TestFunctionAnalysis
>();
271 PA2
.preserveSet
<AllAnalysesOn
<Function
>>();
272 PA2
.preserve
<TestModuleAnalysis
>();
273 PA2
.preserveSet
<AllAnalysesOn
<Module
>>();
274 auto PA3
= PreservedAnalyses::none();
275 PA3
.preserve
<TestModuleAnalysis
>();
276 PA3
.preserveSet
<AllAnalysesOn
<Function
>>();
278 // Self intersection is a no-op.
279 auto Intersected
= PA1
;
280 Intersected
.intersect(PA1
);
281 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
282 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
283 .preservedSet
<AllAnalysesOn
<Function
>>());
284 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
285 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
286 .preservedSet
<AllAnalysesOn
<Module
>>());
288 // Intersecting with all is a no-op.
289 Intersected
.intersect(PreservedAnalyses::all());
290 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
291 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
292 .preservedSet
<AllAnalysesOn
<Function
>>());
293 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
294 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
295 .preservedSet
<AllAnalysesOn
<Module
>>());
297 // Intersecting a narrow set with a more broad set is the narrow set.
298 Intersected
.intersect(PA2
);
299 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
300 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
301 .preservedSet
<AllAnalysesOn
<Function
>>());
302 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
303 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
304 .preservedSet
<AllAnalysesOn
<Module
>>());
306 // Intersecting a broad set with a more narrow set is the narrow set.
308 Intersected
.intersect(PA1
);
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
>>());
316 // Intersecting with empty clears.
317 Intersected
.intersect(PreservedAnalyses::none());
318 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
319 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
320 .preservedSet
<AllAnalysesOn
<Function
>>());
321 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
322 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>()
323 .preservedSet
<AllAnalysesOn
<Module
>>());
325 // Intersecting non-overlapping clears.
327 Intersected
.intersect(PA3
);
328 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
329 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
330 .preservedSet
<AllAnalysesOn
<Function
>>());
331 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
332 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>()
333 .preservedSet
<AllAnalysesOn
<Module
>>());
335 // Intersecting with moves works in when there is storage on both sides.
338 Intersected
.intersect(std::move(Tmp
));
339 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
340 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
341 .preservedSet
<AllAnalysesOn
<Function
>>());
342 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
343 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
344 .preservedSet
<AllAnalysesOn
<Module
>>());
346 // Intersecting with move works for incoming all and existing all.
347 auto Tmp2
= PreservedAnalyses::all();
348 Intersected
.intersect(std::move(Tmp2
));
349 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
350 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
351 .preservedSet
<AllAnalysesOn
<Function
>>());
352 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
353 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
354 .preservedSet
<AllAnalysesOn
<Module
>>());
355 Intersected
= PreservedAnalyses::all();
357 Intersected
.intersect(std::move(Tmp3
));
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
>>());
366 TEST(PreservedAnalysisTest
, Abandon
) {
367 auto PA
= PreservedAnalyses::none();
369 // We can abandon things after they are preserved.
370 PA
.preserve
<TestFunctionAnalysis
>();
371 PA
.abandon
<TestFunctionAnalysis
>();
372 EXPECT_FALSE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
374 // Repeated is fine, and abandoning if they were never preserved is fine.
375 PA
.abandon
<TestFunctionAnalysis
>();
376 EXPECT_FALSE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
377 PA
.abandon
<TestModuleAnalysis
>();
378 EXPECT_FALSE(PA
.getChecker
<TestModuleAnalysis
>().preserved());
380 // Even if the sets are preserved, the abandoned analyses' checker won't
381 // return true for those sets.
382 PA
.preserveSet
<AllAnalysesOn
<Function
>>();
383 PA
.preserveSet
<AllAnalysesOn
<Module
>>();
384 EXPECT_FALSE(PA
.getChecker
<TestFunctionAnalysis
>()
385 .preservedSet
<AllAnalysesOn
<Function
>>());
386 EXPECT_FALSE(PA
.getChecker
<TestModuleAnalysis
>()
387 .preservedSet
<AllAnalysesOn
<Module
>>());
389 // But an arbitrary (opaque) analysis will still observe the sets as
390 // preserved. This also checks that we can use an explicit ID rather than
392 AnalysisKey FakeKey
, *FakeID
= &FakeKey
;
393 EXPECT_TRUE(PA
.getChecker(FakeID
).preservedSet
<AllAnalysesOn
<Function
>>());
394 EXPECT_TRUE(PA
.getChecker(FakeID
).preservedSet
<AllAnalysesOn
<Module
>>());
397 TEST_F(PassManagerTest
, Basic
) {
398 FunctionAnalysisManager
FAM(/*DebugLogging*/ true);
399 int FunctionAnalysisRuns
= 0;
400 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
402 ModuleAnalysisManager
MAM(/*DebugLogging*/ true);
403 int ModuleAnalysisRuns
= 0;
404 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
405 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
406 FAM
.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM
); });
408 MAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
409 FAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
411 ModulePassManager MPM
;
413 // Count the runs over a Function.
414 int FunctionPassRunCount1
= 0;
415 int AnalyzedInstrCount1
= 0;
416 int AnalyzedFunctionCount1
= 0;
418 // Pointless scoped copy to test move assignment.
419 ModulePassManager
NestedMPM(/*DebugLogging*/ true);
420 FunctionPassManager FPM
;
422 // Pointless scope to test move assignment.
423 FunctionPassManager
NestedFPM(/*DebugLogging*/ true);
424 NestedFPM
.addPass(TestFunctionPass(
425 FunctionPassRunCount1
, AnalyzedInstrCount1
, AnalyzedFunctionCount1
));
426 FPM
= std::move(NestedFPM
);
428 NestedMPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
429 MPM
= std::move(NestedMPM
);
432 // Count the runs over a module.
433 int ModulePassRunCount
= 0;
434 MPM
.addPass(TestModulePass(ModulePassRunCount
));
436 // Count the runs over a Function in a separate manager.
437 int FunctionPassRunCount2
= 0;
438 int AnalyzedInstrCount2
= 0;
439 int AnalyzedFunctionCount2
= 0;
441 FunctionPassManager
FPM(/*DebugLogging*/ true);
442 FPM
.addPass(TestFunctionPass(FunctionPassRunCount2
, AnalyzedInstrCount2
,
443 AnalyzedFunctionCount2
));
444 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
447 // A third function pass manager but with only preserving intervening passes
448 // and with a function pass that invalidates exactly one analysis.
449 MPM
.addPass(TestPreservingModulePass());
450 int FunctionPassRunCount3
= 0;
451 int AnalyzedInstrCount3
= 0;
452 int AnalyzedFunctionCount3
= 0;
454 FunctionPassManager
FPM(/*DebugLogging*/ true);
455 FPM
.addPass(TestFunctionPass(FunctionPassRunCount3
, AnalyzedInstrCount3
,
456 AnalyzedFunctionCount3
));
457 FPM
.addPass(TestInvalidationFunctionPass("f"));
458 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
461 // A fourth function pass manager but with only preserving intervening
462 // passes but triggering the module analysis.
463 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
464 int FunctionPassRunCount4
= 0;
465 int AnalyzedInstrCount4
= 0;
466 int AnalyzedFunctionCount4
= 0;
468 FunctionPassManager FPM
;
469 FPM
.addPass(TestFunctionPass(FunctionPassRunCount4
, AnalyzedInstrCount4
,
470 AnalyzedFunctionCount4
));
471 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
474 // A fifth function pass manager which invalidates one function first but
475 // uses only cached results.
476 int FunctionPassRunCount5
= 0;
477 int AnalyzedInstrCount5
= 0;
478 int AnalyzedFunctionCount5
= 0;
480 FunctionPassManager
FPM(/*DebugLogging*/ true);
481 FPM
.addPass(TestInvalidationFunctionPass("f"));
482 FPM
.addPass(TestFunctionPass(FunctionPassRunCount5
, AnalyzedInstrCount5
,
483 AnalyzedFunctionCount5
,
484 /*OnlyUseCachedResults=*/true));
485 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
490 // Validate module pass counters.
491 EXPECT_EQ(1, ModulePassRunCount
);
493 // Validate all function pass counter sets are the same.
494 EXPECT_EQ(3, FunctionPassRunCount1
);
495 EXPECT_EQ(5, AnalyzedInstrCount1
);
496 EXPECT_EQ(0, AnalyzedFunctionCount1
);
497 EXPECT_EQ(3, FunctionPassRunCount2
);
498 EXPECT_EQ(5, AnalyzedInstrCount2
);
499 EXPECT_EQ(0, AnalyzedFunctionCount2
);
500 EXPECT_EQ(3, FunctionPassRunCount3
);
501 EXPECT_EQ(5, AnalyzedInstrCount3
);
502 EXPECT_EQ(0, AnalyzedFunctionCount3
);
503 EXPECT_EQ(3, FunctionPassRunCount4
);
504 EXPECT_EQ(5, AnalyzedInstrCount4
);
505 EXPECT_EQ(9, AnalyzedFunctionCount4
);
506 EXPECT_EQ(3, FunctionPassRunCount5
);
507 EXPECT_EQ(2, AnalyzedInstrCount5
); // Only 'g' and 'h' were cached.
508 EXPECT_EQ(9, AnalyzedFunctionCount5
);
510 // Validate the analysis counters:
511 // first run over 3 functions, then module pass invalidates
512 // second run over 3 functions, nothing invalidates
513 // third run over 0 functions, but 1 function invalidated
514 // fourth run over 1 function
515 // fifth run invalidates 1 function first, but runs over 0 functions
516 EXPECT_EQ(7, FunctionAnalysisRuns
);
518 EXPECT_EQ(1, ModuleAnalysisRuns
);
521 // A customized pass manager that passes extra arguments through the
523 typedef AnalysisManager
<Function
, int> CustomizedAnalysisManager
;
524 typedef PassManager
<Function
, CustomizedAnalysisManager
, int, int &>
525 CustomizedPassManager
;
527 class CustomizedAnalysis
: public AnalysisInfoMixin
<CustomizedAnalysis
> {
530 Result(int I
) : I(I
) {}
534 Result
run(Function
&F
, CustomizedAnalysisManager
&AM
, int I
) {
539 friend AnalysisInfoMixin
<CustomizedAnalysis
>;
540 static AnalysisKey Key
;
543 AnalysisKey
CustomizedAnalysis::Key
;
545 struct CustomizedPass
: PassInfoMixin
<CustomizedPass
> {
546 std::function
<void(CustomizedAnalysis::Result
&, int &)> Callback
;
548 template <typename CallbackT
>
549 CustomizedPass(CallbackT Callback
) : Callback(Callback
) {}
551 PreservedAnalyses
run(Function
&F
, CustomizedAnalysisManager
&AM
, int I
,
553 Callback(AM
.getResult
<CustomizedAnalysis
>(F
, I
), O
);
554 return PreservedAnalyses::none();
558 TEST_F(PassManagerTest
, CustomizedPassManagerArgs
) {
559 CustomizedAnalysisManager AM
;
560 AM
.registerPass([&] { return CustomizedAnalysis(); });
561 PassInstrumentationCallbacks PIC
;
562 AM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
564 CustomizedPassManager PM
;
566 // Add an instance of the customized pass that just accumulates the input
567 // after it is round-tripped through the analysis.
570 CustomizedPass([](CustomizedAnalysis::Result
&R
, int &O
) { O
+= R
.I
; }));
572 // Run this over every function with the input of 42.
573 for (Function
&F
: *M
)
574 PM
.run(F
, AM
, 42, Result
);
576 // And ensure that we accumulated the correct result.
577 EXPECT_EQ(42 * (int)M
->size(), Result
);
580 /// A test analysis pass which caches in its result another analysis pass and
581 /// uses it to serve queries. This requires the result to invalidate itself
582 /// when its dependency is invalidated.
583 struct TestIndirectFunctionAnalysis
584 : public AnalysisInfoMixin
<TestIndirectFunctionAnalysis
> {
586 Result(TestFunctionAnalysis::Result
&FDep
, TestModuleAnalysis::Result
&MDep
)
587 : FDep(FDep
), MDep(MDep
) {}
588 TestFunctionAnalysis::Result
&FDep
;
589 TestModuleAnalysis::Result
&MDep
;
591 bool invalidate(Function
&F
, const PreservedAnalyses
&PA
,
592 FunctionAnalysisManager::Invalidator
&Inv
) {
593 auto PAC
= PA
.getChecker
<TestIndirectFunctionAnalysis
>();
594 return !(PAC
.preserved() ||
595 PAC
.preservedSet
<AllAnalysesOn
<Function
>>()) ||
596 Inv
.invalidate
<TestFunctionAnalysis
>(F
, PA
);
600 TestIndirectFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
602 /// Run the analysis pass over the function and return a result.
603 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
605 auto &FDep
= AM
.getResult
<TestFunctionAnalysis
>(F
);
606 auto &Proxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
607 const ModuleAnalysisManager
&MAM
= Proxy
.getManager();
608 // For the test, we insist that the module analysis starts off in the
610 auto &MDep
= *MAM
.getCachedResult
<TestModuleAnalysis
>(*F
.getParent());
611 // And register the dependency as module analysis dependencies have to be
612 // pre-registered on the proxy.
613 Proxy
.registerOuterAnalysisInvalidation
<TestModuleAnalysis
,
614 TestIndirectFunctionAnalysis
>();
615 return Result(FDep
, MDep
);
619 friend AnalysisInfoMixin
<TestIndirectFunctionAnalysis
>;
620 static AnalysisKey Key
;
625 AnalysisKey
TestIndirectFunctionAnalysis::Key
;
627 /// A test analysis pass which chaches in its result the result from the above
628 /// indirect analysis pass.
630 /// This allows us to ensure that whenever an analysis pass is invalidated due
631 /// to dependencies (especially dependencies across IR units that trigger
632 /// asynchronous invalidation) we correctly detect that this may in turn cause
633 /// other analysis to be invalidated.
634 struct TestDoublyIndirectFunctionAnalysis
635 : public AnalysisInfoMixin
<TestDoublyIndirectFunctionAnalysis
> {
637 Result(TestIndirectFunctionAnalysis::Result
&IDep
) : IDep(IDep
) {}
638 TestIndirectFunctionAnalysis::Result
&IDep
;
640 bool invalidate(Function
&F
, const PreservedAnalyses
&PA
,
641 FunctionAnalysisManager::Invalidator
&Inv
) {
642 auto PAC
= PA
.getChecker
<TestDoublyIndirectFunctionAnalysis
>();
643 return !(PAC
.preserved() ||
644 PAC
.preservedSet
<AllAnalysesOn
<Function
>>()) ||
645 Inv
.invalidate
<TestIndirectFunctionAnalysis
>(F
, PA
);
649 TestDoublyIndirectFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
651 /// Run the analysis pass over the function and return a result.
652 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
654 auto &IDep
= AM
.getResult
<TestIndirectFunctionAnalysis
>(F
);
659 friend AnalysisInfoMixin
<TestDoublyIndirectFunctionAnalysis
>;
660 static AnalysisKey Key
;
665 AnalysisKey
TestDoublyIndirectFunctionAnalysis::Key
;
667 struct LambdaPass
: public PassInfoMixin
<LambdaPass
> {
668 using FuncT
= std::function
<PreservedAnalyses(Function
&, FunctionAnalysisManager
&)>;
670 LambdaPass(FuncT Func
) : Func(std::move(Func
)) {}
672 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
679 TEST_F(PassManagerTest
, IndirectAnalysisInvalidation
) {
680 FunctionAnalysisManager
FAM(/*DebugLogging*/ true);
681 int FunctionAnalysisRuns
= 0, ModuleAnalysisRuns
= 0,
682 IndirectAnalysisRuns
= 0, DoublyIndirectAnalysisRuns
= 0;
683 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
685 [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns
); });
686 FAM
.registerPass([&] {
687 return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns
);
690 ModuleAnalysisManager
MAM(/*DebugLogging*/ true);
691 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
692 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
693 FAM
.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM
); });
695 PassInstrumentationCallbacks PIC
;
696 MAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
697 FAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
699 int InstrCount
= 0, FunctionCount
= 0;
700 ModulePassManager
MPM(/*DebugLogging*/ true);
701 FunctionPassManager
FPM(/*DebugLogging*/ true);
702 // First just use the analysis to get the instruction count, and preserve
704 FPM
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
705 auto &DoublyIndirectResult
=
706 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
707 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
708 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
709 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
710 return PreservedAnalyses::all();
713 // - both analyses for "f",
714 // - just the underlying (indirect) analysis for "g", and
715 // - just the direct analysis for "h".
716 FPM
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
717 auto &DoublyIndirectResult
=
718 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
719 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
720 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
721 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
722 auto PA
= PreservedAnalyses::none();
723 if (F
.getName() == "g")
724 PA
.preserve
<TestFunctionAnalysis
>();
725 else if (F
.getName() == "h")
726 PA
.preserve
<TestIndirectFunctionAnalysis
>();
729 // Finally, use the analysis again on each function, forcing re-computation
731 FPM
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
732 auto &DoublyIndirectResult
=
733 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
734 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
735 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
736 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
737 return PreservedAnalyses::all();
740 // Create a second function pass manager. This will cause the module-level
741 // invalidation to occur, which will force yet another invalidation of the
742 // indirect function-level analysis as the module analysis it depends on gets
744 FunctionPassManager
FPM2(/*DebugLogging*/ true);
745 FPM2
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
746 auto &DoublyIndirectResult
=
747 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
748 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
749 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
750 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
751 return PreservedAnalyses::all();
754 // Add a requires pass to populate the module analysis and then our function
756 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
757 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
758 // Now require the module analysis again (it will have been invalidated once)
759 // and then use it again from a function pass manager.
760 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
761 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2
)));
764 // There are generally two possible runs for each of the three functions. But
765 // for one function, we only invalidate the indirect analysis so the base one
766 // only gets run five times.
767 EXPECT_EQ(5, FunctionAnalysisRuns
);
768 // The module analysis pass should be run twice here.
769 EXPECT_EQ(2, ModuleAnalysisRuns
);
770 // The indirect analysis is invalidated for each function (either directly or
771 // indirectly) and run twice for each.
772 EXPECT_EQ(9, IndirectAnalysisRuns
);
773 EXPECT_EQ(9, DoublyIndirectAnalysisRuns
);
775 // There are five instructions in the module and we add the count four
777 EXPECT_EQ(5 * 4, InstrCount
);
779 // There are three functions and we count them four times for each of the
781 EXPECT_EQ(3 * 4 * 3, FunctionCount
);