1 //===- CGSCCPassManagerTest.cpp -------------------------------------------===//
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/Analysis/CGSCCPassManager.h"
10 #include "llvm/Analysis/LazyCallGraph.h"
11 #include "llvm/Analysis/TargetLibraryInfo.h"
12 #include "llvm/AsmParser/Parser.h"
13 #include "llvm/IR/Constants.h"
14 #include "llvm/IR/Function.h"
15 #include "llvm/IR/InstIterator.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/IR/PassManager.h"
20 #include "llvm/IR/Verifier.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "llvm/Transforms/Utils/CallGraphUpdater.h"
23 #include "gtest/gtest.h"
29 class TestModuleAnalysis
: public AnalysisInfoMixin
<TestModuleAnalysis
> {
32 Result(int Count
) : FunctionCount(Count
) {}
34 bool invalidate(Module
&, const PreservedAnalyses
&PA
,
35 ModuleAnalysisManager::Invalidator
&) {
36 // Check whether the analysis or all analyses on modules have been
38 auto PAC
= PA
.getChecker
<TestModuleAnalysis
>();
39 return !(PAC
.preserved() || PAC
.preservedSet
<AllAnalysesOn
<Module
>>());
43 TestModuleAnalysis(int &Runs
) : Runs(Runs
) {}
45 Result
run(Module
&M
, ModuleAnalysisManager
&AM
) {
47 return Result(M
.size());
51 friend AnalysisInfoMixin
<TestModuleAnalysis
>;
52 static AnalysisKey Key
;
57 AnalysisKey
TestModuleAnalysis::Key
;
59 class TestSCCAnalysis
: public AnalysisInfoMixin
<TestSCCAnalysis
> {
62 Result(int Count
) : FunctionCount(Count
) {}
64 bool invalidate(LazyCallGraph::SCC
&, const PreservedAnalyses
&PA
,
65 CGSCCAnalysisManager::Invalidator
&) {
66 // Check whether the analysis or all analyses on SCCs have been
68 auto PAC
= PA
.getChecker
<TestSCCAnalysis
>();
69 return !(PAC
.preserved() ||
70 PAC
.preservedSet
<AllAnalysesOn
<LazyCallGraph::SCC
>>());
74 TestSCCAnalysis(int &Runs
) : Runs(Runs
) {}
76 Result
run(LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&) {
78 return Result(C
.size());
82 friend AnalysisInfoMixin
<TestSCCAnalysis
>;
83 static AnalysisKey Key
;
88 AnalysisKey
TestSCCAnalysis::Key
;
90 class TestFunctionAnalysis
: public AnalysisInfoMixin
<TestFunctionAnalysis
> {
93 Result(int Count
) : InstructionCount(Count
) {}
95 bool invalidate(Function
&, const PreservedAnalyses
&PA
,
96 FunctionAnalysisManager::Invalidator
&) {
97 // Check whether the analysis or all analyses on functions have been
99 auto PAC
= PA
.getChecker
<TestFunctionAnalysis
>();
100 return !(PAC
.preserved() || PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
104 TestFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
106 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
109 for (Instruction
&I
: instructions(F
)) {
113 return Result(Count
);
117 friend AnalysisInfoMixin
<TestFunctionAnalysis
>;
118 static AnalysisKey Key
;
123 AnalysisKey
TestFunctionAnalysis::Key
;
125 class TestImmutableFunctionAnalysis
126 : public AnalysisInfoMixin
<TestImmutableFunctionAnalysis
> {
129 bool invalidate(Function
&, const PreservedAnalyses
&,
130 FunctionAnalysisManager::Invalidator
&) {
135 TestImmutableFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
137 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
143 friend AnalysisInfoMixin
<TestImmutableFunctionAnalysis
>;
144 static AnalysisKey Key
;
149 AnalysisKey
TestImmutableFunctionAnalysis::Key
;
151 struct LambdaModulePass
: public PassInfoMixin
<LambdaModulePass
> {
152 template <typename T
>
153 LambdaModulePass(T
&&Arg
) : Func(std::forward
<T
>(Arg
)) {}
155 PreservedAnalyses
run(Module
&F
, ModuleAnalysisManager
&AM
) {
159 std::function
<PreservedAnalyses(Module
&, ModuleAnalysisManager
&)> Func
;
162 struct LambdaSCCPass
: public PassInfoMixin
<LambdaSCCPass
> {
163 template <typename T
> LambdaSCCPass(T
&&Arg
) : Func(std::forward
<T
>(Arg
)) {}
165 PreservedAnalyses
run(LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
166 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
167 return Func(C
, AM
, CG
, UR
);
170 std::function
<PreservedAnalyses(LazyCallGraph::SCC
&, CGSCCAnalysisManager
&,
171 LazyCallGraph
&, CGSCCUpdateResult
&)>
175 struct LambdaFunctionPass
: public PassInfoMixin
<LambdaFunctionPass
> {
176 template <typename T
>
177 LambdaFunctionPass(T
&&Arg
) : Func(std::forward
<T
>(Arg
)) {}
179 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
183 std::function
<PreservedAnalyses(Function
&, FunctionAnalysisManager
&)> Func
;
186 std::unique_ptr
<Module
> parseIR(const char *IR
) {
187 // We just use a static context here. This is never called from multiple
188 // threads so it is harmless no matter how it is implemented. We just need
189 // the context to outlive the module which it does.
190 static LLVMContext C
;
192 return parseAssemblyString(IR
, Err
, C
);
195 class CGSCCPassManagerTest
: public ::testing::Test
{
198 FunctionAnalysisManager FAM
;
199 CGSCCAnalysisManager CGAM
;
200 ModuleAnalysisManager MAM
;
202 std::unique_ptr
<Module
> M
;
205 CGSCCPassManagerTest()
206 : FAM(), CGAM(), MAM(),
208 // Define a module with the following call graph, where calls go
209 // out the bottom of nodes and enter the top:
223 "define void @x() {\n"
227 "define void @h3() {\n"
232 "define void @h2() {\n"
238 "define void @h1() {\n"
243 "define void @g() {\n"
249 "define void @f() {\n"
255 FAM
.registerPass([&] { return TargetLibraryAnalysis(); });
256 MAM
.registerPass([&] { return LazyCallGraphAnalysis(); });
257 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
259 // Register required pass instrumentation analysis.
260 MAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
261 CGAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
262 FAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
264 // Cross-register proxies.
265 MAM
.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM
); });
266 CGAM
.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); });
267 CGAM
.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM
); });
268 FAM
.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM
); });
269 FAM
.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM
); });
273 TEST_F(CGSCCPassManagerTest
, Basic
) {
274 int FunctionAnalysisRuns
= 0;
275 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
276 int ImmutableFunctionAnalysisRuns
= 0;
277 FAM
.registerPass([&] {
278 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns
);
281 int SCCAnalysisRuns
= 0;
282 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
284 int ModuleAnalysisRuns
= 0;
285 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
287 ModulePassManager MPM
;
288 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
290 CGSCCPassManager CGPM1
;
291 FunctionPassManager FPM1
;
292 int FunctionPassRunCount1
= 0;
293 FPM1
.addPass(LambdaFunctionPass([&](Function
&, FunctionAnalysisManager
&) {
294 ++FunctionPassRunCount1
;
295 return PreservedAnalyses::none();
297 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
299 int SCCPassRunCount1
= 0;
300 int AnalyzedInstrCount1
= 0;
301 int AnalyzedSCCFunctionCount1
= 0;
302 int AnalyzedModuleFunctionCount1
= 0;
304 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
305 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
308 // Note: The proper way to get to a module pass from a CGSCC pass is
309 // through the ModuleAnalysisManagerCGSCCProxy:
311 // const auto &MAMProxy =
312 // AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
314 // However getting a stateful analysis is incorrect usage, and the call
315 // to getCachedResult below asserts:
317 // if (TestModuleAnalysis::Result *TMA =
318 // MAMProxy.getCachedResult<TestModuleAnalysis>(
319 // *C.begin()->getFunction().getParent()))
320 // AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
322 // For the purposes of this unittest, use the above MAM directly.
323 if (TestModuleAnalysis::Result
*TMA
=
324 MAM
.getCachedResult
<TestModuleAnalysis
>(
325 *C
.begin()->getFunction().getParent()))
326 AnalyzedModuleFunctionCount1
+= TMA
->FunctionCount
;
328 FunctionAnalysisManager
&FAM
=
329 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
330 TestSCCAnalysis::Result
&AR
= AM
.getResult
<TestSCCAnalysis
>(C
, CG
);
331 AnalyzedSCCFunctionCount1
+= AR
.FunctionCount
;
332 for (LazyCallGraph::Node
&N
: C
) {
333 TestFunctionAnalysis::Result
&FAR
=
334 FAM
.getResult
<TestFunctionAnalysis
>(N
.getFunction());
335 AnalyzedInstrCount1
+= FAR
.InstructionCount
;
337 // Just ensure we get the immutable results.
338 (void)FAM
.getResult
<TestImmutableFunctionAnalysis
>(N
.getFunction());
341 return PreservedAnalyses::all();
344 FunctionPassManager FPM2
;
345 int FunctionPassRunCount2
= 0;
346 FPM2
.addPass(LambdaFunctionPass([&](Function
&, FunctionAnalysisManager
&) {
347 ++FunctionPassRunCount2
;
348 return PreservedAnalyses::none();
350 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
352 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
354 FunctionPassManager FPM3
;
355 int FunctionPassRunCount3
= 0;
356 FPM3
.addPass(LambdaFunctionPass([&](Function
&, FunctionAnalysisManager
&) {
357 ++FunctionPassRunCount3
;
358 return PreservedAnalyses::none();
360 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3
)));
364 EXPECT_EQ(4, SCCPassRunCount1
);
365 EXPECT_EQ(6, FunctionPassRunCount1
);
366 EXPECT_EQ(6, FunctionPassRunCount2
);
367 EXPECT_EQ(6, FunctionPassRunCount3
);
369 EXPECT_EQ(1, ModuleAnalysisRuns
);
370 EXPECT_EQ(4, SCCAnalysisRuns
);
371 EXPECT_EQ(6, FunctionAnalysisRuns
);
372 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns
);
374 EXPECT_EQ(14, AnalyzedInstrCount1
);
375 EXPECT_EQ(6, AnalyzedSCCFunctionCount1
);
376 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1
);
379 // Test that an SCC pass which fails to preserve a module analysis does in fact
380 // invalidate that module analysis.
381 TEST_F(CGSCCPassManagerTest
, TestSCCPassInvalidatesModuleAnalysis
) {
382 int ModuleAnalysisRuns
= 0;
383 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
385 ModulePassManager MPM
;
386 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
388 // The first CGSCC run we preserve everything and make sure that works and
389 // the module analysis is available in the second CGSCC run from the one
390 // required module pass above.
391 CGSCCPassManager CGPM1
;
392 int CountFoundModuleAnalysis1
= 0;
393 CGPM1
.addPass(LambdaSCCPass([&](LazyCallGraph::SCC
&C
,
394 CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
395 CGSCCUpdateResult
&UR
) {
396 const auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerCGSCCProxy
>(C
, CG
);
397 if (MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(
398 *C
.begin()->getFunction().getParent()))
399 ++CountFoundModuleAnalysis1
;
401 return PreservedAnalyses::all();
403 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
405 // The second CGSCC run checks that the module analysis got preserved the
406 // previous time and in one SCC fails to preserve it.
407 CGSCCPassManager CGPM2
;
408 int CountFoundModuleAnalysis2
= 0;
410 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
411 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
412 const auto &MAMProxy
=
413 AM
.getResult
<ModuleAnalysisManagerCGSCCProxy
>(C
, CG
);
414 if (MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(
415 *C
.begin()->getFunction().getParent()))
416 ++CountFoundModuleAnalysis2
;
418 // Only fail to preserve analyses on one SCC and make sure that gets
420 return C
.getName() == "(g)" ? PreservedAnalyses::none()
421 : PreservedAnalyses::all();
423 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
425 // The third CGSCC run should fail to find a cached module analysis as it
426 // should have been invalidated by the above CGSCC run.
427 CGSCCPassManager CGPM3
;
428 int CountFoundModuleAnalysis3
= 0;
429 CGPM3
.addPass(LambdaSCCPass([&](LazyCallGraph::SCC
&C
,
430 CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
431 CGSCCUpdateResult
&UR
) {
432 const auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerCGSCCProxy
>(C
, CG
);
433 if (MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(
434 *C
.begin()->getFunction().getParent()))
435 ++CountFoundModuleAnalysis3
;
437 return PreservedAnalyses::none();
439 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3
)));
443 EXPECT_EQ(1, ModuleAnalysisRuns
);
444 EXPECT_EQ(4, CountFoundModuleAnalysis1
);
445 EXPECT_EQ(4, CountFoundModuleAnalysis2
);
446 EXPECT_EQ(0, CountFoundModuleAnalysis3
);
449 // Similar to the above, but test that this works for function passes embedded
450 // *within* a CGSCC layer.
451 TEST_F(CGSCCPassManagerTest
, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis
) {
452 int ModuleAnalysisRuns
= 0;
453 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
455 ModulePassManager MPM
;
456 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
458 // The first run we preserve everything and make sure that works and the
459 // module analysis is available in the second run from the one required
460 // module pass above.
461 FunctionPassManager FPM1
;
462 // Start true and mark false if we ever failed to find a module analysis
463 // because we expect this to succeed for each SCC.
464 bool FoundModuleAnalysis1
= true;
465 FPM1
.addPass(LambdaFunctionPass([&](Function
&F
,
466 FunctionAnalysisManager
&AM
) {
467 const auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
468 if (!MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(*F
.getParent()))
469 FoundModuleAnalysis1
= false;
471 return PreservedAnalyses::all();
473 CGSCCPassManager CGPM1
;
474 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
475 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
477 // The second run checks that the module analysis got preserved the previous
478 // time and in one function fails to preserve it.
479 FunctionPassManager FPM2
;
480 // Again, start true and mark false if we ever failed to find a module analysis
481 // because we expect this to succeed for each SCC.
482 bool FoundModuleAnalysis2
= true;
483 FPM2
.addPass(LambdaFunctionPass([&](Function
&F
,
484 FunctionAnalysisManager
&AM
) {
485 const auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
486 if (!MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(*F
.getParent()))
487 FoundModuleAnalysis2
= false;
489 // Only fail to preserve analyses on one SCC and make sure that gets
491 return F
.getName() == "h2" ? PreservedAnalyses::none()
492 : PreservedAnalyses::all();
494 CGSCCPassManager CGPM2
;
495 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
496 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
498 // The third run should fail to find a cached module analysis as it should
499 // have been invalidated by the above run.
500 FunctionPassManager FPM3
;
501 // Start false and mark true if we ever *succeeded* to find a module
502 // analysis, as we expect this to fail for every function.
503 bool FoundModuleAnalysis3
= false;
504 FPM3
.addPass(LambdaFunctionPass([&](Function
&F
,
505 FunctionAnalysisManager
&AM
) {
506 const auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
507 if (MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(*F
.getParent()))
508 FoundModuleAnalysis3
= true;
510 return PreservedAnalyses::none();
512 CGSCCPassManager CGPM3
;
513 CGPM3
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3
)));
514 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3
)));
518 EXPECT_EQ(1, ModuleAnalysisRuns
);
519 EXPECT_TRUE(FoundModuleAnalysis1
);
520 EXPECT_TRUE(FoundModuleAnalysis2
);
521 EXPECT_FALSE(FoundModuleAnalysis3
);
524 // Test that a Module pass which fails to preserve an SCC analysis in fact
525 // invalidates that analysis.
526 TEST_F(CGSCCPassManagerTest
, TestModulePassInvalidatesSCCAnalysis
) {
527 int SCCAnalysisRuns
= 0;
528 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
530 ModulePassManager MPM
;
532 // First force the analysis to be run.
533 CGSCCPassManager CGPM1
;
534 CGPM1
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
535 CGSCCAnalysisManager
, LazyCallGraph
&,
536 CGSCCUpdateResult
&>());
537 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
539 // Now run a module pass that preserves the LazyCallGraph and the proxy but
540 // not the SCC analysis.
541 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
542 PreservedAnalyses PA
;
543 PA
.preserve
<LazyCallGraphAnalysis
>();
544 PA
.preserve
<CGSCCAnalysisManagerModuleProxy
>();
545 PA
.preserve
<FunctionAnalysisManagerModuleProxy
>();
549 // And now a second CGSCC run which requires the SCC analysis again. This
550 // will trigger re-running it.
551 CGSCCPassManager CGPM2
;
552 CGPM2
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
553 CGSCCAnalysisManager
, LazyCallGraph
&,
554 CGSCCUpdateResult
&>());
555 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
558 // Two runs and four SCCs.
559 EXPECT_EQ(2 * 4, SCCAnalysisRuns
);
562 // Check that marking the SCC analysis preserved is sufficient to avoid
563 // invaliadtion. This should only run the analysis once for each SCC.
564 TEST_F(CGSCCPassManagerTest
, TestModulePassCanPreserveSCCAnalysis
) {
565 int SCCAnalysisRuns
= 0;
566 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
568 ModulePassManager MPM
;
570 // First force the analysis to be run.
571 CGSCCPassManager CGPM1
;
572 CGPM1
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
573 CGSCCAnalysisManager
, LazyCallGraph
&,
574 CGSCCUpdateResult
&>());
575 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
577 // Now run a module pass that preserves each of the necessary components
578 // (but not everything).
579 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
580 PreservedAnalyses PA
;
581 PA
.preserve
<LazyCallGraphAnalysis
>();
582 PA
.preserve
<CGSCCAnalysisManagerModuleProxy
>();
583 PA
.preserve
<FunctionAnalysisManagerModuleProxy
>();
584 PA
.preserve
<TestSCCAnalysis
>();
588 // And now a second CGSCC run which requires the SCC analysis again but find
590 CGSCCPassManager CGPM2
;
591 CGPM2
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
592 CGSCCAnalysisManager
, LazyCallGraph
&,
593 CGSCCUpdateResult
&>());
594 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
598 EXPECT_EQ(4, SCCAnalysisRuns
);
601 // Check that even when the analysis is preserved, if the SCC information isn't
602 // we still nuke things because the SCC keys could change.
603 TEST_F(CGSCCPassManagerTest
, TestModulePassInvalidatesSCCAnalysisOnCGChange
) {
604 int SCCAnalysisRuns
= 0;
605 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
607 ModulePassManager MPM
;
609 // First force the analysis to be run.
610 CGSCCPassManager CGPM1
;
611 CGPM1
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
612 CGSCCAnalysisManager
, LazyCallGraph
&,
613 CGSCCUpdateResult
&>());
614 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
616 // Now run a module pass that preserves the analysis but not the call
618 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
619 PreservedAnalyses PA
;
620 PA
.preserve
<TestSCCAnalysis
>();
624 // And now a second CGSCC run which requires the SCC analysis again.
625 CGSCCPassManager CGPM2
;
626 CGPM2
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
627 CGSCCAnalysisManager
, LazyCallGraph
&,
628 CGSCCUpdateResult
&>());
629 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
632 // Two runs and four SCCs.
633 EXPECT_EQ(2 * 4, SCCAnalysisRuns
);
636 // Test that an SCC pass which fails to preserve a Function analysis in fact
637 // invalidates that analysis.
638 TEST_F(CGSCCPassManagerTest
, TestSCCPassInvalidatesFunctionAnalysis
) {
639 int FunctionAnalysisRuns
= 0;
640 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
642 // Create a very simple module with a single function and SCC to make testing
643 // these issues much easier.
644 std::unique_ptr
<Module
> M
= parseIR("declare void @g()\n"
645 "declare void @h()\n"
646 "define void @f() {\n"
653 CGSCCPassManager CGPM
;
655 // First force the analysis to be run.
656 FunctionPassManager FPM1
;
657 FPM1
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
658 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
660 // Now run a module pass that preserves the LazyCallGraph and proxy but not
662 CGPM
.addPass(LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&,
663 LazyCallGraph
&, CGSCCUpdateResult
&) {
664 PreservedAnalyses PA
;
665 PA
.preserve
<LazyCallGraphAnalysis
>();
669 // And now a second CGSCC run which requires the SCC analysis again. This
670 // will trigger re-running it.
671 FunctionPassManager FPM2
;
672 FPM2
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
673 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
675 ModulePassManager MPM
;
676 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
678 EXPECT_EQ(2, FunctionAnalysisRuns
);
681 // Check that marking the SCC analysis preserved is sufficient. This should
682 // only run the analysis once the SCC.
683 TEST_F(CGSCCPassManagerTest
, TestSCCPassCanPreserveFunctionAnalysis
) {
684 int FunctionAnalysisRuns
= 0;
685 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
687 // Create a very simple module with a single function and SCC to make testing
688 // these issues much easier.
689 std::unique_ptr
<Module
> M
= parseIR("declare void @g()\n"
690 "declare void @h()\n"
691 "define void @f() {\n"
698 CGSCCPassManager CGPM
;
700 // First force the analysis to be run.
701 FunctionPassManager FPM1
;
702 FPM1
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
703 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
705 // Now run a module pass that preserves each of the necessary components
708 CGPM
.addPass(LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&,
709 LazyCallGraph
&, CGSCCUpdateResult
&) {
710 PreservedAnalyses PA
;
711 PA
.preserve
<LazyCallGraphAnalysis
>();
712 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
713 PA
.preserve
<TestFunctionAnalysis
>();
717 // And now a second CGSCC run which requires the SCC analysis again but find
719 FunctionPassManager FPM2
;
720 FPM2
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
721 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
723 ModulePassManager MPM
;
724 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
726 EXPECT_EQ(1, FunctionAnalysisRuns
);
729 // Note that there is no test for invalidating the call graph or other
730 // structure with an SCC pass because there is no mechanism to do that from
731 // withinsuch a pass. Instead, such a pass has to directly update the call
734 // Test that a madule pass invalidates function analyses when the CGSCC proxies
736 TEST_F(CGSCCPassManagerTest
,
737 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC
) {
738 MAM
.registerPass([&] { return LazyCallGraphAnalysis(); });
740 int FunctionAnalysisRuns
= 0;
741 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
743 ModulePassManager MPM
;
745 // First force the analysis to be run.
746 FunctionPassManager FPM1
;
747 FPM1
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
748 CGSCCPassManager CGPM1
;
749 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
750 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
752 // Now run a module pass that preserves the LazyCallGraph and proxies but not
753 // the Function analysis.
754 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
755 PreservedAnalyses PA
;
756 PA
.preserve
<LazyCallGraphAnalysis
>();
757 PA
.preserve
<CGSCCAnalysisManagerModuleProxy
>();
758 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
759 PA
.preserve
<FunctionAnalysisManagerModuleProxy
>();
763 // And now a second CGSCC run which requires the SCC analysis again. This
764 // will trigger re-running it.
765 FunctionPassManager FPM2
;
766 FPM2
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
767 CGSCCPassManager CGPM2
;
768 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
769 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
772 // Two runs and 6 functions.
773 EXPECT_EQ(2 * 6, FunctionAnalysisRuns
);
776 // Check that by marking the function pass and proxies as preserved, this
777 // propagates all the way through.
778 TEST_F(CGSCCPassManagerTest
,
779 TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC
) {
780 MAM
.registerPass([&] { return LazyCallGraphAnalysis(); });
782 int FunctionAnalysisRuns
= 0;
783 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
785 ModulePassManager MPM
;
787 // First force the analysis to be run.
788 FunctionPassManager FPM1
;
789 FPM1
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
790 CGSCCPassManager CGPM1
;
791 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
792 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
794 // Now run a module pass that preserves the LazyCallGraph, the proxy, and
795 // the Function analysis.
796 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
797 PreservedAnalyses PA
;
798 PA
.preserve
<LazyCallGraphAnalysis
>();
799 PA
.preserve
<CGSCCAnalysisManagerModuleProxy
>();
800 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
801 PA
.preserve
<FunctionAnalysisManagerModuleProxy
>();
802 PA
.preserve
<TestFunctionAnalysis
>();
806 // And now a second CGSCC run which requires the SCC analysis again. This
807 // will trigger re-running it.
808 FunctionPassManager FPM2
;
809 FPM2
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
810 CGSCCPassManager CGPM2
;
811 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
812 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
815 // One run and 6 functions.
816 EXPECT_EQ(6, FunctionAnalysisRuns
);
819 // Check that if the lazy call graph itself isn't preserved we still manage to
820 // invalidate everything.
821 TEST_F(CGSCCPassManagerTest
,
822 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange
) {
823 MAM
.registerPass([&] { return LazyCallGraphAnalysis(); });
825 int FunctionAnalysisRuns
= 0;
826 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
828 ModulePassManager MPM
;
830 // First force the analysis to be run.
831 FunctionPassManager FPM1
;
832 FPM1
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
833 CGSCCPassManager CGPM1
;
834 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
835 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
837 // Now run a module pass that preserves the LazyCallGraph but not the
838 // Function analysis.
839 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
840 PreservedAnalyses PA
;
844 // And now a second CGSCC run which requires the SCC analysis again. This
845 // will trigger re-running it.
846 FunctionPassManager FPM2
;
847 FPM2
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
848 CGSCCPassManager CGPM2
;
849 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
850 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
853 // Two runs and 6 functions.
854 EXPECT_EQ(2 * 6, FunctionAnalysisRuns
);
857 /// A test CGSCC-level analysis pass which caches in its result another
858 /// analysis pass and uses it to serve queries. This requires the result to
859 /// invalidate itself when its dependency is invalidated.
861 /// FIXME: Currently this doesn't also depend on a function analysis, and if it
862 /// did we would fail to invalidate it correctly.
863 struct TestIndirectSCCAnalysis
864 : public AnalysisInfoMixin
<TestIndirectSCCAnalysis
> {
866 Result(TestSCCAnalysis::Result
&SCCDep
, TestModuleAnalysis::Result
&MDep
)
867 : SCCDep(SCCDep
), MDep(MDep
) {}
868 TestSCCAnalysis::Result
&SCCDep
;
869 TestModuleAnalysis::Result
&MDep
;
871 bool invalidate(LazyCallGraph::SCC
&C
, const PreservedAnalyses
&PA
,
872 CGSCCAnalysisManager::Invalidator
&Inv
) {
873 auto PAC
= PA
.getChecker
<TestIndirectSCCAnalysis
>();
874 return !(PAC
.preserved() ||
875 PAC
.preservedSet
<AllAnalysesOn
<LazyCallGraph::SCC
>>()) ||
876 Inv
.invalidate
<TestSCCAnalysis
>(C
, PA
);
880 TestIndirectSCCAnalysis(int &Runs
, ModuleAnalysisManager
&MAM
)
881 : Runs(Runs
), MAM(MAM
) {}
883 /// Run the analysis pass over the function and return a result.
884 Result
run(LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
887 auto &SCCDep
= AM
.getResult
<TestSCCAnalysis
>(C
, CG
);
889 auto &ModuleProxy
= AM
.getResult
<ModuleAnalysisManagerCGSCCProxy
>(C
, CG
);
890 // For the test, we insist that the module analysis starts off in the
891 // cache. Getting a cached result that isn't stateless triggers an assert.
892 // auto &MDep = *ModuleProxy.getCachedResult<TestModuleAnalysis>(
893 // *C.begin()->getFunction().getParent());
894 // Use MAM, for the purposes of this unittest.
895 auto &MDep
= *MAM
.getCachedResult
<TestModuleAnalysis
>(
896 *C
.begin()->getFunction().getParent());
897 // Register the dependency as module analysis dependencies have to be
898 // pre-registered on the proxy.
899 ModuleProxy
.registerOuterAnalysisInvalidation
<TestModuleAnalysis
,
900 TestIndirectSCCAnalysis
>();
902 return Result(SCCDep
, MDep
);
906 friend AnalysisInfoMixin
<TestIndirectSCCAnalysis
>;
907 static AnalysisKey Key
;
910 ModuleAnalysisManager
&MAM
;
913 AnalysisKey
TestIndirectSCCAnalysis::Key
;
915 /// A test analysis pass which caches in its result the result from the above
916 /// indirect analysis pass.
918 /// This allows us to ensure that whenever an analysis pass is invalidated due
919 /// to dependencies (especially dependencies across IR units that trigger
920 /// asynchronous invalidation) we correctly detect that this may in turn cause
921 /// other analysis to be invalidated.
922 struct TestDoublyIndirectSCCAnalysis
923 : public AnalysisInfoMixin
<TestDoublyIndirectSCCAnalysis
> {
925 Result(TestIndirectSCCAnalysis::Result
&IDep
) : IDep(IDep
) {}
926 TestIndirectSCCAnalysis::Result
&IDep
;
928 bool invalidate(LazyCallGraph::SCC
&C
, const PreservedAnalyses
&PA
,
929 CGSCCAnalysisManager::Invalidator
&Inv
) {
930 auto PAC
= PA
.getChecker
<TestDoublyIndirectSCCAnalysis
>();
931 return !(PAC
.preserved() ||
932 PAC
.preservedSet
<AllAnalysesOn
<LazyCallGraph::SCC
>>()) ||
933 Inv
.invalidate
<TestIndirectSCCAnalysis
>(C
, PA
);
937 TestDoublyIndirectSCCAnalysis(int &Runs
) : Runs(Runs
) {}
939 /// Run the analysis pass over the function and return a result.
940 Result
run(LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
943 auto &IDep
= AM
.getResult
<TestIndirectSCCAnalysis
>(C
, CG
);
948 friend AnalysisInfoMixin
<TestDoublyIndirectSCCAnalysis
>;
949 static AnalysisKey Key
;
954 AnalysisKey
TestDoublyIndirectSCCAnalysis::Key
;
956 /// A test analysis pass which caches results from three different IR unit
957 /// layers and requires intermediate layers to correctly propagate the entire
959 struct TestIndirectFunctionAnalysis
960 : public AnalysisInfoMixin
<TestIndirectFunctionAnalysis
> {
962 Result(TestFunctionAnalysis::Result
&FDep
, TestModuleAnalysis::Result
&MDep
,
963 TestSCCAnalysis::Result
&SCCDep
)
964 : FDep(FDep
), MDep(MDep
), SCCDep(SCCDep
) {}
965 TestFunctionAnalysis::Result
&FDep
;
966 TestModuleAnalysis::Result
&MDep
;
967 TestSCCAnalysis::Result
&SCCDep
;
969 bool invalidate(Function
&F
, const PreservedAnalyses
&PA
,
970 FunctionAnalysisManager::Invalidator
&Inv
) {
971 auto PAC
= PA
.getChecker
<TestIndirectFunctionAnalysis
>();
972 return !(PAC
.preserved() ||
973 PAC
.preservedSet
<AllAnalysesOn
<Function
>>()) ||
974 Inv
.invalidate
<TestFunctionAnalysis
>(F
, PA
);
978 TestIndirectFunctionAnalysis(int &Runs
, ModuleAnalysisManager
&MAM
,
979 CGSCCAnalysisManager
&CGAM
)
980 : Runs(Runs
), MAM(MAM
), CGAM(CGAM
) {}
982 /// Run the analysis pass over the function and return a result.
983 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
985 auto &FDep
= AM
.getResult
<TestFunctionAnalysis
>(F
);
987 auto &ModuleProxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
988 // For the test, we insist that the module analysis starts off in the
989 // cache. Getting a cached result that isn't stateless triggers an assert.
990 // Use MAM, for the purposes of this unittest.
991 auto &MDep
= *MAM
.getCachedResult
<TestModuleAnalysis
>(*F
.getParent());
992 // Register the dependency as module analysis dependencies have to be
993 // pre-registered on the proxy.
994 ModuleProxy
.registerOuterAnalysisInvalidation
<
995 TestModuleAnalysis
, TestIndirectFunctionAnalysis
>();
997 // For the test we assume this is run inside a CGSCC pass manager.
998 // Use MAM, for the purposes of this unittest.
999 const LazyCallGraph
&CG
=
1000 *MAM
.getCachedResult
<LazyCallGraphAnalysis
>(*F
.getParent());
1001 auto &CGSCCProxy
= AM
.getResult
<CGSCCAnalysisManagerFunctionProxy
>(F
);
1002 // For the test, we insist that the CGSCC analysis starts off in the cache.
1003 // Getting a cached result that isn't stateless triggers an assert.
1004 // Use CGAM, for the purposes of this unittest.
1006 *CGAM
.getCachedResult
<TestSCCAnalysis
>(*CG
.lookupSCC(*CG
.lookup(F
)));
1007 // Register the dependency as CGSCC analysis dependencies have to be
1008 // pre-registered on the proxy.
1009 CGSCCProxy
.registerOuterAnalysisInvalidation
<
1010 TestSCCAnalysis
, TestIndirectFunctionAnalysis
>();
1012 return Result(FDep
, MDep
, SCCDep
);
1016 friend AnalysisInfoMixin
<TestIndirectFunctionAnalysis
>;
1017 static AnalysisKey Key
;
1020 ModuleAnalysisManager
&MAM
;
1021 CGSCCAnalysisManager
&CGAM
;
1024 AnalysisKey
TestIndirectFunctionAnalysis::Key
;
1026 TEST_F(CGSCCPassManagerTest
, TestIndirectAnalysisInvalidation
) {
1027 int ModuleAnalysisRuns
= 0;
1028 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
1030 int SCCAnalysisRuns
= 0, IndirectSCCAnalysisRuns
= 0,
1031 DoublyIndirectSCCAnalysisRuns
= 0;
1032 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
1034 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns
, MAM
); });
1035 CGAM
.registerPass([&] {
1036 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns
);
1039 int FunctionAnalysisRuns
= 0, IndirectFunctionAnalysisRuns
= 0;
1040 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
1041 FAM
.registerPass([&] {
1042 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns
, MAM
,
1046 ModulePassManager MPM
;
1048 int FunctionCount
= 0;
1049 CGSCCPassManager CGPM
;
1050 // First just use the analysis to get the function count and preserve
1053 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1054 LazyCallGraph
&CG
, CGSCCUpdateResult
&) {
1055 auto &DoublyIndirectResult
=
1056 AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1057 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
1058 FunctionCount
+= IndirectResult
.SCCDep
.FunctionCount
;
1059 return PreservedAnalyses::all();
1061 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(
1062 RequireAnalysisPass
<TestIndirectFunctionAnalysis
, Function
>()));
1065 // - both analyses for the (f) and (x) SCCs,
1066 // - just the underlying (indirect) analysis for (g) SCC, and
1067 // - just the direct analysis for (h1,h2,h3) SCC.
1069 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1070 LazyCallGraph
&CG
, CGSCCUpdateResult
&) {
1071 auto &DoublyIndirectResult
=
1072 AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1073 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
1074 FunctionCount
+= IndirectResult
.SCCDep
.FunctionCount
;
1075 auto PA
= PreservedAnalyses::none();
1076 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
1077 PA
.preserveSet
<AllAnalysesOn
<Function
>>();
1078 if (C
.getName() == "(g)")
1079 PA
.preserve
<TestSCCAnalysis
>();
1080 else if (C
.getName() == "(h3, h1, h2)")
1081 PA
.preserve
<TestIndirectSCCAnalysis
>();
1084 // Finally, use the analysis again on each SCC (and function), forcing
1085 // re-computation for all of them.
1087 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1088 LazyCallGraph
&CG
, CGSCCUpdateResult
&) {
1089 auto &DoublyIndirectResult
=
1090 AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1091 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
1092 FunctionCount
+= IndirectResult
.SCCDep
.FunctionCount
;
1093 return PreservedAnalyses::all();
1095 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(
1096 RequireAnalysisPass
<TestIndirectFunctionAnalysis
, Function
>()));
1098 // Create a second CGSCC pass manager. This will cause the module-level
1099 // invalidation to occur, which will force yet another invalidation of the
1100 // indirect SCC-level analysis as the module analysis it depends on gets
1102 CGSCCPassManager CGPM2
;
1104 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1105 LazyCallGraph
&CG
, CGSCCUpdateResult
&) {
1106 auto &DoublyIndirectResult
=
1107 AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1108 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
1109 FunctionCount
+= IndirectResult
.SCCDep
.FunctionCount
;
1110 return PreservedAnalyses::all();
1112 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(
1113 RequireAnalysisPass
<TestIndirectFunctionAnalysis
, Function
>()));
1115 // Add a requires pass to populate the module analysis and then our CGSCC
1117 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1118 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1119 // Now require the module analysis again (it will have been invalidated once)
1120 // and then use it again from our second CGSCC pipeline..
1121 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1122 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
1125 // There are generally two possible runs for each of the four SCCs. But
1126 // for one SCC, we only invalidate the indirect analysis so the base one
1127 // only gets run seven times.
1128 EXPECT_EQ(7, SCCAnalysisRuns
);
1129 // The module analysis pass should be run twice here.
1130 EXPECT_EQ(2, ModuleAnalysisRuns
);
1131 // The indirect analysis is invalidated (either directly or indirectly) three
1132 // times for each of four SCCs.
1133 EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns
);
1134 EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns
);
1136 // We run the indirect function analysis once per function the first time.
1137 // Then we re-run it for every SCC but "(g)". Then we re-run it for every
1139 EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns
);
1141 // Four passes count each of six functions once (via SCCs).
1142 EXPECT_EQ(4 * 6, FunctionCount
);
1145 TEST_F(CGSCCPassManagerTest
, TestAnalysisInvalidationCGSCCUpdate
) {
1146 int ModuleAnalysisRuns
= 0;
1147 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
1149 int SCCAnalysisRuns
= 0, IndirectSCCAnalysisRuns
= 0,
1150 DoublyIndirectSCCAnalysisRuns
= 0;
1151 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
1153 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns
, MAM
); });
1154 CGAM
.registerPass([&] {
1155 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns
);
1158 int FunctionAnalysisRuns
= 0, IndirectFunctionAnalysisRuns
= 0;
1159 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
1160 FAM
.registerPass([&] {
1161 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns
, MAM
,
1165 ModulePassManager MPM
;
1167 CGSCCPassManager CGPM
;
1168 // First just use the analysis to get the function count and preserve
1170 using RequireTestIndirectFunctionAnalysisPass
=
1171 RequireAnalysisPass
<TestIndirectFunctionAnalysis
, Function
>;
1172 using RequireTestDoublyIndirectSCCAnalysisPass
=
1173 RequireAnalysisPass
<TestDoublyIndirectSCCAnalysis
, LazyCallGraph::SCC
,
1174 CGSCCAnalysisManager
, LazyCallGraph
&,
1175 CGSCCUpdateResult
&>;
1176 CGPM
.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1177 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(
1178 RequireTestIndirectFunctionAnalysisPass()));
1180 // Next, we inject an SCC pass that invalidates everything for the `(h3, h1,
1181 // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the
1182 // CG. This should successfully invalidate (and force to be re-run) all the
1183 // analyses for that SCC and for the functions.
1185 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1186 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
1187 (void)AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1188 if (C
.getName() != "(h3, h1, h2)")
1189 return PreservedAnalyses::all();
1191 // Build the preserved set.
1192 auto PA
= PreservedAnalyses::none();
1193 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
1194 PA
.preserve
<TestIndirectSCCAnalysis
>();
1195 PA
.preserve
<TestDoublyIndirectSCCAnalysis
>();
1197 // Delete the call from `h2` to `h3`.
1198 auto &H2N
= *llvm::find_if(
1199 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "h2"; });
1200 auto &H2F
= H2N
.getFunction();
1201 auto &H3F
= *cast
<CallInst
>(H2F
.begin()->begin())->getCalledFunction();
1202 assert(H3F
.getName() == "h3" && "Wrong called function!");
1203 H2F
.begin()->begin()->eraseFromParent();
1204 // Insert a bitcast of `h3` so that we retain a ref edge to it.
1205 (void)CastInst::CreatePointerCast(&H3F
,
1206 Type::getInt8PtrTy(H2F
.getContext()),
1207 "dummy", &*H2F
.begin()->begin());
1209 // Now update the call graph.
1211 updateCGAndAnalysisManagerForFunctionPass(CG
, C
, H2N
, AM
, UR
, FAM
);
1212 assert(&NewC
!= &C
&& "Should get a new SCC due to update!");
1217 // Now use the analysis again on each SCC and function, forcing
1218 // re-computation for all of them.
1219 CGPM
.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1220 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(
1221 RequireTestIndirectFunctionAnalysisPass()));
1223 // Create another CGSCC pipeline that requires all the analyses again.
1224 CGSCCPassManager CGPM2
;
1225 CGPM2
.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1226 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(
1227 RequireTestIndirectFunctionAnalysisPass()));
1229 // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3`
1230 // back to `h2`, and then invalidates everything for what will then be the
1231 // `(h3, h1, h2)` SCC again.
1232 CGSCCPassManager CGPM3
;
1234 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1235 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
1236 (void)AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1237 if (C
.getName() != "(h2)")
1238 return PreservedAnalyses::all();
1240 // Build the preserved set.
1241 auto PA
= PreservedAnalyses::none();
1242 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
1243 PA
.preserve
<TestIndirectSCCAnalysis
>();
1244 PA
.preserve
<TestDoublyIndirectSCCAnalysis
>();
1246 // Delete the bitcast of `h3` that we added earlier.
1247 auto &H2N
= *C
.begin();
1248 auto &H2F
= H2N
.getFunction();
1249 auto &H3F
= *cast
<Function
>(cast
<BitCastInst
>(H2F
.begin()->begin())->getOperand(0));
1250 assert(H3F
.getName() == "h3" && "Wrong called function!");
1251 H2F
.begin()->begin()->eraseFromParent();
1252 // And insert a call to `h3`.
1253 (void)CallInst::Create(&H3F
, {}, "", &*H2F
.begin()->begin());
1255 // Now update the call graph.
1257 updateCGAndAnalysisManagerForFunctionPass(CG
, C
, H2N
, AM
, UR
, FAM
);
1258 assert(&NewC
!= &C
&& "Should get a new SCC due to update!");
1263 // Now use the analysis again on each SCC and function, forcing
1264 // re-computation for all of them.
1265 CGPM3
.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1266 CGPM3
.addPass(createCGSCCToFunctionPassAdaptor(
1267 RequireTestIndirectFunctionAnalysisPass()));
1269 // Create a second CGSCC pass manager. This will cause the module-level
1270 // invalidation to occur, which will force yet another invalidation of the
1271 // indirect SCC-level analysis as the module analysis it depends on gets
1273 CGSCCPassManager CGPM4
;
1274 CGPM4
.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1275 CGPM4
.addPass(createCGSCCToFunctionPassAdaptor(
1276 RequireTestIndirectFunctionAnalysisPass()));
1278 // Add a requires pass to populate the module analysis and then one of our
1279 // CGSCC pipelines. Repeat for all four CGSCC pipelines.
1280 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1281 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1282 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1283 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
1284 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1285 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3
)));
1286 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1287 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4
)));
1290 // We run over four SCCs the first time. But then we split an SCC into three.
1291 // And then we merge those three back into one. However, this also
1292 // invalidates all three SCCs further down in the PO walk.
1293 EXPECT_EQ(4 + 3 + 3, SCCAnalysisRuns
);
1294 // The module analysis pass should be run three times.
1295 EXPECT_EQ(3, ModuleAnalysisRuns
);
1296 // We run over four SCCs the first time. Then over the two new ones. Then the
1297 // entire module is invalidated causing a full run over all seven. Then we
1298 // fold three SCCs back to one, re-compute for it and the two SCCs above it
1299 // in the graph, and then run over the whole module again.
1300 EXPECT_EQ(4 + 2 + 7 + 3 + 4, IndirectSCCAnalysisRuns
);
1301 EXPECT_EQ(4 + 2 + 7 + 3 + 4, DoublyIndirectSCCAnalysisRuns
);
1303 // First we run over all six functions. Then we re-run it over three when we
1304 // split their SCCs. Then we re-run over the whole module. Then we re-run
1305 // over three functions merged back into a single SCC, then those three
1306 // functions again, the two functions in SCCs above it in the graph, and then
1307 // over the whole module again.
1308 EXPECT_EQ(6 + 3 + 6 + 3 + 2 + 6, FunctionAnalysisRuns
);
1310 // Re run the function analysis over the entire module, and then re-run it
1311 // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over
1312 // the entire module, then the three functions merged back into a single SCC,
1313 // those three functions again, then the two functions in SCCs above it in
1314 // the graph, and then over the whole module.
1315 EXPECT_EQ(6 + 3 + 6 + 3 + 2 + 6, IndirectFunctionAnalysisRuns
);
1318 // The (negative) tests below check for assertions so we only run them if NDEBUG
1322 struct LambdaSCCPassNoPreserve
: public PassInfoMixin
<LambdaSCCPassNoPreserve
> {
1323 template <typename T
>
1324 LambdaSCCPassNoPreserve(T
&&Arg
) : Func(std::forward
<T
>(Arg
)) {}
1326 PreservedAnalyses
run(LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1327 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
1328 Func(C
, AM
, CG
, UR
);
1329 PreservedAnalyses PA
;
1330 // We update the core CGSCC data structures and so can preserve the proxy to
1331 // the function analysis manager.
1332 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
1336 std::function
<void(LazyCallGraph::SCC
&, CGSCCAnalysisManager
&,
1337 LazyCallGraph
&, CGSCCUpdateResult
&)>
1341 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses0
) {
1342 CGSCCPassManager CGPM
;
1343 CGPM
.addPass(LambdaSCCPassNoPreserve(
1344 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1345 CGSCCUpdateResult
&UR
) {
1346 if (C
.getName() != "(h3, h1, h2)")
1350 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1351 Function
*FnX
= M
->getFunction("x");
1352 Function
*FnH1
= M
->getFunction("h1");
1353 Function
*FnH2
= M
->getFunction("h2");
1354 Function
*FnH3
= M
->getFunction("h3");
1355 ASSERT_NE(FnX
, nullptr);
1356 ASSERT_NE(FnH1
, nullptr);
1357 ASSERT_NE(FnH2
, nullptr);
1358 ASSERT_NE(FnH3
, nullptr);
1360 // And insert a call to `h1`, `h2`, and `h3`.
1361 Instruction
*IP
= &FnH2
->getEntryBlock().front();
1362 (void)CallInst::Create(FnH1
, {}, "", IP
);
1363 (void)CallInst::Create(FnH2
, {}, "", IP
);
1364 (void)CallInst::Create(FnH3
, {}, "", IP
);
1366 auto &H2N
= *llvm::find_if(
1367 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "h2"; });
1368 ASSERT_NO_FATAL_FAILURE(
1369 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, H2N
, AM
, UR
, FAM
));
1372 ModulePassManager MPM
;
1373 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1377 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses1
) {
1378 CGSCCPassManager CGPM
;
1379 CGPM
.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC
&C
,
1380 CGSCCAnalysisManager
&AM
,
1382 CGSCCUpdateResult
&UR
) {
1383 if (C
.getName() != "(h3, h1, h2)")
1387 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1388 Function
*FnX
= M
->getFunction("x");
1389 Function
*FnH1
= M
->getFunction("h1");
1390 Function
*FnH2
= M
->getFunction("h2");
1391 Function
*FnH3
= M
->getFunction("h3");
1392 ASSERT_NE(FnX
, nullptr);
1393 ASSERT_NE(FnH1
, nullptr);
1394 ASSERT_NE(FnH2
, nullptr);
1395 ASSERT_NE(FnH3
, nullptr);
1397 // And insert a call to `h1`, `h2`, and `h3`.
1398 Instruction
*IP
= &FnH2
->getEntryBlock().front();
1399 (void)CallInst::Create(FnH1
, {}, "", IP
);
1400 (void)CallInst::Create(FnH2
, {}, "", IP
);
1401 (void)CallInst::Create(FnH3
, {}, "", IP
);
1403 auto &H2N
= *llvm::find_if(
1404 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "h2"; });
1406 updateCGAndAnalysisManagerForFunctionPass(CG
, C
, H2N
, AM
, UR
, FAM
),
1407 "Any new calls should be modeled as");
1410 ModulePassManager MPM
;
1411 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1415 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses2
) {
1416 CGSCCPassManager CGPM
;
1417 CGPM
.addPass(LambdaSCCPassNoPreserve(
1418 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1419 CGSCCUpdateResult
&UR
) {
1420 if (C
.getName() != "(f)")
1424 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1425 Function
*FnF
= M
->getFunction("f");
1426 Function
*FnH2
= M
->getFunction("h2");
1427 ASSERT_NE(FnF
, nullptr);
1428 ASSERT_NE(FnH2
, nullptr);
1430 // And insert a call to `h2`
1431 Instruction
*IP
= &FnF
->getEntryBlock().front();
1432 (void)CallInst::Create(FnH2
, {}, "", IP
);
1434 auto &FN
= *llvm::find_if(
1435 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "f"; });
1436 ASSERT_NO_FATAL_FAILURE(
1437 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, FN
, AM
, UR
, FAM
));
1440 ModulePassManager MPM
;
1441 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1445 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses3
) {
1446 CGSCCPassManager CGPM
;
1447 CGPM
.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC
&C
,
1448 CGSCCAnalysisManager
&AM
,
1450 CGSCCUpdateResult
&UR
) {
1451 if (C
.getName() != "(f)")
1455 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1456 Function
*FnF
= M
->getFunction("f");
1457 Function
*FnH2
= M
->getFunction("h2");
1458 ASSERT_NE(FnF
, nullptr);
1459 ASSERT_NE(FnH2
, nullptr);
1461 // And insert a call to `h2`
1462 Instruction
*IP
= &FnF
->getEntryBlock().front();
1463 (void)CallInst::Create(FnH2
, {}, "", IP
);
1465 auto &FN
= *llvm::find_if(
1466 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "f"; });
1468 updateCGAndAnalysisManagerForFunctionPass(CG
, C
, FN
, AM
, UR
, FAM
),
1469 "Any new calls should be modeled as");
1472 ModulePassManager MPM
;
1473 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1477 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses4
) {
1478 CGSCCPassManager CGPM
;
1479 CGPM
.addPass(LambdaSCCPassNoPreserve(
1480 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1481 CGSCCUpdateResult
&UR
) {
1482 if (C
.getName() != "(f)")
1486 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1487 Function
*FnF
= M
->getFunction("f");
1488 Function
*FnewF
= Function::Create(FnF
->getFunctionType(),
1489 FnF
->getLinkage(), "newF", *M
);
1490 BasicBlock
*BB
= BasicBlock::Create(FnewF
->getContext(), "", FnewF
);
1491 ReturnInst::Create(FnewF
->getContext(), BB
);
1493 // And insert a call to `newF`
1494 Instruction
*IP
= &FnF
->getEntryBlock().front();
1495 (void)CallInst::Create(FnewF
, {}, "", IP
);
1497 // Use the CallGraphUpdater to update the call graph for the new
1499 CallGraphUpdater CGU
;
1500 CGU
.initialize(CG
, C
, AM
, UR
);
1501 CGU
.registerOutlinedFunction(*FnF
, *FnewF
);
1503 auto &FN
= *llvm::find_if(
1504 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "f"; });
1506 ASSERT_NO_FATAL_FAILURE(
1507 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, FN
, AM
, UR
, FAM
));
1510 ModulePassManager MPM
;
1511 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1515 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses5
) {
1516 CGSCCPassManager CGPM
;
1517 CGPM
.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC
&C
,
1518 CGSCCAnalysisManager
&AM
,
1520 CGSCCUpdateResult
&UR
) {
1521 if (C
.getName() != "(f)")
1525 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1526 Function
*FnF
= M
->getFunction("f");
1528 Function::Create(FnF
->getFunctionType(), FnF
->getLinkage(), "newF", *M
);
1529 BasicBlock
*BB
= BasicBlock::Create(FnewF
->getContext(), "", FnewF
);
1530 ReturnInst::Create(FnewF
->getContext(), BB
);
1532 // Use the CallGraphUpdater to update the call graph for the new
1534 CallGraphUpdater CGU
;
1535 CGU
.initialize(CG
, C
, AM
, UR
);
1537 // And insert a call to `newF`
1538 Instruction
*IP
= &FnF
->getEntryBlock().front();
1539 (void)CallInst::Create(FnewF
, {}, "", IP
);
1541 auto &FN
= *llvm::find_if(
1542 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "f"; });
1544 ASSERT_DEATH(updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, FN
, AM
, UR
, FAM
),
1545 "should already have an associated node");
1548 ModulePassManager MPM
;
1549 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1553 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses6
) {
1554 CGSCCPassManager CGPM
;
1555 CGPM
.addPass(LambdaSCCPassNoPreserve(
1556 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1557 CGSCCUpdateResult
&UR
) {
1558 if (C
.getName() != "(h3, h1, h2)")
1561 Function
*FnX
= M
->getFunction("x");
1562 Function
*FnH1
= M
->getFunction("h1");
1563 Function
*FnH2
= M
->getFunction("h2");
1564 Function
*FnH3
= M
->getFunction("h3");
1565 ASSERT_NE(FnX
, nullptr);
1566 ASSERT_NE(FnH1
, nullptr);
1567 ASSERT_NE(FnH2
, nullptr);
1568 ASSERT_NE(FnH3
, nullptr);
1570 // And insert a call to `h1`, `h2`, and `h3`.
1571 Instruction
*IP
= &FnH2
->getEntryBlock().front();
1572 (void)CallInst::Create(FnH1
, {}, "", IP
);
1573 (void)CallInst::Create(FnH2
, {}, "", IP
);
1574 (void)CallInst::Create(FnH3
, {}, "", IP
);
1576 // Use the CallGraphUpdater to update the call graph for the new
1578 CallGraphUpdater CGU
;
1579 CGU
.initialize(CG
, C
, AM
, UR
);
1580 ASSERT_NO_FATAL_FAILURE(CGU
.reanalyzeFunction(*FnH2
));
1583 ModulePassManager MPM
;
1584 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1588 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses7
) {
1589 CGSCCPassManager CGPM
;
1590 CGPM
.addPass(LambdaSCCPassNoPreserve(
1591 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1592 CGSCCUpdateResult
&UR
) {
1593 if (C
.getName() != "(f)")
1596 Function
*FnF
= M
->getFunction("f");
1597 Function
*FnH2
= M
->getFunction("h2");
1598 ASSERT_NE(FnF
, nullptr);
1599 ASSERT_NE(FnH2
, nullptr);
1601 // And insert a call to `h2`
1602 Instruction
*IP
= &FnF
->getEntryBlock().front();
1603 (void)CallInst::Create(FnH2
, {}, "", IP
);
1605 // Use the CallGraphUpdater to update the call graph for the new
1607 CallGraphUpdater CGU
;
1608 CGU
.initialize(CG
, C
, AM
, UR
);
1609 ASSERT_NO_FATAL_FAILURE(CGU
.reanalyzeFunction(*FnF
));
1612 ModulePassManager MPM
;
1613 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1617 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses8
) {
1618 CGSCCPassManager CGPM
;
1619 CGPM
.addPass(LambdaSCCPassNoPreserve(
1620 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1621 CGSCCUpdateResult
&UR
) {
1622 if (C
.getName() != "(f)")
1625 Function
*FnF
= M
->getFunction("f");
1626 Function
*FnewF
= Function::Create(FnF
->getFunctionType(),
1627 FnF
->getLinkage(), "newF", *M
);
1628 BasicBlock
*BB
= BasicBlock::Create(FnewF
->getContext(), "", FnewF
);
1629 auto *RI
= ReturnInst::Create(FnewF
->getContext(), BB
);
1630 while (FnF
->getEntryBlock().size() > 1)
1631 FnF
->getEntryBlock().front().moveBefore(RI
);
1632 ASSERT_NE(FnF
, nullptr);
1634 // Create an unsused constant that is referencing the old (=replaced)
1636 ConstantExpr::getBitCast(FnF
, Type::getInt8PtrTy(FnF
->getContext()));
1638 // Use the CallGraphUpdater to update the call graph.
1639 CallGraphUpdater CGU
;
1640 CGU
.initialize(CG
, C
, AM
, UR
);
1641 ASSERT_NO_FATAL_FAILURE(CGU
.replaceFunctionWith(*FnF
, *FnewF
));
1642 ASSERT_TRUE(FnF
->isDeclaration());
1643 ASSERT_EQ(FnF
->getNumUses(), 0U);
1646 ModulePassManager MPM
;
1647 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1651 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses9
) {
1652 CGSCCPassManager CGPM
;
1653 CGPM
.addPass(LambdaSCCPassNoPreserve(
1654 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1655 CGSCCUpdateResult
&UR
) {
1656 if (C
.getName() != "(f)")
1659 Function
*FnF
= M
->getFunction("f");
1661 // Use the CallGraphUpdater to update the call graph.
1663 CallGraphUpdater CGU
;
1664 CGU
.initialize(CG
, C
, AM
, UR
);
1665 ASSERT_NO_FATAL_FAILURE(CGU
.removeFunction(*FnF
));
1666 ASSERT_EQ(M
->getFunctionList().size(), 6U);
1668 ASSERT_EQ(M
->getFunctionList().size(), 5U);
1671 ModulePassManager MPM
;
1672 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1676 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses10
) {
1677 CGSCCPassManager CGPM
;
1678 CGPM
.addPass(LambdaSCCPassNoPreserve(
1679 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1680 CGSCCUpdateResult
&UR
) {
1681 if (C
.getName() != "(h3, h1, h2)")
1684 Function
*FnX
= M
->getFunction("x");
1685 Function
*FnH1
= M
->getFunction("h1");
1686 Function
*FnH2
= M
->getFunction("h2");
1687 Function
*FnH3
= M
->getFunction("h3");
1688 ASSERT_NE(FnX
, nullptr);
1689 ASSERT_NE(FnH1
, nullptr);
1690 ASSERT_NE(FnH2
, nullptr);
1691 ASSERT_NE(FnH3
, nullptr);
1693 // And insert a call to `h1`, and `h3`.
1694 Instruction
*IP
= &FnH1
->getEntryBlock().front();
1695 (void)CallInst::Create(FnH1
, {}, "", IP
);
1696 (void)CallInst::Create(FnH3
, {}, "", IP
);
1698 // Remove the `h2` call.
1699 ASSERT_TRUE(isa
<CallBase
>(IP
));
1700 ASSERT_EQ(cast
<CallBase
>(IP
)->getCalledFunction(), FnH2
);
1701 IP
->eraseFromParent();
1703 // Use the CallGraphUpdater to update the call graph.
1704 CallGraphUpdater CGU
;
1705 CGU
.initialize(CG
, C
, AM
, UR
);
1706 ASSERT_NO_FATAL_FAILURE(CGU
.reanalyzeFunction(*FnH1
));
1707 ASSERT_NO_FATAL_FAILURE(CGU
.removeFunction(*FnH2
));
1710 ModulePassManager MPM
;
1711 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1715 // Returns a vector containing the SCC's nodes. Useful for not iterating over an
1716 // SCC while mutating it.
1717 static SmallVector
<LazyCallGraph::Node
*> SCCNodes(LazyCallGraph::SCC
&C
) {
1718 SmallVector
<LazyCallGraph::Node
*> Nodes
;
1720 Nodes
.push_back(&N
);
1725 // Start with call recursive f, create f -> g and ref recursive f.
1726 TEST_F(CGSCCPassManagerTest
, TestInsertionOfNewFunctions1
) {
1727 std::unique_ptr
<Module
> M
= parseIR("define void @f() {\n"
1735 CGSCCPassManager CGPM
;
1736 CGPM
.addPass(LambdaSCCPassNoPreserve(
1737 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1738 CGSCCUpdateResult
&UR
) {
1743 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1745 for (LazyCallGraph::Node
*N
: SCCNodes(C
)) {
1746 Function
&F
= N
->getFunction();
1747 if (F
.getName() != "f")
1750 // Create a new function 'g'.
1751 auto *G
= Function::Create(F
.getFunctionType(), F
.getLinkage(),
1752 F
.getAddressSpace(), "g", F
.getParent());
1754 BasicBlock::Create(F
.getParent()->getContext(), "entry", G
);
1755 (void)ReturnInst::Create(G
->getContext(), GBB
);
1756 // Instruct the LazyCallGraph to create a new node for 'g', as the
1757 // single node in a new SCC, into the call graph. As a result
1758 // the call graph is composed of a single RefSCC with two SCCs:
1761 // "Demote" the 'f -> f' call edge to a ref edge.
1762 // 1. Erase the call edge from 'f' to 'f'.
1763 F
.getEntryBlock().front().eraseFromParent();
1764 // 2. Insert a ref edge from 'f' to 'f'.
1765 (void)CastInst::CreatePointerCast(
1766 &F
, Type::getInt8PtrTy(F
.getContext()), "f.ref",
1767 &F
.getEntryBlock().front());
1768 // 3. Insert a ref edge from 'f' to 'g'.
1769 (void)CastInst::CreatePointerCast(
1770 G
, Type::getInt8PtrTy(F
.getContext()), "g.ref",
1771 &F
.getEntryBlock().front());
1773 CG
.addSplitFunction(F
, *G
);
1775 ASSERT_FALSE(verifyModule(*F
.getParent(), &errs()));
1777 ASSERT_NO_FATAL_FAILURE(
1778 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, *N
, AM
, UR
, FAM
))
1779 << "Updating the call graph with a demoted, self-referential "
1780 "call edge 'f -> f', and a newly inserted ref edge 'f -> g', "
1781 "caused a fatal failure";
1787 ModulePassManager MPM
;
1788 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1793 // Start with f, end with f -> g1, f -> g2, and f -ref-> (h1 <-ref-> h2).
1794 TEST_F(CGSCCPassManagerTest
, TestInsertionOfNewFunctions2
) {
1795 std::unique_ptr
<Module
> M
= parseIR("define void @f() {\n"
1802 CGSCCPassManager CGPM
;
1803 CGPM
.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC
&C
,
1804 CGSCCAnalysisManager
&AM
,
1806 CGSCCUpdateResult
&UR
) {
1811 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1813 for (LazyCallGraph::Node
*N
: SCCNodes(C
)) {
1814 Function
&F
= N
->getFunction();
1815 if (F
.getName() != "f")
1818 // Create g1 and g2.
1819 auto *G1
= Function::Create(F
.getFunctionType(), F
.getLinkage(),
1820 F
.getAddressSpace(), "g1", F
.getParent());
1821 auto *G2
= Function::Create(F
.getFunctionType(), F
.getLinkage(),
1822 F
.getAddressSpace(), "g2", F
.getParent());
1824 BasicBlock::Create(F
.getParent()->getContext(), "entry", G1
);
1826 BasicBlock::Create(F
.getParent()->getContext(), "entry", G2
);
1827 (void)ReturnInst::Create(G1
->getContext(), G1BB
);
1828 (void)ReturnInst::Create(G2
->getContext(), G2BB
);
1830 // Add 'f -> g1' call edge.
1831 (void)CallInst::Create(G1
, {}, "", &F
.getEntryBlock().front());
1832 // Add 'f -> g2' call edge.
1833 (void)CallInst::Create(G2
, {}, "", &F
.getEntryBlock().front());
1835 CG
.addSplitFunction(F
, *G1
);
1836 CG
.addSplitFunction(F
, *G2
);
1838 // Create mutually recursive functions (ref only) 'h1' and 'h2'.
1839 auto *H1
= Function::Create(F
.getFunctionType(), F
.getLinkage(),
1840 F
.getAddressSpace(), "h1", F
.getParent());
1841 auto *H2
= Function::Create(F
.getFunctionType(), F
.getLinkage(),
1842 F
.getAddressSpace(), "h2", F
.getParent());
1844 BasicBlock::Create(F
.getParent()->getContext(), "entry", H1
);
1846 BasicBlock::Create(F
.getParent()->getContext(), "entry", H2
);
1847 (void)CastInst::CreatePointerCast(H2
, Type::getInt8PtrTy(F
.getContext()),
1849 (void)ReturnInst::Create(H1
->getContext(), H1BB
);
1850 (void)CastInst::CreatePointerCast(H1
, Type::getInt8PtrTy(F
.getContext()),
1852 (void)ReturnInst::Create(H2
->getContext(), H2BB
);
1854 // Add 'f -> h1' ref edge.
1855 (void)CastInst::CreatePointerCast(H1
, Type::getInt8PtrTy(F
.getContext()),
1856 "h1.ref", &F
.getEntryBlock().front());
1857 // Add 'f -> h2' ref edge.
1858 (void)CastInst::CreatePointerCast(H2
, Type::getInt8PtrTy(F
.getContext()),
1859 "h2.ref", &F
.getEntryBlock().front());
1861 CG
.addSplitRefRecursiveFunctions(F
, SmallVector
<Function
*, 2>({H1
, H2
}));
1863 ASSERT_FALSE(verifyModule(*F
.getParent(), &errs()));
1865 ASSERT_NO_FATAL_FAILURE(
1866 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, *N
, AM
, UR
, FAM
))
1867 << "Updating the call graph with mutually recursive g1 <-> g2, h1 "
1868 "<-> h2 caused a fatal failure";
1874 ModulePassManager MPM
;
1875 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1880 TEST_F(CGSCCPassManagerTest
, TestInsertionOfNewNonTrivialCallEdge
) {
1881 std::unique_ptr
<Module
> M
= parseIR("define void @f1() {\n"
1883 " %a = bitcast void ()* @f4 to i8*\n"
1884 " %b = bitcast void ()* @f2 to i8*\n"
1887 "define void @f2() {\n"
1889 " %a = bitcast void ()* @f1 to i8*\n"
1890 " %b = bitcast void ()* @f3 to i8*\n"
1893 "define void @f3() {\n"
1895 " %a = bitcast void ()* @f2 to i8*\n"
1896 " %b = bitcast void ()* @f4 to i8*\n"
1899 "define void @f4() {\n"
1901 " %a = bitcast void ()* @f3 to i8*\n"
1902 " %b = bitcast void ()* @f1 to i8*\n"
1907 CGSCCPassManager CGPM
;
1908 CGPM
.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC
&C
,
1909 CGSCCAnalysisManager
&AM
,
1911 CGSCCUpdateResult
&UR
) {
1916 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1918 for (LazyCallGraph::Node
*N
: SCCNodes(C
)) {
1919 Function
&F
= N
->getFunction();
1920 if (F
.getName() != "f1")
1923 Function
*F3
= F
.getParent()->getFunction("f3");
1924 ASSERT_TRUE(F3
!= nullptr);
1926 // Create call from f1 to f3.
1927 (void)CallInst::Create(F3
, {}, "", F
.getEntryBlock().getTerminator());
1929 ASSERT_NO_FATAL_FAILURE(
1930 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, *N
, AM
, UR
, FAM
))
1931 << "Updating the call graph with mutually recursive g1 <-> g2, h1 "
1932 "<-> h2 caused a fatal failure";
1938 ModulePassManager MPM
;
1939 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1945 TEST_F(CGSCCPassManagerTest
, TestFunctionPassesAreQueriedForInvalidation
) {
1946 std::unique_ptr
<Module
> M
= parseIR("define void @f() { ret void }");
1947 CGSCCPassManager CGPM
;
1948 bool SCCCalled
= false;
1949 FunctionPassManager FPM
;
1951 FAM
.registerPass([&] { return TestImmutableFunctionAnalysis(ImmRuns
); });
1952 FPM
.addPass(RequireAnalysisPass
<TestImmutableFunctionAnalysis
, Function
>());
1954 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1955 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
1957 return PreservedAnalyses::none();
1959 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(
1960 RequireAnalysisPass
<TestImmutableFunctionAnalysis
, Function
>()));
1961 ModulePassManager MPM
;
1963 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
1964 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1966 ASSERT_EQ(ImmRuns
, 1);
1967 ASSERT_TRUE(SCCCalled
);