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/Analysis/AssumptionCache.h"
11 #include "llvm/Analysis/TargetTransformInfo.h"
12 #include "llvm/AsmParser/Parser.h"
13 #include "llvm/IR/Dominators.h"
14 #include "llvm/IR/Function.h"
15 #include "llvm/IR/LLVMContext.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/IR/PassManagerImpl.h"
18 #include "llvm/Passes/StandardInstrumentations.h"
19 #include "llvm/Support/SourceMgr.h"
20 #include "llvm/Transforms/Scalar/SimplifyCFG.h"
21 #include "gtest/gtest.h"
27 class TestFunctionAnalysis
: public AnalysisInfoMixin
<TestFunctionAnalysis
> {
30 Result(int Count
) : InstructionCount(Count
) {}
32 bool invalidate(Function
&, const PreservedAnalyses
&PA
,
33 FunctionAnalysisManager::Invalidator
&) {
34 // Check whether the analysis or all analyses on functions have been
36 auto PAC
= PA
.getChecker
<TestFunctionAnalysis
>();
37 return !(PAC
.preserved() || PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
41 TestFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
43 /// Run the analysis pass over the function and return a result.
44 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
47 for (Function::iterator BBI
= F
.begin(), BBE
= F
.end(); BBI
!= BBE
; ++BBI
)
48 for (BasicBlock::iterator II
= BBI
->begin(), IE
= BBI
->end(); II
!= IE
;
55 friend AnalysisInfoMixin
<TestFunctionAnalysis
>;
56 static AnalysisKey Key
;
61 AnalysisKey
TestFunctionAnalysis::Key
;
63 class TestModuleAnalysis
: public AnalysisInfoMixin
<TestModuleAnalysis
> {
66 Result(int Count
) : FunctionCount(Count
) {}
68 bool invalidate(Module
&, const PreservedAnalyses
&PA
,
69 ModuleAnalysisManager::Invalidator
&) {
70 // Check whether the analysis or all analyses on modules have been
72 auto PAC
= PA
.getChecker
<TestModuleAnalysis
>();
73 return !(PAC
.preserved() || PAC
.preservedSet
<AllAnalysesOn
<Module
>>());
77 TestModuleAnalysis(int &Runs
) : Runs(Runs
) {}
79 Result
run(Module
&M
, ModuleAnalysisManager
&AM
) {
82 for (Module::iterator I
= M
.begin(), E
= M
.end(); I
!= E
; ++I
)
88 friend AnalysisInfoMixin
<TestModuleAnalysis
>;
89 static AnalysisKey Key
;
94 AnalysisKey
TestModuleAnalysis::Key
;
96 struct TestModulePass
: PassInfoMixin
<TestModulePass
> {
97 TestModulePass(int &RunCount
) : RunCount(RunCount
) {}
99 PreservedAnalyses
run(Module
&M
, ModuleAnalysisManager
&) {
101 return PreservedAnalyses::none();
107 struct TestPreservingModulePass
: PassInfoMixin
<TestPreservingModulePass
> {
108 PreservedAnalyses
run(Module
&M
, ModuleAnalysisManager
&) {
109 return PreservedAnalyses::all();
113 struct TestFunctionPass
: PassInfoMixin
<TestFunctionPass
> {
114 TestFunctionPass(int &RunCount
, int &AnalyzedInstrCount
,
115 int &AnalyzedFunctionCount
, ModuleAnalysisManager
&MAM
,
116 bool OnlyUseCachedResults
= false)
117 : RunCount(RunCount
), AnalyzedInstrCount(AnalyzedInstrCount
),
118 AnalyzedFunctionCount(AnalyzedFunctionCount
), MAM(MAM
),
119 OnlyUseCachedResults(OnlyUseCachedResults
) {}
121 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
124 // Getting a cached result that isn't stateless through the proxy will
125 // trigger an assert:
126 // auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
127 // Use MAM, for the purposes of this unittest.
128 if (TestModuleAnalysis::Result
*TMA
=
129 MAM
.getCachedResult
<TestModuleAnalysis
>(*F
.getParent())) {
130 AnalyzedFunctionCount
+= TMA
->FunctionCount
;
133 if (OnlyUseCachedResults
) {
134 // Hack to force the use of the cached interface.
135 if (TestFunctionAnalysis::Result
*AR
=
136 AM
.getCachedResult
<TestFunctionAnalysis
>(F
))
137 AnalyzedInstrCount
+= AR
->InstructionCount
;
139 // Typical path just runs the analysis as needed.
140 TestFunctionAnalysis::Result
&AR
= AM
.getResult
<TestFunctionAnalysis
>(F
);
141 AnalyzedInstrCount
+= AR
.InstructionCount
;
144 return PreservedAnalyses::all();
148 int &AnalyzedInstrCount
;
149 int &AnalyzedFunctionCount
;
150 ModuleAnalysisManager
&MAM
;
151 bool OnlyUseCachedResults
;
154 // A test function pass that invalidates all function analyses for a function
155 // with a specific name.
156 struct TestInvalidationFunctionPass
157 : PassInfoMixin
<TestInvalidationFunctionPass
> {
158 TestInvalidationFunctionPass(StringRef FunctionName
) : Name(FunctionName
) {}
160 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
161 return F
.getName() == Name
? PreservedAnalyses::none()
162 : PreservedAnalyses::all();
168 std::unique_ptr
<Module
> parseIR(LLVMContext
&Context
, const char *IR
) {
170 return parseAssemblyString(IR
, Err
, Context
);
173 class PassManagerTest
: public ::testing::Test
{
176 std::unique_ptr
<Module
> M
;
180 : M(parseIR(Context
, "define void @f() {\n"
186 "define void @g() {\n"
189 "define void @h() {\n"
194 TEST(PreservedAnalysesTest
, Basic
) {
195 PreservedAnalyses PA1
= PreservedAnalyses();
197 auto PAC
= PA1
.getChecker
<TestFunctionAnalysis
>();
198 EXPECT_FALSE(PAC
.preserved());
199 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
202 auto PAC
= PA1
.getChecker
<TestModuleAnalysis
>();
203 EXPECT_FALSE(PAC
.preserved());
204 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Module
>>());
206 auto PA2
= PreservedAnalyses::none();
208 auto PAC
= PA2
.getChecker
<TestFunctionAnalysis
>();
209 EXPECT_FALSE(PAC
.preserved());
210 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
212 auto PA3
= PreservedAnalyses::all();
214 auto PAC
= PA3
.getChecker
<TestFunctionAnalysis
>();
215 EXPECT_TRUE(PAC
.preserved());
216 EXPECT_TRUE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
218 PreservedAnalyses PA4
= PA1
;
220 auto PAC
= PA4
.getChecker
<TestFunctionAnalysis
>();
221 EXPECT_FALSE(PAC
.preserved());
222 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
226 auto PAC
= PA4
.getChecker
<TestFunctionAnalysis
>();
227 EXPECT_TRUE(PAC
.preserved());
228 EXPECT_TRUE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
230 PA4
= std::move(PA2
);
232 auto PAC
= PA4
.getChecker
<TestFunctionAnalysis
>();
233 EXPECT_FALSE(PAC
.preserved());
234 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
236 auto PA5
= PreservedAnalyses::allInSet
<AllAnalysesOn
<Function
>>();
238 auto PAC
= PA5
.getChecker
<TestFunctionAnalysis
>();
239 EXPECT_FALSE(PAC
.preserved());
240 EXPECT_TRUE(PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
241 EXPECT_FALSE(PAC
.preservedSet
<AllAnalysesOn
<Module
>>());
245 TEST(PreservedAnalysesTest
, Preserve
) {
246 auto PA
= PreservedAnalyses::none();
247 PA
.preserve
<TestFunctionAnalysis
>();
248 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
249 EXPECT_FALSE(PA
.getChecker
<TestModuleAnalysis
>().preserved());
250 PA
.preserve
<TestModuleAnalysis
>();
251 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
252 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>().preserved());
254 // Redundant calls are fine.
255 PA
.preserve
<TestFunctionAnalysis
>();
256 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
257 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>().preserved());
260 TEST(PreservedAnalysesTest
, PreserveSets
) {
261 auto PA
= PreservedAnalyses::none();
262 PA
.preserveSet
<AllAnalysesOn
<Function
>>();
263 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>()
264 .preservedSet
<AllAnalysesOn
<Function
>>());
265 EXPECT_FALSE(PA
.getChecker
<TestModuleAnalysis
>()
266 .preservedSet
<AllAnalysesOn
<Module
>>());
267 PA
.preserveSet
<AllAnalysesOn
<Module
>>();
268 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>()
269 .preservedSet
<AllAnalysesOn
<Function
>>());
270 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>()
271 .preservedSet
<AllAnalysesOn
<Module
>>());
274 PA
.preserve
<TestFunctionAnalysis
>();
275 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>()
276 .preservedSet
<AllAnalysesOn
<Function
>>());
277 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>()
278 .preservedSet
<AllAnalysesOn
<Module
>>());
280 // Redundant calls are fine.
281 PA
.preserveSet
<AllAnalysesOn
<Module
>>();
282 EXPECT_TRUE(PA
.getChecker
<TestFunctionAnalysis
>()
283 .preservedSet
<AllAnalysesOn
<Function
>>());
284 EXPECT_TRUE(PA
.getChecker
<TestModuleAnalysis
>()
285 .preservedSet
<AllAnalysesOn
<Module
>>());
288 TEST(PreservedAnalysisTest
, Intersect
) {
289 // Setup the initial sets.
290 auto PA1
= PreservedAnalyses::none();
291 PA1
.preserve
<TestFunctionAnalysis
>();
292 PA1
.preserveSet
<AllAnalysesOn
<Module
>>();
293 auto PA2
= PreservedAnalyses::none();
294 PA2
.preserve
<TestFunctionAnalysis
>();
295 PA2
.preserveSet
<AllAnalysesOn
<Function
>>();
296 PA2
.preserve
<TestModuleAnalysis
>();
297 PA2
.preserveSet
<AllAnalysesOn
<Module
>>();
298 auto PA3
= PreservedAnalyses::none();
299 PA3
.preserve
<TestModuleAnalysis
>();
300 PA3
.preserveSet
<AllAnalysesOn
<Function
>>();
302 // Self intersection is a no-op.
303 auto Intersected
= PA1
;
304 Intersected
.intersect(PA1
);
305 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
306 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
307 .preservedSet
<AllAnalysesOn
<Function
>>());
308 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
309 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
310 .preservedSet
<AllAnalysesOn
<Module
>>());
312 // Intersecting with all is a no-op.
313 Intersected
.intersect(PreservedAnalyses::all());
314 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
315 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
316 .preservedSet
<AllAnalysesOn
<Function
>>());
317 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
318 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
319 .preservedSet
<AllAnalysesOn
<Module
>>());
321 // Intersecting a narrow set with a more broad set is the narrow set.
322 Intersected
.intersect(PA2
);
323 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
324 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
325 .preservedSet
<AllAnalysesOn
<Function
>>());
326 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
327 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
328 .preservedSet
<AllAnalysesOn
<Module
>>());
330 // Intersecting a broad set with a more narrow set is the narrow set.
332 Intersected
.intersect(PA1
);
333 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
334 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
335 .preservedSet
<AllAnalysesOn
<Function
>>());
336 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
337 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
338 .preservedSet
<AllAnalysesOn
<Module
>>());
340 // Intersecting with empty clears.
341 Intersected
.intersect(PreservedAnalyses::none());
342 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
343 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
344 .preservedSet
<AllAnalysesOn
<Function
>>());
345 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
346 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>()
347 .preservedSet
<AllAnalysesOn
<Module
>>());
349 // Intersecting non-overlapping clears.
351 Intersected
.intersect(PA3
);
352 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
353 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
354 .preservedSet
<AllAnalysesOn
<Function
>>());
355 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
356 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>()
357 .preservedSet
<AllAnalysesOn
<Module
>>());
359 // Intersecting with moves works in when there is storage on both sides.
362 Intersected
.intersect(std::move(Tmp
));
363 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
364 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
365 .preservedSet
<AllAnalysesOn
<Function
>>());
366 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
367 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
368 .preservedSet
<AllAnalysesOn
<Module
>>());
370 // Intersecting with move works for incoming all and existing all.
371 auto Tmp2
= PreservedAnalyses::all();
372 Intersected
.intersect(std::move(Tmp2
));
373 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
374 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
375 .preservedSet
<AllAnalysesOn
<Function
>>());
376 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
377 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
378 .preservedSet
<AllAnalysesOn
<Module
>>());
379 Intersected
= PreservedAnalyses::all();
381 Intersected
.intersect(std::move(Tmp3
));
382 EXPECT_TRUE(Intersected
.getChecker
<TestFunctionAnalysis
>().preserved());
383 EXPECT_FALSE(Intersected
.getChecker
<TestFunctionAnalysis
>()
384 .preservedSet
<AllAnalysesOn
<Function
>>());
385 EXPECT_FALSE(Intersected
.getChecker
<TestModuleAnalysis
>().preserved());
386 EXPECT_TRUE(Intersected
.getChecker
<TestModuleAnalysis
>()
387 .preservedSet
<AllAnalysesOn
<Module
>>());
390 TEST(PreservedAnalysisTest
, Abandon
) {
391 auto PA
= PreservedAnalyses::none();
393 // We can abandon things after they are preserved.
394 PA
.preserve
<TestFunctionAnalysis
>();
395 PA
.abandon
<TestFunctionAnalysis
>();
396 EXPECT_FALSE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
398 // Repeated is fine, and abandoning if they were never preserved is fine.
399 PA
.abandon
<TestFunctionAnalysis
>();
400 EXPECT_FALSE(PA
.getChecker
<TestFunctionAnalysis
>().preserved());
401 PA
.abandon
<TestModuleAnalysis
>();
402 EXPECT_FALSE(PA
.getChecker
<TestModuleAnalysis
>().preserved());
404 // Even if the sets are preserved, the abandoned analyses' checker won't
405 // return true for those sets.
406 PA
.preserveSet
<AllAnalysesOn
<Function
>>();
407 PA
.preserveSet
<AllAnalysesOn
<Module
>>();
408 EXPECT_FALSE(PA
.getChecker
<TestFunctionAnalysis
>()
409 .preservedSet
<AllAnalysesOn
<Function
>>());
410 EXPECT_FALSE(PA
.getChecker
<TestModuleAnalysis
>()
411 .preservedSet
<AllAnalysesOn
<Module
>>());
413 // But an arbitrary (opaque) analysis will still observe the sets as
414 // preserved. This also checks that we can use an explicit ID rather than
416 AnalysisKey FakeKey
, *FakeID
= &FakeKey
;
417 EXPECT_TRUE(PA
.getChecker(FakeID
).preservedSet
<AllAnalysesOn
<Function
>>());
418 EXPECT_TRUE(PA
.getChecker(FakeID
).preservedSet
<AllAnalysesOn
<Module
>>());
421 TEST_F(PassManagerTest
, Basic
) {
422 FunctionAnalysisManager FAM
;
423 int FunctionAnalysisRuns
= 0;
424 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
426 ModuleAnalysisManager MAM
;
427 int ModuleAnalysisRuns
= 0;
428 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
429 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
430 FAM
.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM
); });
432 MAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
433 FAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
435 ModulePassManager MPM
;
437 // Count the runs over a Function.
438 int FunctionPassRunCount1
= 0;
439 int AnalyzedInstrCount1
= 0;
440 int AnalyzedFunctionCount1
= 0;
442 // Pointless scoped copy to test move assignment.
443 ModulePassManager NestedMPM
;
444 FunctionPassManager FPM
;
446 // Pointless scope to test move assignment.
447 FunctionPassManager NestedFPM
;
448 NestedFPM
.addPass(TestFunctionPass(FunctionPassRunCount1
,
450 AnalyzedFunctionCount1
, MAM
));
451 FPM
= std::move(NestedFPM
);
453 NestedMPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
454 MPM
= std::move(NestedMPM
);
457 // Count the runs over a module.
458 int ModulePassRunCount
= 0;
459 MPM
.addPass(TestModulePass(ModulePassRunCount
));
461 // Count the runs over a Function in a separate manager.
462 int FunctionPassRunCount2
= 0;
463 int AnalyzedInstrCount2
= 0;
464 int AnalyzedFunctionCount2
= 0;
466 FunctionPassManager FPM
;
467 FPM
.addPass(TestFunctionPass(FunctionPassRunCount2
, AnalyzedInstrCount2
,
468 AnalyzedFunctionCount2
, MAM
));
469 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
472 // A third function pass manager but with only preserving intervening passes
473 // and with a function pass that invalidates exactly one analysis.
474 MPM
.addPass(TestPreservingModulePass());
475 int FunctionPassRunCount3
= 0;
476 int AnalyzedInstrCount3
= 0;
477 int AnalyzedFunctionCount3
= 0;
479 FunctionPassManager FPM
;
480 FPM
.addPass(TestFunctionPass(FunctionPassRunCount3
, AnalyzedInstrCount3
,
481 AnalyzedFunctionCount3
, MAM
));
482 FPM
.addPass(TestInvalidationFunctionPass("f"));
483 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
486 // A fourth function pass manager but with only preserving intervening
487 // passes but triggering the module analysis.
488 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
489 int FunctionPassRunCount4
= 0;
490 int AnalyzedInstrCount4
= 0;
491 int AnalyzedFunctionCount4
= 0;
493 FunctionPassManager FPM
;
494 FPM
.addPass(TestFunctionPass(FunctionPassRunCount4
, AnalyzedInstrCount4
,
495 AnalyzedFunctionCount4
, MAM
));
496 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
499 // A fifth function pass manager which invalidates one function first but
500 // uses only cached results.
501 int FunctionPassRunCount5
= 0;
502 int AnalyzedInstrCount5
= 0;
503 int AnalyzedFunctionCount5
= 0;
505 FunctionPassManager FPM
;
506 FPM
.addPass(TestInvalidationFunctionPass("f"));
507 FPM
.addPass(TestFunctionPass(FunctionPassRunCount5
, AnalyzedInstrCount5
,
508 AnalyzedFunctionCount5
, MAM
,
509 /*OnlyUseCachedResults=*/true));
510 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
515 // Validate module pass counters.
516 EXPECT_EQ(1, ModulePassRunCount
);
518 // Validate all function pass counter sets are the same.
519 EXPECT_EQ(3, FunctionPassRunCount1
);
520 EXPECT_EQ(5, AnalyzedInstrCount1
);
521 EXPECT_EQ(0, AnalyzedFunctionCount1
);
522 EXPECT_EQ(3, FunctionPassRunCount2
);
523 EXPECT_EQ(5, AnalyzedInstrCount2
);
524 EXPECT_EQ(0, AnalyzedFunctionCount2
);
525 EXPECT_EQ(3, FunctionPassRunCount3
);
526 EXPECT_EQ(5, AnalyzedInstrCount3
);
527 EXPECT_EQ(0, AnalyzedFunctionCount3
);
528 EXPECT_EQ(3, FunctionPassRunCount4
);
529 EXPECT_EQ(5, AnalyzedInstrCount4
);
530 EXPECT_EQ(9, AnalyzedFunctionCount4
);
531 EXPECT_EQ(3, FunctionPassRunCount5
);
532 EXPECT_EQ(2, AnalyzedInstrCount5
); // Only 'g' and 'h' were cached.
533 EXPECT_EQ(9, AnalyzedFunctionCount5
);
535 // Validate the analysis counters:
536 // first run over 3 functions, then module pass invalidates
537 // second run over 3 functions, nothing invalidates
538 // third run over 0 functions, but 1 function invalidated
539 // fourth run over 1 function
540 // fifth run invalidates 1 function first, but runs over 0 functions
541 EXPECT_EQ(7, FunctionAnalysisRuns
);
543 EXPECT_EQ(1, ModuleAnalysisRuns
);
546 // A customized pass manager that passes extra arguments through the
548 typedef AnalysisManager
<Function
, int> CustomizedAnalysisManager
;
549 typedef PassManager
<Function
, CustomizedAnalysisManager
, int, int &>
550 CustomizedPassManager
;
552 class CustomizedAnalysis
: public AnalysisInfoMixin
<CustomizedAnalysis
> {
555 Result(int I
) : I(I
) {}
559 Result
run(Function
&F
, CustomizedAnalysisManager
&AM
, int I
) {
564 friend AnalysisInfoMixin
<CustomizedAnalysis
>;
565 static AnalysisKey Key
;
568 AnalysisKey
CustomizedAnalysis::Key
;
570 struct CustomizedPass
: PassInfoMixin
<CustomizedPass
> {
571 std::function
<void(CustomizedAnalysis::Result
&, int &)> Callback
;
573 template <typename CallbackT
>
574 CustomizedPass(CallbackT Callback
) : Callback(Callback
) {}
576 PreservedAnalyses
run(Function
&F
, CustomizedAnalysisManager
&AM
, int I
,
578 Callback(AM
.getResult
<CustomizedAnalysis
>(F
, I
), O
);
579 return PreservedAnalyses::none();
583 TEST_F(PassManagerTest
, CustomizedPassManagerArgs
) {
584 CustomizedAnalysisManager AM
;
585 AM
.registerPass([&] { return CustomizedAnalysis(); });
586 PassInstrumentationCallbacks PIC
;
587 AM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
589 CustomizedPassManager PM
;
591 // Add an instance of the customized pass that just accumulates the input
592 // after it is round-tripped through the analysis.
595 CustomizedPass([](CustomizedAnalysis::Result
&R
, int &O
) { O
+= R
.I
; }));
597 // Run this over every function with the input of 42.
598 for (Function
&F
: *M
)
599 PM
.run(F
, AM
, 42, Result
);
601 // And ensure that we accumulated the correct result.
602 EXPECT_EQ(42 * (int)M
->size(), Result
);
605 /// A test analysis pass which caches in its result another analysis pass and
606 /// uses it to serve queries. This requires the result to invalidate itself
607 /// when its dependency is invalidated.
608 struct TestIndirectFunctionAnalysis
609 : public AnalysisInfoMixin
<TestIndirectFunctionAnalysis
> {
611 Result(TestFunctionAnalysis::Result
&FDep
, TestModuleAnalysis::Result
&MDep
)
612 : FDep(FDep
), MDep(MDep
) {}
613 TestFunctionAnalysis::Result
&FDep
;
614 TestModuleAnalysis::Result
&MDep
;
616 bool invalidate(Function
&F
, const PreservedAnalyses
&PA
,
617 FunctionAnalysisManager::Invalidator
&Inv
) {
618 auto PAC
= PA
.getChecker
<TestIndirectFunctionAnalysis
>();
619 return !(PAC
.preserved() ||
620 PAC
.preservedSet
<AllAnalysesOn
<Function
>>()) ||
621 Inv
.invalidate
<TestFunctionAnalysis
>(F
, PA
);
625 TestIndirectFunctionAnalysis(int &Runs
, ModuleAnalysisManager
&MAM
)
626 : Runs(Runs
), MAM(MAM
) {}
628 /// Run the analysis pass over the function and return a result.
629 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
631 auto &FDep
= AM
.getResult
<TestFunctionAnalysis
>(F
);
632 auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
633 // For the test, we insist that the module analysis starts off in the
634 // cache. Getting a cached result that isn't stateless trigger an assert.
635 // Use MAM, for the purposes of this unittest.
636 auto &MDep
= *MAM
.getCachedResult
<TestModuleAnalysis
>(*F
.getParent());
637 // And register the dependency as module analysis dependencies have to be
638 // pre-registered on the proxy.
639 MAMProxy
.registerOuterAnalysisInvalidation
<TestModuleAnalysis
,
640 TestIndirectFunctionAnalysis
>();
641 return Result(FDep
, MDep
);
645 friend AnalysisInfoMixin
<TestIndirectFunctionAnalysis
>;
646 static AnalysisKey Key
;
649 ModuleAnalysisManager
&MAM
;
652 AnalysisKey
TestIndirectFunctionAnalysis::Key
;
654 /// A test analysis pass which chaches in its result the result from the above
655 /// indirect analysis pass.
657 /// This allows us to ensure that whenever an analysis pass is invalidated due
658 /// to dependencies (especially dependencies across IR units that trigger
659 /// asynchronous invalidation) we correctly detect that this may in turn cause
660 /// other analysis to be invalidated.
661 struct TestDoublyIndirectFunctionAnalysis
662 : public AnalysisInfoMixin
<TestDoublyIndirectFunctionAnalysis
> {
664 Result(TestIndirectFunctionAnalysis::Result
&IDep
) : IDep(IDep
) {}
665 TestIndirectFunctionAnalysis::Result
&IDep
;
667 bool invalidate(Function
&F
, const PreservedAnalyses
&PA
,
668 FunctionAnalysisManager::Invalidator
&Inv
) {
669 auto PAC
= PA
.getChecker
<TestDoublyIndirectFunctionAnalysis
>();
670 return !(PAC
.preserved() ||
671 PAC
.preservedSet
<AllAnalysesOn
<Function
>>()) ||
672 Inv
.invalidate
<TestIndirectFunctionAnalysis
>(F
, PA
);
676 TestDoublyIndirectFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
678 /// Run the analysis pass over the function and return a result.
679 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
681 auto &IDep
= AM
.getResult
<TestIndirectFunctionAnalysis
>(F
);
686 friend AnalysisInfoMixin
<TestDoublyIndirectFunctionAnalysis
>;
687 static AnalysisKey Key
;
692 AnalysisKey
TestDoublyIndirectFunctionAnalysis::Key
;
694 struct LambdaPass
: public PassInfoMixin
<LambdaPass
> {
695 using FuncT
= std::function
<PreservedAnalyses(Function
&, FunctionAnalysisManager
&)>;
697 LambdaPass(FuncT Func
) : Func(std::move(Func
)) {}
699 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
706 TEST_F(PassManagerTest
, IndirectAnalysisInvalidation
) {
707 FunctionAnalysisManager FAM
;
708 ModuleAnalysisManager MAM
;
709 int FunctionAnalysisRuns
= 0, ModuleAnalysisRuns
= 0,
710 IndirectAnalysisRuns
= 0, DoublyIndirectAnalysisRuns
= 0;
711 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
713 [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns
, MAM
); });
714 FAM
.registerPass([&] {
715 return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns
);
718 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
719 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
720 FAM
.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM
); });
722 PassInstrumentationCallbacks PIC
;
723 MAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
724 FAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
726 int InstrCount
= 0, FunctionCount
= 0;
727 ModulePassManager MPM
;
728 FunctionPassManager FPM
;
729 // First just use the analysis to get the instruction count, and preserve
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 // - both analyses for "f",
741 // - just the underlying (indirect) analysis for "g", and
742 // - just the direct analysis for "h".
743 FPM
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
744 auto &DoublyIndirectResult
=
745 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
746 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
747 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
748 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
749 auto PA
= PreservedAnalyses::none();
750 if (F
.getName() == "g")
751 PA
.preserve
<TestFunctionAnalysis
>();
752 else if (F
.getName() == "h")
753 PA
.preserve
<TestIndirectFunctionAnalysis
>();
756 // Finally, use the analysis again on each function, forcing re-computation
758 FPM
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
759 auto &DoublyIndirectResult
=
760 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
761 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
762 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
763 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
764 return PreservedAnalyses::all();
767 // Create a second function pass manager. This will cause the module-level
768 // invalidation to occur, which will force yet another invalidation of the
769 // indirect function-level analysis as the module analysis it depends on gets
771 FunctionPassManager FPM2
;
772 FPM2
.addPass(LambdaPass([&](Function
&F
, FunctionAnalysisManager
&AM
) {
773 auto &DoublyIndirectResult
=
774 AM
.getResult
<TestDoublyIndirectFunctionAnalysis
>(F
);
775 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
776 InstrCount
+= IndirectResult
.FDep
.InstructionCount
;
777 FunctionCount
+= IndirectResult
.MDep
.FunctionCount
;
778 return PreservedAnalyses::all();
781 // Add a requires pass to populate the module analysis and then our function
783 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
784 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
785 // Now require the module analysis again (it will have been invalidated once)
786 // and then use it again from a function pass manager.
787 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
788 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM2
)));
791 // There are generally two possible runs for each of the three functions. But
792 // for one function, we only invalidate the indirect analysis so the base one
793 // only gets run five times.
794 EXPECT_EQ(5, FunctionAnalysisRuns
);
795 // The module analysis pass should be run twice here.
796 EXPECT_EQ(2, ModuleAnalysisRuns
);
797 // The indirect analysis is invalidated for each function (either directly or
798 // indirectly) and run twice for each.
799 EXPECT_EQ(9, IndirectAnalysisRuns
);
800 EXPECT_EQ(9, DoublyIndirectAnalysisRuns
);
802 // There are five instructions in the module and we add the count four
804 EXPECT_EQ(5 * 4, InstrCount
);
806 // There are three functions and we count them four times for each of the
808 EXPECT_EQ(3 * 4 * 3, FunctionCount
);
811 // Run SimplifyCFGPass that makes CFG changes and reports PreservedAnalyses
812 // without CFGAnalyses. So the CFGChecker does not complain.
813 TEST_F(PassManagerTest
, FunctionPassCFGChecker
) {
815 // SimplifyCFG changes this function to
816 // define void @foo {next: ret void}
817 auto M
= parseIR(Context
, "define void @foo() {\n"
825 auto *F
= M
->getFunction("foo");
826 FunctionAnalysisManager FAM
;
827 ModuleAnalysisManager MAM
;
828 FunctionPassManager FPM
;
829 PassInstrumentationCallbacks PIC
;
830 StandardInstrumentations
SI(M
->getContext(), /*DebugLogging*/ true);
831 SI
.registerCallbacks(PIC
, &MAM
);
832 MAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
833 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
834 FAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
835 FAM
.registerPass([&] { return DominatorTreeAnalysis(); });
836 FAM
.registerPass([&] { return AssumptionAnalysis(); });
837 FAM
.registerPass([&] { return TargetIRAnalysis(); });
839 FPM
.addPass(SimplifyCFGPass());
843 // FunctionPass that manually invalidates analyses and always returns
844 // PreservedAnalyses::all().
845 struct TestSimplifyCFGInvalidatingAnalysisPass
846 : PassInfoMixin
<TestSimplifyCFGInvalidatingAnalysisPass
> {
847 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&FAM
) {
848 // Run SimplifyCFG and if it changes CFG then invalidate the CFG analysis.
849 // This allows to return PreserveAnalysis::all().
850 PreservedAnalyses PA
= CFGSimplifier
.run(F
, FAM
);
851 FAM
.invalidate(F
, PA
);
852 return PreservedAnalyses::all();
855 SimplifyCFGPass CFGSimplifier
;
858 // Run TestSimplifyCFGInvalidatingAnalysisPass which changes CFG by running
859 // SimplifyCFGPass then manually invalidates analyses and always returns
860 // PreservedAnalyses::all(). CFGChecker does not complain because it resets
861 // its saved CFG snapshot when the analyses are invalidated manually.
862 TEST_F(PassManagerTest
, FunctionPassCFGCheckerInvalidateAnalysis
) {
864 // SimplifyCFG changes this function to
865 // define void @foo {next: ret void}
866 auto M
= parseIR(Context
, "define void @foo() {\n"
874 auto *F
= M
->getFunction("foo");
875 FunctionAnalysisManager FAM
;
876 ModuleAnalysisManager MAM
;
877 FunctionPassManager FPM
;
878 PassInstrumentationCallbacks PIC
;
879 StandardInstrumentations
SI(M
->getContext(), /*DebugLogging*/ true);
880 SI
.registerCallbacks(PIC
, &MAM
);
881 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
882 MAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
883 FAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
884 FAM
.registerPass([&] { return DominatorTreeAnalysis(); });
885 FAM
.registerPass([&] { return AssumptionAnalysis(); });
886 FAM
.registerPass([&] { return TargetIRAnalysis(); });
888 FPM
.addPass(TestSimplifyCFGInvalidatingAnalysisPass());
892 // Wrap a FunctionPassManager running SimplifyCFG pass with another
893 // FunctionPassManager.
894 struct TestSimplifyCFGWrapperPass
: PassInfoMixin
<TestSimplifyCFGWrapperPass
> {
895 TestSimplifyCFGWrapperPass(FunctionPassManager
&InnerPM
) : InnerPM(InnerPM
) {}
897 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&FAM
) {
898 // Here we simulate exactly what FunctionPassManager::run() does but
899 // instead of running all passes from InnerPM.Passes we run them in bulk
900 // by calling InnerPM.run().
901 PreservedAnalyses PA
= PreservedAnalyses::all();
902 PassInstrumentation PI
= FAM
.getResult
<PassInstrumentationAnalysis
>(F
);
904 if (!PI
.runBeforePass
<Function
>(InnerPM
, F
))
905 return PreservedAnalyses::all();
907 PreservedAnalyses PassPA
= InnerPM
.run(F
, FAM
);
908 PI
.runAfterPass(InnerPM
, F
, PassPA
);
909 FAM
.invalidate(F
, PassPA
);
910 PA
.intersect(PassPA
);
911 PA
.preserveSet
<AllAnalysesOn
<Function
>>();
915 FunctionPassManager
&InnerPM
;
918 // Run TestSimplifyCFGWrapperPass which simulates behavior of
919 // FunctionPassManager::run() except that it runs all passes at once by calling
920 // an inner pass manager's passes with PassManager::run(). This is how one pass
921 // manager is expected to wrap another pass manager.
922 // SimplifyCFGPass, which is called by the inner pass manager, changes the CFG.
923 // The CFGChecker's AfterPassCallback, run right after SimplifyCFGPass, does not
924 // complain because CFGAnalyses is not in the PreservedAnalises set returned by
925 // SimplifyCFGPass. Then the CFG analysis is invalidated by the analysis manager
926 // according to the PreservedAnalises set. Further calls to CFGChecker's
927 // AfterPassCallback see that all analyses for the current function are
928 // preserved but there is no CFG snapshot available (i.e.
929 // AM.getCachedResult<PreservedCFGCheckerAnalysis>(F) returns nullptr).
930 TEST_F(PassManagerTest
, FunctionPassCFGCheckerWrapped
) {
932 // SimplifyCFG changes this function to
933 // define void @foo {next: ret void}
934 auto M
= parseIR(Context
, "define void @foo() {\n"
942 auto *F
= M
->getFunction("foo");
943 FunctionAnalysisManager FAM
;
944 ModuleAnalysisManager MAM
;
945 FunctionPassManager FPM
;
946 PassInstrumentationCallbacks PIC
;
947 StandardInstrumentations
SI(M
->getContext(), /*DebugLogging*/ true);
948 SI
.registerCallbacks(PIC
, &MAM
);
949 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
950 MAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
951 FAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
952 FAM
.registerPass([&] { return DominatorTreeAnalysis(); });
953 FAM
.registerPass([&] { return AssumptionAnalysis(); });
954 FAM
.registerPass([&] { return TargetIRAnalysis(); });
956 FunctionPassManager InnerFPM
;
957 InnerFPM
.addPass(SimplifyCFGPass());
959 FPM
.addPass(TestSimplifyCFGWrapperPass(InnerFPM
));
963 #ifdef EXPENSIVE_CHECKS
965 struct WrongFunctionPass
: PassInfoMixin
<WrongFunctionPass
> {
966 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&FAM
) {
967 F
.getEntryBlock().begin()->eraseFromParent();
968 return PreservedAnalyses::all();
970 static StringRef
name() { return "WrongFunctionPass"; }
973 TEST_F(PassManagerTest
, FunctionPassMissedFunctionAnalysisInvalidation
) {
975 auto M
= parseIR(Context
, "define void @foo() {\n"
976 " %a = add i32 0, 0\n"
980 FunctionAnalysisManager FAM
;
981 ModuleAnalysisManager MAM
;
982 PassInstrumentationCallbacks PIC
;
983 StandardInstrumentations
SI(M
->getContext(), /*DebugLogging*/ false);
984 SI
.registerCallbacks(PIC
, &MAM
);
985 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
986 MAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
987 FAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
988 FAM
.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM
); });
990 FunctionPassManager FPM
;
991 FPM
.addPass(WrongFunctionPass());
993 auto *F
= M
->getFunction("foo");
994 EXPECT_DEATH(FPM
.run(*F
, FAM
), "Function @foo changed by WrongFunctionPass without invalidating analyses");
997 struct WrongModulePass
: PassInfoMixin
<WrongModulePass
> {
998 PreservedAnalyses
run(Module
&M
, ModuleAnalysisManager
&MAM
) {
999 for (Function
&F
: M
)
1000 F
.getEntryBlock().begin()->eraseFromParent();
1002 PreservedAnalyses PA
;
1003 PA
.preserveSet
<AllAnalysesOn
<Function
>>();
1004 PA
.preserve
<FunctionAnalysisManagerModuleProxy
>();
1007 static StringRef
name() { return "WrongModulePass"; }
1010 TEST_F(PassManagerTest
, ModulePassMissedFunctionAnalysisInvalidation
) {
1011 LLVMContext Context
;
1012 auto M
= parseIR(Context
, "define void @foo() {\n"
1013 " %a = add i32 0, 0\n"
1017 FunctionAnalysisManager FAM
;
1018 ModuleAnalysisManager MAM
;
1019 PassInstrumentationCallbacks PIC
;
1020 StandardInstrumentations
SI(M
->getContext(), /*DebugLogging*/ false);
1021 SI
.registerCallbacks(PIC
, &MAM
);
1022 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
1023 MAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
1024 FAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
1025 FAM
.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM
); });
1027 ModulePassManager MPM
;
1028 MPM
.addPass(WrongModulePass());
1032 "Function @foo changed by WrongModulePass without invalidating analyses");
1035 struct WrongModulePass2
: PassInfoMixin
<WrongModulePass2
> {
1036 PreservedAnalyses
run(Module
&M
, ModuleAnalysisManager
&MAM
) {
1037 for (Function
&F
: M
)
1038 F
.getEntryBlock().begin()->eraseFromParent();
1040 PreservedAnalyses PA
;
1041 PA
.preserveSet
<AllAnalysesOn
<Module
>>();
1042 PA
.abandon
<FunctionAnalysisManagerModuleProxy
>();
1045 static StringRef
name() { return "WrongModulePass2"; }
1048 TEST_F(PassManagerTest
, ModulePassMissedModuleAnalysisInvalidation
) {
1049 LLVMContext Context
;
1050 auto M
= parseIR(Context
, "define void @foo() {\n"
1051 " %a = add i32 0, 0\n"
1055 FunctionAnalysisManager FAM
;
1056 ModuleAnalysisManager MAM
;
1057 PassInstrumentationCallbacks PIC
;
1058 StandardInstrumentations
SI(M
->getContext(), /*DebugLogging*/ false);
1059 SI
.registerCallbacks(PIC
, &MAM
);
1060 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
1061 MAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
1062 FAM
.registerPass([&] { return PassInstrumentationAnalysis(&PIC
); });
1063 FAM
.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM
); });
1065 ModulePassManager MPM
;
1066 MPM
.addPass(WrongModulePass2());
1070 "Module changed by WrongModulePass2 without invalidating analyses");