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/PassInstrumentation.h"
21 #include "llvm/IR/Verifier.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Transforms/Utils/CallGraphUpdater.h"
24 #include "gtest/gtest.h"
30 class TestModuleAnalysis
: public AnalysisInfoMixin
<TestModuleAnalysis
> {
33 Result(int Count
) : FunctionCount(Count
) {}
35 bool invalidate(Module
&, const PreservedAnalyses
&PA
,
36 ModuleAnalysisManager::Invalidator
&) {
37 // Check whether the analysis or all analyses on modules have been
39 auto PAC
= PA
.getChecker
<TestModuleAnalysis
>();
40 return !(PAC
.preserved() || PAC
.preservedSet
<AllAnalysesOn
<Module
>>());
44 TestModuleAnalysis(int &Runs
) : Runs(Runs
) {}
46 Result
run(Module
&M
, ModuleAnalysisManager
&AM
) {
48 return Result(M
.size());
52 friend AnalysisInfoMixin
<TestModuleAnalysis
>;
53 static AnalysisKey Key
;
58 AnalysisKey
TestModuleAnalysis::Key
;
60 class TestSCCAnalysis
: public AnalysisInfoMixin
<TestSCCAnalysis
> {
63 Result(int Count
) : FunctionCount(Count
) {}
65 bool invalidate(LazyCallGraph::SCC
&, const PreservedAnalyses
&PA
,
66 CGSCCAnalysisManager::Invalidator
&) {
67 // Check whether the analysis or all analyses on SCCs have been
69 auto PAC
= PA
.getChecker
<TestSCCAnalysis
>();
70 return !(PAC
.preserved() ||
71 PAC
.preservedSet
<AllAnalysesOn
<LazyCallGraph::SCC
>>());
75 TestSCCAnalysis(int &Runs
) : Runs(Runs
) {}
77 Result
run(LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&) {
79 return Result(C
.size());
83 friend AnalysisInfoMixin
<TestSCCAnalysis
>;
84 static AnalysisKey Key
;
89 AnalysisKey
TestSCCAnalysis::Key
;
91 class TestFunctionAnalysis
: public AnalysisInfoMixin
<TestFunctionAnalysis
> {
94 Result(int Count
) : InstructionCount(Count
) {}
96 bool invalidate(Function
&, const PreservedAnalyses
&PA
,
97 FunctionAnalysisManager::Invalidator
&) {
98 // Check whether the analysis or all analyses on functions have been
100 auto PAC
= PA
.getChecker
<TestFunctionAnalysis
>();
101 return !(PAC
.preserved() || PAC
.preservedSet
<AllAnalysesOn
<Function
>>());
105 TestFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
107 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
110 for (Instruction
&I
: instructions(F
)) {
114 return Result(Count
);
118 friend AnalysisInfoMixin
<TestFunctionAnalysis
>;
119 static AnalysisKey Key
;
124 AnalysisKey
TestFunctionAnalysis::Key
;
126 class TestImmutableFunctionAnalysis
127 : public AnalysisInfoMixin
<TestImmutableFunctionAnalysis
> {
130 bool invalidate(Function
&, const PreservedAnalyses
&,
131 FunctionAnalysisManager::Invalidator
&) {
136 TestImmutableFunctionAnalysis(int &Runs
) : Runs(Runs
) {}
138 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
144 friend AnalysisInfoMixin
<TestImmutableFunctionAnalysis
>;
145 static AnalysisKey Key
;
150 AnalysisKey
TestImmutableFunctionAnalysis::Key
;
152 struct LambdaModulePass
: public PassInfoMixin
<LambdaModulePass
> {
153 template <typename T
>
154 LambdaModulePass(T
&&Arg
) : Func(std::forward
<T
>(Arg
)) {}
156 PreservedAnalyses
run(Module
&F
, ModuleAnalysisManager
&AM
) {
160 std::function
<PreservedAnalyses(Module
&, ModuleAnalysisManager
&)> Func
;
163 struct LambdaSCCPass
: public PassInfoMixin
<LambdaSCCPass
> {
164 template <typename T
> LambdaSCCPass(T
&&Arg
) : Func(std::forward
<T
>(Arg
)) {}
166 PreservedAnalyses
run(LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
167 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
168 return Func(C
, AM
, CG
, UR
);
171 std::function
<PreservedAnalyses(LazyCallGraph::SCC
&, CGSCCAnalysisManager
&,
172 LazyCallGraph
&, CGSCCUpdateResult
&)>
176 struct LambdaFunctionPass
: public PassInfoMixin
<LambdaFunctionPass
> {
177 template <typename T
>
178 LambdaFunctionPass(T
&&Arg
) : Func(std::forward
<T
>(Arg
)) {}
180 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
) {
184 std::function
<PreservedAnalyses(Function
&, FunctionAnalysisManager
&)> Func
;
187 std::unique_ptr
<Module
> parseIR(const char *IR
) {
188 // We just use a static context here. This is never called from multiple
189 // threads so it is harmless no matter how it is implemented. We just need
190 // the context to outlive the module which it does.
191 static LLVMContext C
;
193 return parseAssemblyString(IR
, Err
, C
);
196 class CGSCCPassManagerTest
: public ::testing::Test
{
199 FunctionAnalysisManager FAM
;
200 CGSCCAnalysisManager CGAM
;
201 ModuleAnalysisManager MAM
;
203 std::unique_ptr
<Module
> M
;
206 CGSCCPassManagerTest()
207 : FAM(), CGAM(), MAM(),
209 // Define a module with the following call graph, where calls go
210 // out the bottom of nodes and enter the top:
224 "define void @x() {\n"
228 "define void @h3() {\n"
233 "define void @h2() {\n"
239 "define void @h1() {\n"
244 "define void @g() {\n"
250 "define void @f() {\n"
256 FAM
.registerPass([&] { return TargetLibraryAnalysis(); });
257 MAM
.registerPass([&] { return LazyCallGraphAnalysis(); });
258 MAM
.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM
); });
260 // Register required pass instrumentation analysis.
261 MAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
262 CGAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
263 FAM
.registerPass([&] { return PassInstrumentationAnalysis(); });
265 // Cross-register proxies.
266 MAM
.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM
); });
267 CGAM
.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); });
268 CGAM
.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM
); });
269 FAM
.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM
); });
270 FAM
.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM
); });
274 TEST_F(CGSCCPassManagerTest
, Basic
) {
275 int FunctionAnalysisRuns
= 0;
276 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
277 int ImmutableFunctionAnalysisRuns
= 0;
278 FAM
.registerPass([&] {
279 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns
);
282 int SCCAnalysisRuns
= 0;
283 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
285 int ModuleAnalysisRuns
= 0;
286 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
288 ModulePassManager MPM
;
289 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
291 CGSCCPassManager CGPM1
;
292 FunctionPassManager FPM1
;
293 int FunctionPassRunCount1
= 0;
294 FPM1
.addPass(LambdaFunctionPass([&](Function
&, FunctionAnalysisManager
&) {
295 ++FunctionPassRunCount1
;
296 return PreservedAnalyses::none();
298 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
300 int SCCPassRunCount1
= 0;
301 int AnalyzedInstrCount1
= 0;
302 int AnalyzedSCCFunctionCount1
= 0;
303 int AnalyzedModuleFunctionCount1
= 0;
305 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
306 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
309 // Note: The proper way to get to a module pass from a CGSCC pass is
310 // through the ModuleAnalysisManagerCGSCCProxy:
312 // const auto &MAMProxy =
313 // AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
315 // However getting a stateful analysis is incorrect usage, and the call
316 // to getCachedResult below asserts:
318 // if (TestModuleAnalysis::Result *TMA =
319 // MAMProxy.getCachedResult<TestModuleAnalysis>(
320 // *C.begin()->getFunction().getParent()))
321 // AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
323 // For the purposes of this unittest, use the above MAM directly.
324 if (TestModuleAnalysis::Result
*TMA
=
325 MAM
.getCachedResult
<TestModuleAnalysis
>(
326 *C
.begin()->getFunction().getParent()))
327 AnalyzedModuleFunctionCount1
+= TMA
->FunctionCount
;
329 FunctionAnalysisManager
&FAM
=
330 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
331 TestSCCAnalysis::Result
&AR
= AM
.getResult
<TestSCCAnalysis
>(C
, CG
);
332 AnalyzedSCCFunctionCount1
+= AR
.FunctionCount
;
333 for (LazyCallGraph::Node
&N
: C
) {
334 TestFunctionAnalysis::Result
&FAR
=
335 FAM
.getResult
<TestFunctionAnalysis
>(N
.getFunction());
336 AnalyzedInstrCount1
+= FAR
.InstructionCount
;
338 // Just ensure we get the immutable results.
339 (void)FAM
.getResult
<TestImmutableFunctionAnalysis
>(N
.getFunction());
342 return PreservedAnalyses::all();
345 FunctionPassManager FPM2
;
346 int FunctionPassRunCount2
= 0;
347 FPM2
.addPass(LambdaFunctionPass([&](Function
&, FunctionAnalysisManager
&) {
348 ++FunctionPassRunCount2
;
349 return PreservedAnalyses::none();
351 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
353 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
355 FunctionPassManager FPM3
;
356 int FunctionPassRunCount3
= 0;
357 FPM3
.addPass(LambdaFunctionPass([&](Function
&, FunctionAnalysisManager
&) {
358 ++FunctionPassRunCount3
;
359 return PreservedAnalyses::none();
361 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3
)));
365 EXPECT_EQ(4, SCCPassRunCount1
);
366 EXPECT_EQ(6, FunctionPassRunCount1
);
367 EXPECT_EQ(6, FunctionPassRunCount2
);
368 EXPECT_EQ(6, FunctionPassRunCount3
);
370 EXPECT_EQ(1, ModuleAnalysisRuns
);
371 EXPECT_EQ(4, SCCAnalysisRuns
);
372 EXPECT_EQ(6, FunctionAnalysisRuns
);
373 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns
);
375 EXPECT_EQ(14, AnalyzedInstrCount1
);
376 EXPECT_EQ(6, AnalyzedSCCFunctionCount1
);
377 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1
);
380 // Test that an SCC pass which fails to preserve a module analysis does in fact
381 // invalidate that module analysis.
382 TEST_F(CGSCCPassManagerTest
, TestSCCPassInvalidatesModuleAnalysis
) {
383 int ModuleAnalysisRuns
= 0;
384 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
386 ModulePassManager MPM
;
387 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
389 // The first CGSCC run we preserve everything and make sure that works and
390 // the module analysis is available in the second CGSCC run from the one
391 // required module pass above.
392 CGSCCPassManager CGPM1
;
393 int CountFoundModuleAnalysis1
= 0;
394 CGPM1
.addPass(LambdaSCCPass([&](LazyCallGraph::SCC
&C
,
395 CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
396 CGSCCUpdateResult
&UR
) {
397 const auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerCGSCCProxy
>(C
, CG
);
398 if (MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(
399 *C
.begin()->getFunction().getParent()))
400 ++CountFoundModuleAnalysis1
;
402 return PreservedAnalyses::all();
404 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
406 // The second CGSCC run checks that the module analysis got preserved the
407 // previous time and in one SCC fails to preserve it.
408 CGSCCPassManager CGPM2
;
409 int CountFoundModuleAnalysis2
= 0;
411 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
412 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
413 const auto &MAMProxy
=
414 AM
.getResult
<ModuleAnalysisManagerCGSCCProxy
>(C
, CG
);
415 if (MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(
416 *C
.begin()->getFunction().getParent()))
417 ++CountFoundModuleAnalysis2
;
419 // Only fail to preserve analyses on one SCC and make sure that gets
421 return C
.getName() == "(g)" ? PreservedAnalyses::none()
422 : PreservedAnalyses::all();
424 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
426 // The third CGSCC run should fail to find a cached module analysis as it
427 // should have been invalidated by the above CGSCC run.
428 CGSCCPassManager CGPM3
;
429 int CountFoundModuleAnalysis3
= 0;
430 CGPM3
.addPass(LambdaSCCPass([&](LazyCallGraph::SCC
&C
,
431 CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
432 CGSCCUpdateResult
&UR
) {
433 const auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerCGSCCProxy
>(C
, CG
);
434 if (MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(
435 *C
.begin()->getFunction().getParent()))
436 ++CountFoundModuleAnalysis3
;
438 return PreservedAnalyses::none();
440 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3
)));
444 EXPECT_EQ(1, ModuleAnalysisRuns
);
445 EXPECT_EQ(4, CountFoundModuleAnalysis1
);
446 EXPECT_EQ(4, CountFoundModuleAnalysis2
);
447 EXPECT_EQ(0, CountFoundModuleAnalysis3
);
450 // Similar to the above, but test that this works for function passes embedded
451 // *within* a CGSCC layer.
452 TEST_F(CGSCCPassManagerTest
, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis
) {
453 int ModuleAnalysisRuns
= 0;
454 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
456 ModulePassManager MPM
;
457 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
459 // The first run we preserve everything and make sure that works and the
460 // module analysis is available in the second run from the one required
461 // module pass above.
462 FunctionPassManager FPM1
;
463 // Start true and mark false if we ever failed to find a module analysis
464 // because we expect this to succeed for each SCC.
465 bool FoundModuleAnalysis1
= true;
466 FPM1
.addPass(LambdaFunctionPass([&](Function
&F
,
467 FunctionAnalysisManager
&AM
) {
468 const auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
469 if (!MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(*F
.getParent()))
470 FoundModuleAnalysis1
= false;
472 return PreservedAnalyses::all();
474 CGSCCPassManager CGPM1
;
475 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
476 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
478 // The second run checks that the module analysis got preserved the previous
479 // time and in one function fails to preserve it.
480 FunctionPassManager FPM2
;
481 // Again, start true and mark false if we ever failed to find a module analysis
482 // because we expect this to succeed for each SCC.
483 bool FoundModuleAnalysis2
= true;
484 FPM2
.addPass(LambdaFunctionPass([&](Function
&F
,
485 FunctionAnalysisManager
&AM
) {
486 const auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
487 if (!MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(*F
.getParent()))
488 FoundModuleAnalysis2
= false;
490 // Only fail to preserve analyses on one SCC and make sure that gets
492 return F
.getName() == "h2" ? PreservedAnalyses::none()
493 : PreservedAnalyses::all();
495 CGSCCPassManager CGPM2
;
496 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
497 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
499 // The third run should fail to find a cached module analysis as it should
500 // have been invalidated by the above run.
501 FunctionPassManager FPM3
;
502 // Start false and mark true if we ever *succeeded* to find a module
503 // analysis, as we expect this to fail for every function.
504 bool FoundModuleAnalysis3
= false;
505 FPM3
.addPass(LambdaFunctionPass([&](Function
&F
,
506 FunctionAnalysisManager
&AM
) {
507 const auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
508 if (MAMProxy
.cachedResultExists
<TestModuleAnalysis
>(*F
.getParent()))
509 FoundModuleAnalysis3
= true;
511 return PreservedAnalyses::none();
513 CGSCCPassManager CGPM3
;
514 CGPM3
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3
)));
515 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3
)));
519 EXPECT_EQ(1, ModuleAnalysisRuns
);
520 EXPECT_TRUE(FoundModuleAnalysis1
);
521 EXPECT_TRUE(FoundModuleAnalysis2
);
522 EXPECT_FALSE(FoundModuleAnalysis3
);
525 // Test that a Module pass which fails to preserve an SCC analysis in fact
526 // invalidates that analysis.
527 TEST_F(CGSCCPassManagerTest
, TestModulePassInvalidatesSCCAnalysis
) {
528 int SCCAnalysisRuns
= 0;
529 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
531 ModulePassManager MPM
;
533 // First force the analysis to be run.
534 CGSCCPassManager CGPM1
;
535 CGPM1
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
536 CGSCCAnalysisManager
, LazyCallGraph
&,
537 CGSCCUpdateResult
&>());
538 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
540 // Now run a module pass that preserves the LazyCallGraph and the proxy but
541 // not the SCC analysis.
542 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
543 PreservedAnalyses PA
;
544 PA
.preserve
<LazyCallGraphAnalysis
>();
545 PA
.preserve
<CGSCCAnalysisManagerModuleProxy
>();
546 PA
.preserve
<FunctionAnalysisManagerModuleProxy
>();
550 // And now a second CGSCC run which requires the SCC analysis again. This
551 // will trigger re-running it.
552 CGSCCPassManager CGPM2
;
553 CGPM2
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
554 CGSCCAnalysisManager
, LazyCallGraph
&,
555 CGSCCUpdateResult
&>());
556 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
559 // Two runs and four SCCs.
560 EXPECT_EQ(2 * 4, SCCAnalysisRuns
);
563 // Check that marking the SCC analysis preserved is sufficient to avoid
564 // invaliadtion. This should only run the analysis once for each SCC.
565 TEST_F(CGSCCPassManagerTest
, TestModulePassCanPreserveSCCAnalysis
) {
566 int SCCAnalysisRuns
= 0;
567 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
569 ModulePassManager MPM
;
571 // First force the analysis to be run.
572 CGSCCPassManager CGPM1
;
573 CGPM1
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
574 CGSCCAnalysisManager
, LazyCallGraph
&,
575 CGSCCUpdateResult
&>());
576 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
578 // Now run a module pass that preserves each of the necessary components
579 // (but not everything).
580 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
581 PreservedAnalyses PA
;
582 PA
.preserve
<LazyCallGraphAnalysis
>();
583 PA
.preserve
<CGSCCAnalysisManagerModuleProxy
>();
584 PA
.preserve
<FunctionAnalysisManagerModuleProxy
>();
585 PA
.preserve
<TestSCCAnalysis
>();
589 // And now a second CGSCC run which requires the SCC analysis again but find
591 CGSCCPassManager CGPM2
;
592 CGPM2
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
593 CGSCCAnalysisManager
, LazyCallGraph
&,
594 CGSCCUpdateResult
&>());
595 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
599 EXPECT_EQ(4, SCCAnalysisRuns
);
602 // Check that even when the analysis is preserved, if the SCC information isn't
603 // we still nuke things because the SCC keys could change.
604 TEST_F(CGSCCPassManagerTest
, TestModulePassInvalidatesSCCAnalysisOnCGChange
) {
605 int SCCAnalysisRuns
= 0;
606 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
608 ModulePassManager MPM
;
610 // First force the analysis to be run.
611 CGSCCPassManager CGPM1
;
612 CGPM1
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
613 CGSCCAnalysisManager
, LazyCallGraph
&,
614 CGSCCUpdateResult
&>());
615 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
617 // Now run a module pass that preserves the analysis but not the call
619 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
620 PreservedAnalyses PA
;
621 PA
.preserve
<TestSCCAnalysis
>();
625 // And now a second CGSCC run which requires the SCC analysis again.
626 CGSCCPassManager CGPM2
;
627 CGPM2
.addPass(RequireAnalysisPass
<TestSCCAnalysis
, LazyCallGraph::SCC
,
628 CGSCCAnalysisManager
, LazyCallGraph
&,
629 CGSCCUpdateResult
&>());
630 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
633 // Two runs and four SCCs.
634 EXPECT_EQ(2 * 4, SCCAnalysisRuns
);
637 // Test that an SCC pass which fails to preserve a Function analysis in fact
638 // invalidates that analysis.
639 TEST_F(CGSCCPassManagerTest
, TestSCCPassInvalidatesFunctionAnalysis
) {
640 int FunctionAnalysisRuns
= 0;
641 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
643 // Create a very simple module with a single function and SCC to make testing
644 // these issues much easier.
645 std::unique_ptr
<Module
> M
= parseIR("declare void @g()\n"
646 "declare void @h()\n"
647 "define void @f() {\n"
654 CGSCCPassManager CGPM
;
656 // First force the analysis to be run.
657 FunctionPassManager FPM1
;
658 FPM1
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
659 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
661 // Now run a module pass that preserves the LazyCallGraph and proxy but not
663 CGPM
.addPass(LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&,
664 LazyCallGraph
&, CGSCCUpdateResult
&) {
665 PreservedAnalyses PA
;
666 PA
.preserve
<LazyCallGraphAnalysis
>();
670 // And now a second CGSCC run which requires the SCC analysis again. This
671 // will trigger re-running it.
672 FunctionPassManager FPM2
;
673 FPM2
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
674 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
676 ModulePassManager MPM
;
677 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
679 EXPECT_EQ(2, FunctionAnalysisRuns
);
682 // Check that marking the SCC analysis preserved is sufficient. This should
683 // only run the analysis once the SCC.
684 TEST_F(CGSCCPassManagerTest
, TestSCCPassCanPreserveFunctionAnalysis
) {
685 int FunctionAnalysisRuns
= 0;
686 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
688 // Create a very simple module with a single function and SCC to make testing
689 // these issues much easier.
690 std::unique_ptr
<Module
> M
= parseIR("declare void @g()\n"
691 "declare void @h()\n"
692 "define void @f() {\n"
699 CGSCCPassManager CGPM
;
701 // First force the analysis to be run.
702 FunctionPassManager FPM1
;
703 FPM1
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
704 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
706 // Now run a module pass that preserves each of the necessary components
709 CGPM
.addPass(LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&,
710 LazyCallGraph
&, CGSCCUpdateResult
&) {
711 PreservedAnalyses PA
;
712 PA
.preserve
<LazyCallGraphAnalysis
>();
713 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
714 PA
.preserve
<TestFunctionAnalysis
>();
718 // And now a second CGSCC run which requires the SCC analysis again but find
720 FunctionPassManager FPM2
;
721 FPM2
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
722 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
724 ModulePassManager MPM
;
725 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
727 EXPECT_EQ(1, FunctionAnalysisRuns
);
730 // Note that there is no test for invalidating the call graph or other
731 // structure with an SCC pass because there is no mechanism to do that from
732 // withinsuch a pass. Instead, such a pass has to directly update the call
735 // Test that a madule pass invalidates function analyses when the CGSCC proxies
737 TEST_F(CGSCCPassManagerTest
,
738 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC
) {
739 MAM
.registerPass([&] { return LazyCallGraphAnalysis(); });
741 int FunctionAnalysisRuns
= 0;
742 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
744 ModulePassManager MPM
;
746 // First force the analysis to be run.
747 FunctionPassManager FPM1
;
748 FPM1
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
749 CGSCCPassManager CGPM1
;
750 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
751 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
753 // Now run a module pass that preserves the LazyCallGraph and proxies but not
754 // the Function analysis.
755 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
756 PreservedAnalyses PA
;
757 PA
.preserve
<LazyCallGraphAnalysis
>();
758 PA
.preserve
<CGSCCAnalysisManagerModuleProxy
>();
759 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
760 PA
.preserve
<FunctionAnalysisManagerModuleProxy
>();
764 // And now a second CGSCC run which requires the SCC analysis again. This
765 // will trigger re-running it.
766 FunctionPassManager FPM2
;
767 FPM2
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
768 CGSCCPassManager CGPM2
;
769 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
770 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
773 // Two runs and 6 functions.
774 EXPECT_EQ(2 * 6, FunctionAnalysisRuns
);
777 // Check that by marking the function pass and proxies as preserved, this
778 // propagates all the way through.
779 TEST_F(CGSCCPassManagerTest
,
780 TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC
) {
781 MAM
.registerPass([&] { return LazyCallGraphAnalysis(); });
783 int FunctionAnalysisRuns
= 0;
784 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
786 ModulePassManager MPM
;
788 // First force the analysis to be run.
789 FunctionPassManager FPM1
;
790 FPM1
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
791 CGSCCPassManager CGPM1
;
792 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
793 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
795 // Now run a module pass that preserves the LazyCallGraph, the proxy, and
796 // the Function analysis.
797 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
798 PreservedAnalyses PA
;
799 PA
.preserve
<LazyCallGraphAnalysis
>();
800 PA
.preserve
<CGSCCAnalysisManagerModuleProxy
>();
801 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
802 PA
.preserve
<FunctionAnalysisManagerModuleProxy
>();
803 PA
.preserve
<TestFunctionAnalysis
>();
807 // And now a second CGSCC run which requires the SCC analysis again. This
808 // will trigger re-running it.
809 FunctionPassManager FPM2
;
810 FPM2
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
811 CGSCCPassManager CGPM2
;
812 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
813 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
816 // One run and 6 functions.
817 EXPECT_EQ(6, FunctionAnalysisRuns
);
820 // Check that if the lazy call graph itself isn't preserved we still manage to
821 // invalidate everything.
822 TEST_F(CGSCCPassManagerTest
,
823 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange
) {
824 MAM
.registerPass([&] { return LazyCallGraphAnalysis(); });
826 int FunctionAnalysisRuns
= 0;
827 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
829 ModulePassManager MPM
;
831 // First force the analysis to be run.
832 FunctionPassManager FPM1
;
833 FPM1
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
834 CGSCCPassManager CGPM1
;
835 CGPM1
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1
)));
836 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1
)));
838 // Now run a module pass that preserves the LazyCallGraph but not the
839 // Function analysis.
840 MPM
.addPass(LambdaModulePass([&](Module
&M
, ModuleAnalysisManager
&) {
841 PreservedAnalyses PA
;
845 // And now a second CGSCC run which requires the SCC analysis again. This
846 // will trigger re-running it.
847 FunctionPassManager FPM2
;
848 FPM2
.addPass(RequireAnalysisPass
<TestFunctionAnalysis
, Function
>());
849 CGSCCPassManager CGPM2
;
850 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2
)));
851 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
854 // Two runs and 6 functions.
855 EXPECT_EQ(2 * 6, FunctionAnalysisRuns
);
858 /// A test CGSCC-level analysis pass which caches in its result another
859 /// analysis pass and uses it to serve queries. This requires the result to
860 /// invalidate itself when its dependency is invalidated.
862 /// FIXME: Currently this doesn't also depend on a function analysis, and if it
863 /// did we would fail to invalidate it correctly.
864 struct TestIndirectSCCAnalysis
865 : public AnalysisInfoMixin
<TestIndirectSCCAnalysis
> {
867 Result(TestSCCAnalysis::Result
&SCCDep
, TestModuleAnalysis::Result
&MDep
)
868 : SCCDep(SCCDep
), MDep(MDep
) {}
869 TestSCCAnalysis::Result
&SCCDep
;
870 TestModuleAnalysis::Result
&MDep
;
872 bool invalidate(LazyCallGraph::SCC
&C
, const PreservedAnalyses
&PA
,
873 CGSCCAnalysisManager::Invalidator
&Inv
) {
874 auto PAC
= PA
.getChecker
<TestIndirectSCCAnalysis
>();
875 return !(PAC
.preserved() ||
876 PAC
.preservedSet
<AllAnalysesOn
<LazyCallGraph::SCC
>>()) ||
877 Inv
.invalidate
<TestSCCAnalysis
>(C
, PA
);
881 TestIndirectSCCAnalysis(int &Runs
, ModuleAnalysisManager
&MAM
)
882 : Runs(Runs
), MAM(MAM
) {}
884 /// Run the analysis pass over the function and return a result.
885 Result
run(LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
888 auto &SCCDep
= AM
.getResult
<TestSCCAnalysis
>(C
, CG
);
890 auto &ModuleProxy
= AM
.getResult
<ModuleAnalysisManagerCGSCCProxy
>(C
, CG
);
891 // For the test, we insist that the module analysis starts off in the
892 // cache. Getting a cached result that isn't stateless triggers an assert.
893 // auto &MDep = *ModuleProxy.getCachedResult<TestModuleAnalysis>(
894 // *C.begin()->getFunction().getParent());
895 // Use MAM, for the purposes of this unittest.
896 auto &MDep
= *MAM
.getCachedResult
<TestModuleAnalysis
>(
897 *C
.begin()->getFunction().getParent());
898 // Register the dependency as module analysis dependencies have to be
899 // pre-registered on the proxy.
900 ModuleProxy
.registerOuterAnalysisInvalidation
<TestModuleAnalysis
,
901 TestIndirectSCCAnalysis
>();
903 return Result(SCCDep
, MDep
);
907 friend AnalysisInfoMixin
<TestIndirectSCCAnalysis
>;
908 static AnalysisKey Key
;
911 ModuleAnalysisManager
&MAM
;
914 AnalysisKey
TestIndirectSCCAnalysis::Key
;
916 /// A test analysis pass which caches in its result the result from the above
917 /// indirect analysis pass.
919 /// This allows us to ensure that whenever an analysis pass is invalidated due
920 /// to dependencies (especially dependencies across IR units that trigger
921 /// asynchronous invalidation) we correctly detect that this may in turn cause
922 /// other analysis to be invalidated.
923 struct TestDoublyIndirectSCCAnalysis
924 : public AnalysisInfoMixin
<TestDoublyIndirectSCCAnalysis
> {
926 Result(TestIndirectSCCAnalysis::Result
&IDep
) : IDep(IDep
) {}
927 TestIndirectSCCAnalysis::Result
&IDep
;
929 bool invalidate(LazyCallGraph::SCC
&C
, const PreservedAnalyses
&PA
,
930 CGSCCAnalysisManager::Invalidator
&Inv
) {
931 auto PAC
= PA
.getChecker
<TestDoublyIndirectSCCAnalysis
>();
932 return !(PAC
.preserved() ||
933 PAC
.preservedSet
<AllAnalysesOn
<LazyCallGraph::SCC
>>()) ||
934 Inv
.invalidate
<TestIndirectSCCAnalysis
>(C
, PA
);
938 TestDoublyIndirectSCCAnalysis(int &Runs
) : Runs(Runs
) {}
940 /// Run the analysis pass over the function and return a result.
941 Result
run(LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
944 auto &IDep
= AM
.getResult
<TestIndirectSCCAnalysis
>(C
, CG
);
949 friend AnalysisInfoMixin
<TestDoublyIndirectSCCAnalysis
>;
950 static AnalysisKey Key
;
955 AnalysisKey
TestDoublyIndirectSCCAnalysis::Key
;
957 /// A test analysis pass which caches results from three different IR unit
958 /// layers and requires intermediate layers to correctly propagate the entire
960 struct TestIndirectFunctionAnalysis
961 : public AnalysisInfoMixin
<TestIndirectFunctionAnalysis
> {
963 Result(TestFunctionAnalysis::Result
&FDep
, TestModuleAnalysis::Result
&MDep
,
964 TestSCCAnalysis::Result
&SCCDep
)
965 : FDep(FDep
), MDep(MDep
), SCCDep(SCCDep
) {}
966 TestFunctionAnalysis::Result
&FDep
;
967 TestModuleAnalysis::Result
&MDep
;
968 TestSCCAnalysis::Result
&SCCDep
;
970 bool invalidate(Function
&F
, const PreservedAnalyses
&PA
,
971 FunctionAnalysisManager::Invalidator
&Inv
) {
972 auto PAC
= PA
.getChecker
<TestIndirectFunctionAnalysis
>();
973 return !(PAC
.preserved() ||
974 PAC
.preservedSet
<AllAnalysesOn
<Function
>>()) ||
975 Inv
.invalidate
<TestFunctionAnalysis
>(F
, PA
);
979 TestIndirectFunctionAnalysis(int &Runs
, ModuleAnalysisManager
&MAM
,
980 CGSCCAnalysisManager
&CGAM
)
981 : Runs(Runs
), MAM(MAM
), CGAM(CGAM
) {}
983 /// Run the analysis pass over the function and return a result.
984 Result
run(Function
&F
, FunctionAnalysisManager
&AM
) {
986 auto &FDep
= AM
.getResult
<TestFunctionAnalysis
>(F
);
988 auto &ModuleProxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
989 // For the test, we insist that the module analysis starts off in the
990 // cache. Getting a cached result that isn't stateless triggers an assert.
991 // Use MAM, for the purposes of this unittest.
992 auto &MDep
= *MAM
.getCachedResult
<TestModuleAnalysis
>(*F
.getParent());
993 // Register the dependency as module analysis dependencies have to be
994 // pre-registered on the proxy.
995 ModuleProxy
.registerOuterAnalysisInvalidation
<
996 TestModuleAnalysis
, TestIndirectFunctionAnalysis
>();
998 // For the test we assume this is run inside a CGSCC pass manager.
999 // Use MAM, for the purposes of this unittest.
1000 const LazyCallGraph
&CG
=
1001 *MAM
.getCachedResult
<LazyCallGraphAnalysis
>(*F
.getParent());
1002 auto &CGSCCProxy
= AM
.getResult
<CGSCCAnalysisManagerFunctionProxy
>(F
);
1003 // For the test, we insist that the CGSCC analysis starts off in the cache.
1004 // Getting a cached result that isn't stateless triggers an assert.
1005 // Use CGAM, for the purposes of this unittest.
1007 *CGAM
.getCachedResult
<TestSCCAnalysis
>(*CG
.lookupSCC(*CG
.lookup(F
)));
1008 // Register the dependency as CGSCC analysis dependencies have to be
1009 // pre-registered on the proxy.
1010 CGSCCProxy
.registerOuterAnalysisInvalidation
<
1011 TestSCCAnalysis
, TestIndirectFunctionAnalysis
>();
1013 return Result(FDep
, MDep
, SCCDep
);
1017 friend AnalysisInfoMixin
<TestIndirectFunctionAnalysis
>;
1018 static AnalysisKey Key
;
1021 ModuleAnalysisManager
&MAM
;
1022 CGSCCAnalysisManager
&CGAM
;
1025 AnalysisKey
TestIndirectFunctionAnalysis::Key
;
1027 TEST_F(CGSCCPassManagerTest
, TestIndirectAnalysisInvalidation
) {
1028 int ModuleAnalysisRuns
= 0;
1029 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
1031 int SCCAnalysisRuns
= 0, IndirectSCCAnalysisRuns
= 0,
1032 DoublyIndirectSCCAnalysisRuns
= 0;
1033 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
1035 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns
, MAM
); });
1036 CGAM
.registerPass([&] {
1037 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns
);
1040 int FunctionAnalysisRuns
= 0, IndirectFunctionAnalysisRuns
= 0;
1041 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
1042 FAM
.registerPass([&] {
1043 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns
, MAM
,
1047 ModulePassManager MPM
;
1049 int FunctionCount
= 0;
1050 CGSCCPassManager CGPM
;
1051 // First just use the analysis to get the function count and preserve
1054 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1055 LazyCallGraph
&CG
, CGSCCUpdateResult
&) {
1056 auto &DoublyIndirectResult
=
1057 AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1058 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
1059 FunctionCount
+= IndirectResult
.SCCDep
.FunctionCount
;
1060 return PreservedAnalyses::all();
1062 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(
1063 RequireAnalysisPass
<TestIndirectFunctionAnalysis
, Function
>()));
1066 // - both analyses for the (f) and (x) SCCs,
1067 // - just the underlying (indirect) analysis for (g) SCC, and
1068 // - just the direct analysis for (h1,h2,h3) SCC.
1070 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1071 LazyCallGraph
&CG
, CGSCCUpdateResult
&) {
1072 auto &DoublyIndirectResult
=
1073 AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1074 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
1075 FunctionCount
+= IndirectResult
.SCCDep
.FunctionCount
;
1076 auto PA
= PreservedAnalyses::none();
1077 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
1078 PA
.preserveSet
<AllAnalysesOn
<Function
>>();
1079 if (C
.getName() == "(g)")
1080 PA
.preserve
<TestSCCAnalysis
>();
1081 else if (C
.getName() == "(h3, h1, h2)")
1082 PA
.preserve
<TestIndirectSCCAnalysis
>();
1085 // Finally, use the analysis again on each SCC (and function), forcing
1086 // re-computation for all of them.
1088 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1089 LazyCallGraph
&CG
, CGSCCUpdateResult
&) {
1090 auto &DoublyIndirectResult
=
1091 AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1092 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
1093 FunctionCount
+= IndirectResult
.SCCDep
.FunctionCount
;
1094 return PreservedAnalyses::all();
1096 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(
1097 RequireAnalysisPass
<TestIndirectFunctionAnalysis
, Function
>()));
1099 // Create a second CGSCC pass manager. This will cause the module-level
1100 // invalidation to occur, which will force yet another invalidation of the
1101 // indirect SCC-level analysis as the module analysis it depends on gets
1103 CGSCCPassManager CGPM2
;
1105 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1106 LazyCallGraph
&CG
, CGSCCUpdateResult
&) {
1107 auto &DoublyIndirectResult
=
1108 AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1109 auto &IndirectResult
= DoublyIndirectResult
.IDep
;
1110 FunctionCount
+= IndirectResult
.SCCDep
.FunctionCount
;
1111 return PreservedAnalyses::all();
1113 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(
1114 RequireAnalysisPass
<TestIndirectFunctionAnalysis
, Function
>()));
1116 // Add a requires pass to populate the module analysis and then our CGSCC
1118 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1119 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1120 // Now require the module analysis again (it will have been invalidated once)
1121 // and then use it again from our second CGSCC pipeline..
1122 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1123 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
1126 // There are generally two possible runs for each of the four SCCs. But
1127 // for one SCC, we only invalidate the indirect analysis so the base one
1128 // only gets run seven times.
1129 EXPECT_EQ(7, SCCAnalysisRuns
);
1130 // The module analysis pass should be run twice here.
1131 EXPECT_EQ(2, ModuleAnalysisRuns
);
1132 // The indirect analysis is invalidated (either directly or indirectly) three
1133 // times for each of four SCCs.
1134 EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns
);
1135 EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns
);
1137 // We run the indirect function analysis once per function the first time.
1138 // Then we re-run it for every SCC but "(g)". Then we re-run it for every
1140 EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns
);
1142 // Four passes count each of six functions once (via SCCs).
1143 EXPECT_EQ(4 * 6, FunctionCount
);
1146 TEST_F(CGSCCPassManagerTest
, TestAnalysisInvalidationCGSCCUpdate
) {
1147 int ModuleAnalysisRuns
= 0;
1148 MAM
.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns
); });
1150 int SCCAnalysisRuns
= 0, IndirectSCCAnalysisRuns
= 0,
1151 DoublyIndirectSCCAnalysisRuns
= 0;
1152 CGAM
.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns
); });
1154 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns
, MAM
); });
1155 CGAM
.registerPass([&] {
1156 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns
);
1159 int FunctionAnalysisRuns
= 0, IndirectFunctionAnalysisRuns
= 0;
1160 FAM
.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns
); });
1161 FAM
.registerPass([&] {
1162 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns
, MAM
,
1166 ModulePassManager MPM
;
1168 CGSCCPassManager CGPM
;
1169 // First just use the analysis to get the function count and preserve
1171 using RequireTestIndirectFunctionAnalysisPass
=
1172 RequireAnalysisPass
<TestIndirectFunctionAnalysis
, Function
>;
1173 using RequireTestDoublyIndirectSCCAnalysisPass
=
1174 RequireAnalysisPass
<TestDoublyIndirectSCCAnalysis
, LazyCallGraph::SCC
,
1175 CGSCCAnalysisManager
, LazyCallGraph
&,
1176 CGSCCUpdateResult
&>;
1177 CGPM
.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1178 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(
1179 RequireTestIndirectFunctionAnalysisPass()));
1181 // Next, we inject an SCC pass that invalidates everything for the `(h3, h1,
1182 // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the
1183 // CG. This should successfully invalidate (and force to be re-run) all the
1184 // analyses for that SCC and for the functions.
1186 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1187 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
1188 (void)AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1189 if (C
.getName() != "(h3, h1, h2)")
1190 return PreservedAnalyses::all();
1192 // Build the preserved set.
1193 auto PA
= PreservedAnalyses::none();
1194 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
1195 PA
.preserve
<TestIndirectSCCAnalysis
>();
1196 PA
.preserve
<TestDoublyIndirectSCCAnalysis
>();
1198 // Delete the call from `h2` to `h3`.
1199 auto &H2N
= *llvm::find_if(
1200 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "h2"; });
1201 auto &H2F
= H2N
.getFunction();
1202 auto &H3F
= *cast
<CallInst
>(H2F
.begin()->begin())->getCalledFunction();
1203 assert(H3F
.getName() == "h3" && "Wrong called function!");
1204 H2F
.begin()->begin()->eraseFromParent();
1205 // Insert a bitcast of `h3` so that we retain a ref edge to it.
1206 (void)CastInst::CreatePointerCast(
1207 &H3F
, PointerType::getUnqual(H2F
.getContext()), "dummy",
1208 H2F
.begin()->begin());
1210 // Now update the call graph.
1212 updateCGAndAnalysisManagerForFunctionPass(CG
, C
, H2N
, AM
, UR
, FAM
);
1213 assert(&NewC
!= &C
&& "Should get a new SCC due to update!");
1218 // Now use the analysis again on each SCC and function, forcing
1219 // re-computation for all of them.
1220 CGPM
.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1221 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(
1222 RequireTestIndirectFunctionAnalysisPass()));
1224 // Create another CGSCC pipeline that requires all the analyses again.
1225 CGSCCPassManager CGPM2
;
1226 CGPM2
.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1227 CGPM2
.addPass(createCGSCCToFunctionPassAdaptor(
1228 RequireTestIndirectFunctionAnalysisPass()));
1230 // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3`
1231 // back to `h2`, and then invalidates everything for what will then be the
1232 // `(h3, h1, h2)` SCC again.
1233 CGSCCPassManager CGPM3
;
1235 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1236 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
1237 (void)AM
.getResult
<TestDoublyIndirectSCCAnalysis
>(C
, CG
);
1238 if (C
.getName() != "(h2)")
1239 return PreservedAnalyses::all();
1241 // Build the preserved set.
1242 auto PA
= PreservedAnalyses::none();
1243 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
1244 PA
.preserve
<TestIndirectSCCAnalysis
>();
1245 PA
.preserve
<TestDoublyIndirectSCCAnalysis
>();
1247 // Delete the bitcast of `h3` that we added earlier.
1248 auto &H2N
= *C
.begin();
1249 auto &H2F
= H2N
.getFunction();
1250 auto &H3F
= *cast
<Function
>(cast
<BitCastInst
>(H2F
.begin()->begin())->getOperand(0));
1251 assert(H3F
.getName() == "h3" && "Wrong called function!");
1252 H2F
.begin()->begin()->eraseFromParent();
1253 // And insert a call to `h3`.
1254 (void)CallInst::Create(&H3F
, {}, "", H2F
.begin()->begin());
1256 // Now update the call graph.
1258 updateCGAndAnalysisManagerForFunctionPass(CG
, C
, H2N
, AM
, UR
, FAM
);
1259 assert(&NewC
!= &C
&& "Should get a new SCC due to update!");
1264 // Now use the analysis again on each SCC and function, forcing
1265 // re-computation for all of them.
1266 CGPM3
.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1267 CGPM3
.addPass(createCGSCCToFunctionPassAdaptor(
1268 RequireTestIndirectFunctionAnalysisPass()));
1270 // Create a second CGSCC pass manager. This will cause the module-level
1271 // invalidation to occur, which will force yet another invalidation of the
1272 // indirect SCC-level analysis as the module analysis it depends on gets
1274 CGSCCPassManager CGPM4
;
1275 CGPM4
.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1276 CGPM4
.addPass(createCGSCCToFunctionPassAdaptor(
1277 RequireTestIndirectFunctionAnalysisPass()));
1279 // Add a requires pass to populate the module analysis and then one of our
1280 // CGSCC pipelines. Repeat for all four CGSCC pipelines.
1281 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1282 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1283 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1284 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2
)));
1285 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1286 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3
)));
1287 MPM
.addPass(RequireAnalysisPass
<TestModuleAnalysis
, Module
>());
1288 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4
)));
1291 // We run over four SCCs the first time. But then we split an SCC into three.
1292 // And then we merge those three back into one. However, this also
1293 // invalidates all three SCCs further down in the PO walk.
1294 EXPECT_EQ(4 + 3 + 3, SCCAnalysisRuns
);
1295 // The module analysis pass should be run three times.
1296 EXPECT_EQ(3, ModuleAnalysisRuns
);
1297 // We run over four SCCs the first time. Then over the two new ones. Then the
1298 // entire module is invalidated causing a full run over all seven. Then we
1299 // fold three SCCs back to one, re-compute for it and the two SCCs above it
1300 // in the graph, and then run over the whole module again.
1301 EXPECT_EQ(4 + 2 + 7 + 3 + 4, IndirectSCCAnalysisRuns
);
1302 EXPECT_EQ(4 + 2 + 7 + 3 + 4, DoublyIndirectSCCAnalysisRuns
);
1304 // First we run over all six functions. Then we re-run it over three when we
1305 // split their SCCs. Then we re-run over the whole module. Then we re-run
1306 // over three functions merged back into a single SCC, then those three
1307 // functions again, the two functions in SCCs above it in the graph, and then
1308 // over the whole module again.
1309 EXPECT_EQ(6 + 3 + 6 + 3 + 2 + 6, FunctionAnalysisRuns
);
1311 // Re run the function analysis over the entire module, and then re-run it
1312 // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over
1313 // the entire module, then the three functions merged back into a single SCC,
1314 // those three functions again, then the two functions in SCCs above it in
1315 // the graph, and then over the whole module.
1316 EXPECT_EQ(6 + 3 + 6 + 3 + 2 + 6, IndirectFunctionAnalysisRuns
);
1319 // The (negative) tests below check for assertions so we only run them if NDEBUG
1323 struct LambdaSCCPassNoPreserve
: public PassInfoMixin
<LambdaSCCPassNoPreserve
> {
1324 template <typename T
>
1325 LambdaSCCPassNoPreserve(T
&&Arg
) : Func(std::forward
<T
>(Arg
)) {}
1327 PreservedAnalyses
run(LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
1328 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
1329 Func(C
, AM
, CG
, UR
);
1330 PreservedAnalyses PA
;
1331 // We update the core CGSCC data structures and so can preserve the proxy to
1332 // the function analysis manager.
1333 PA
.preserve
<FunctionAnalysisManagerCGSCCProxy
>();
1337 std::function
<void(LazyCallGraph::SCC
&, CGSCCAnalysisManager
&,
1338 LazyCallGraph
&, CGSCCUpdateResult
&)>
1342 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses0
) {
1343 CGSCCPassManager CGPM
;
1344 CGPM
.addPass(LambdaSCCPassNoPreserve(
1345 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1346 CGSCCUpdateResult
&UR
) {
1347 if (C
.getName() != "(h3, h1, h2)")
1351 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1352 Function
*FnX
= M
->getFunction("x");
1353 Function
*FnH1
= M
->getFunction("h1");
1354 Function
*FnH2
= M
->getFunction("h2");
1355 Function
*FnH3
= M
->getFunction("h3");
1356 ASSERT_NE(FnX
, nullptr);
1357 ASSERT_NE(FnH1
, nullptr);
1358 ASSERT_NE(FnH2
, nullptr);
1359 ASSERT_NE(FnH3
, nullptr);
1361 // And insert a call to `h1`, `h2`, and `h3`.
1362 BasicBlock::iterator IP
= FnH2
->getEntryBlock().begin();
1363 (void)CallInst::Create(FnH1
, {}, "", IP
);
1364 (void)CallInst::Create(FnH2
, {}, "", IP
);
1365 (void)CallInst::Create(FnH3
, {}, "", IP
);
1367 auto &H2N
= *llvm::find_if(
1368 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "h2"; });
1369 ASSERT_NO_FATAL_FAILURE(
1370 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, H2N
, AM
, UR
, FAM
));
1373 ModulePassManager MPM
;
1374 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1378 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses1
) {
1379 CGSCCPassManager CGPM
;
1380 CGPM
.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC
&C
,
1381 CGSCCAnalysisManager
&AM
,
1383 CGSCCUpdateResult
&UR
) {
1384 if (C
.getName() != "(h3, h1, h2)")
1388 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1389 Function
*FnX
= M
->getFunction("x");
1390 Function
*FnH1
= M
->getFunction("h1");
1391 Function
*FnH2
= M
->getFunction("h2");
1392 Function
*FnH3
= M
->getFunction("h3");
1393 ASSERT_NE(FnX
, nullptr);
1394 ASSERT_NE(FnH1
, nullptr);
1395 ASSERT_NE(FnH2
, nullptr);
1396 ASSERT_NE(FnH3
, nullptr);
1398 // And insert a call to `h1`, `h2`, and `h3`.
1399 BasicBlock::iterator IP
= FnH2
->getEntryBlock().begin();
1400 (void)CallInst::Create(FnH1
, {}, "", IP
);
1401 (void)CallInst::Create(FnH2
, {}, "", IP
);
1402 (void)CallInst::Create(FnH3
, {}, "", IP
);
1404 auto &H2N
= *llvm::find_if(
1405 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "h2"; });
1407 updateCGAndAnalysisManagerForFunctionPass(CG
, C
, H2N
, AM
, UR
, FAM
),
1408 "Any new calls should be modeled as");
1411 ModulePassManager MPM
;
1412 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1416 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses2
) {
1417 CGSCCPassManager CGPM
;
1418 CGPM
.addPass(LambdaSCCPassNoPreserve(
1419 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1420 CGSCCUpdateResult
&UR
) {
1421 if (C
.getName() != "(f)")
1425 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1426 Function
*FnF
= M
->getFunction("f");
1427 Function
*FnH2
= M
->getFunction("h2");
1428 ASSERT_NE(FnF
, nullptr);
1429 ASSERT_NE(FnH2
, nullptr);
1431 // And insert a call to `h2`
1432 BasicBlock::iterator IP
= FnF
->getEntryBlock().begin();
1433 (void)CallInst::Create(FnH2
, {}, "", IP
);
1435 auto &FN
= *llvm::find_if(
1436 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "f"; });
1437 ASSERT_NO_FATAL_FAILURE(
1438 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, FN
, AM
, UR
, FAM
));
1441 ModulePassManager MPM
;
1442 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1446 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses3
) {
1447 CGSCCPassManager CGPM
;
1448 CGPM
.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC
&C
,
1449 CGSCCAnalysisManager
&AM
,
1451 CGSCCUpdateResult
&UR
) {
1452 if (C
.getName() != "(f)")
1456 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1457 Function
*FnF
= M
->getFunction("f");
1458 Function
*FnH2
= M
->getFunction("h2");
1459 ASSERT_NE(FnF
, nullptr);
1460 ASSERT_NE(FnH2
, nullptr);
1462 // And insert a call to `h2`
1463 BasicBlock::iterator IP
= FnF
->getEntryBlock().begin();
1464 (void)CallInst::Create(FnH2
, {}, "", IP
);
1466 auto &FN
= *llvm::find_if(
1467 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "f"; });
1469 updateCGAndAnalysisManagerForFunctionPass(CG
, C
, FN
, AM
, UR
, FAM
),
1470 "Any new calls should be modeled as");
1473 ModulePassManager MPM
;
1474 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1478 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses4
) {
1479 CGSCCPassManager CGPM
;
1480 CGPM
.addPass(LambdaSCCPassNoPreserve(
1481 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1482 CGSCCUpdateResult
&UR
) {
1483 if (C
.getName() != "(f)")
1487 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1488 Function
*FnF
= M
->getFunction("f");
1489 Function
*FnewF
= Function::Create(FnF
->getFunctionType(),
1490 FnF
->getLinkage(), "newF", *M
);
1491 BasicBlock
*BB
= BasicBlock::Create(FnewF
->getContext(), "", FnewF
);
1492 ReturnInst::Create(FnewF
->getContext(), BB
);
1494 // And insert a call to `newF`
1495 BasicBlock::iterator IP
= FnF
->getEntryBlock().begin();
1496 (void)CallInst::Create(FnewF
, {}, "", IP
);
1498 // Use the CallGraphUpdater to update the call graph for the new
1500 CallGraphUpdater CGU
;
1501 CGU
.initialize(CG
, C
, AM
, UR
);
1502 CGU
.registerOutlinedFunction(*FnF
, *FnewF
);
1504 auto &FN
= *llvm::find_if(
1505 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "f"; });
1507 ASSERT_NO_FATAL_FAILURE(
1508 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, FN
, AM
, UR
, FAM
));
1511 ModulePassManager MPM
;
1512 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1516 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses5
) {
1517 CGSCCPassManager CGPM
;
1518 CGPM
.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC
&C
,
1519 CGSCCAnalysisManager
&AM
,
1521 CGSCCUpdateResult
&UR
) {
1522 if (C
.getName() != "(f)")
1526 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1527 Function
*FnF
= M
->getFunction("f");
1529 Function::Create(FnF
->getFunctionType(), FnF
->getLinkage(), "newF", *M
);
1530 BasicBlock
*BB
= BasicBlock::Create(FnewF
->getContext(), "", FnewF
);
1531 ReturnInst::Create(FnewF
->getContext(), BB
);
1533 // Use the CallGraphUpdater to update the call graph for the new
1535 CallGraphUpdater CGU
;
1536 CGU
.initialize(CG
, C
, AM
, UR
);
1538 // And insert a call to `newF`
1539 BasicBlock::iterator IP
= FnF
->getEntryBlock().begin();
1540 (void)CallInst::Create(FnewF
, {}, "", IP
);
1542 auto &FN
= *llvm::find_if(
1543 C
, [](LazyCallGraph::Node
&N
) { return N
.getName() == "f"; });
1545 ASSERT_DEATH(updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, FN
, AM
, UR
, FAM
),
1546 "should already have an associated node");
1549 ModulePassManager MPM
;
1550 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1554 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses6
) {
1555 CGSCCPassManager CGPM
;
1556 CGPM
.addPass(LambdaSCCPassNoPreserve(
1557 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1558 CGSCCUpdateResult
&UR
) {
1559 if (C
.getName() != "(h3, h1, h2)")
1562 Function
*FnX
= M
->getFunction("x");
1563 Function
*FnH1
= M
->getFunction("h1");
1564 Function
*FnH2
= M
->getFunction("h2");
1565 Function
*FnH3
= M
->getFunction("h3");
1566 ASSERT_NE(FnX
, nullptr);
1567 ASSERT_NE(FnH1
, nullptr);
1568 ASSERT_NE(FnH2
, nullptr);
1569 ASSERT_NE(FnH3
, nullptr);
1571 // And insert a call to `h1`, `h2`, and `h3`.
1572 BasicBlock::iterator IP
= FnH2
->getEntryBlock().begin();
1573 (void)CallInst::Create(FnH1
, {}, "", IP
);
1574 (void)CallInst::Create(FnH2
, {}, "", IP
);
1575 (void)CallInst::Create(FnH3
, {}, "", IP
);
1577 // Use the CallGraphUpdater to update the call graph for the new
1579 CallGraphUpdater CGU
;
1580 CGU
.initialize(CG
, C
, AM
, UR
);
1581 ASSERT_NO_FATAL_FAILURE(CGU
.reanalyzeFunction(*FnH2
));
1584 ModulePassManager MPM
;
1585 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1589 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses7
) {
1590 CGSCCPassManager CGPM
;
1591 CGPM
.addPass(LambdaSCCPassNoPreserve(
1592 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1593 CGSCCUpdateResult
&UR
) {
1594 if (C
.getName() != "(f)")
1597 Function
*FnF
= M
->getFunction("f");
1598 Function
*FnH2
= M
->getFunction("h2");
1599 ASSERT_NE(FnF
, nullptr);
1600 ASSERT_NE(FnH2
, nullptr);
1602 // And insert a call to `h2`
1603 BasicBlock::iterator IP
= FnF
->getEntryBlock().begin();
1604 (void)CallInst::Create(FnH2
, {}, "", IP
);
1606 // Use the CallGraphUpdater to update the call graph for the new
1608 CallGraphUpdater CGU
;
1609 CGU
.initialize(CG
, C
, AM
, UR
);
1610 ASSERT_NO_FATAL_FAILURE(CGU
.reanalyzeFunction(*FnF
));
1613 ModulePassManager MPM
;
1614 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1618 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses8
) {
1619 CGSCCPassManager CGPM
;
1620 CGPM
.addPass(LambdaSCCPassNoPreserve(
1621 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1622 CGSCCUpdateResult
&UR
) {
1623 if (C
.getName() != "(f)")
1626 Function
*FnF
= M
->getFunction("f");
1627 Function
*FnewF
= Function::Create(FnF
->getFunctionType(),
1628 FnF
->getLinkage(), "newF", *M
);
1629 BasicBlock
*BB
= BasicBlock::Create(FnewF
->getContext(), "", FnewF
);
1630 auto *RI
= ReturnInst::Create(FnewF
->getContext(), BB
);
1631 while (FnF
->getEntryBlock().size() > 1)
1632 FnF
->getEntryBlock().front().moveBefore(RI
);
1633 ASSERT_NE(FnF
, nullptr);
1635 // Create an unused constant that is referencing the old (=replaced)
1637 ConstantExpr::getPtrToInt(FnF
, Type::getInt64Ty(FnF
->getContext()));
1639 // Use the CallGraphUpdater to update the call graph.
1640 CallGraphUpdater CGU
;
1641 CGU
.initialize(CG
, C
, AM
, UR
);
1642 ASSERT_NO_FATAL_FAILURE(CGU
.replaceFunctionWith(*FnF
, *FnewF
));
1643 ASSERT_TRUE(FnF
->isDeclaration());
1644 ASSERT_EQ(FnF
->getNumUses(), 0U);
1647 ModulePassManager MPM
;
1648 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1652 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses9
) {
1653 CGSCCPassManager CGPM
;
1654 CGPM
.addPass(LambdaSCCPassNoPreserve(
1655 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1656 CGSCCUpdateResult
&UR
) {
1657 if (C
.getName() != "(f)")
1660 Function
*FnF
= M
->getFunction("f");
1662 // 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);
1669 ModulePassManager MPM
;
1670 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1672 ASSERT_EQ(M
->getFunctionList().size(), 5U);
1675 TEST_F(CGSCCPassManagerTest
, TestUpdateCGAndAnalysisManagerForPasses10
) {
1676 CGSCCPassManager CGPM
;
1677 CGPM
.addPass(LambdaSCCPassNoPreserve(
1678 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1679 CGSCCUpdateResult
&UR
) {
1680 if (C
.getName() != "(h3, h1, h2)")
1683 Function
*FnX
= M
->getFunction("x");
1684 Function
*FnH1
= M
->getFunction("h1");
1685 Function
*FnH2
= M
->getFunction("h2");
1686 Function
*FnH3
= M
->getFunction("h3");
1687 ASSERT_NE(FnX
, nullptr);
1688 ASSERT_NE(FnH1
, nullptr);
1689 ASSERT_NE(FnH2
, nullptr);
1690 ASSERT_NE(FnH3
, nullptr);
1692 // And insert a call to `h1`, and `h3`.
1693 BasicBlock::iterator IP
= FnH1
->getEntryBlock().begin();
1694 (void)CallInst::Create(FnH1
, {}, "", IP
);
1695 (void)CallInst::Create(FnH3
, {}, "", IP
);
1697 // Remove the `h2` call.
1698 ASSERT_TRUE(isa
<CallBase
>(IP
));
1699 ASSERT_EQ(cast
<CallBase
>(IP
)->getCalledFunction(), FnH2
);
1700 IP
->eraseFromParent();
1702 // Use the CallGraphUpdater to update the call graph.
1703 CallGraphUpdater CGU
;
1704 CGU
.initialize(CG
, C
, AM
, UR
);
1705 ASSERT_NO_FATAL_FAILURE(CGU
.reanalyzeFunction(*FnH1
));
1706 ASSERT_NO_FATAL_FAILURE(CGU
.removeFunction(*FnH2
));
1709 ModulePassManager MPM
;
1710 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1714 // Returns a vector containing the SCC's nodes. Useful for not iterating over an
1715 // SCC while mutating it.
1716 static SmallVector
<LazyCallGraph::Node
*> SCCNodes(LazyCallGraph::SCC
&C
) {
1717 SmallVector
<LazyCallGraph::Node
*> Nodes
;
1719 Nodes
.push_back(&N
);
1724 // Start with call recursive f, create f -> g and ref recursive f.
1725 TEST_F(CGSCCPassManagerTest
, TestInsertionOfNewFunctions1
) {
1726 std::unique_ptr
<Module
> M
= parseIR("define void @f() {\n"
1734 CGSCCPassManager CGPM
;
1735 CGPM
.addPass(LambdaSCCPassNoPreserve(
1736 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1737 CGSCCUpdateResult
&UR
) {
1742 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1744 for (LazyCallGraph::Node
*N
: SCCNodes(C
)) {
1745 Function
&F
= N
->getFunction();
1746 if (F
.getName() != "f")
1749 // Create a new function 'g'.
1750 auto *G
= Function::Create(F
.getFunctionType(), F
.getLinkage(),
1751 F
.getAddressSpace(), "g", F
.getParent());
1753 BasicBlock::Create(F
.getParent()->getContext(), "entry", G
);
1754 (void)ReturnInst::Create(G
->getContext(), GBB
);
1755 // Instruct the LazyCallGraph to create a new node for 'g', as the
1756 // single node in a new SCC, into the call graph. As a result
1757 // the call graph is composed of a single RefSCC with two SCCs:
1760 // "Demote" the 'f -> f' call edge to a ref edge.
1761 // 1. Erase the call edge from 'f' to 'f'.
1762 F
.getEntryBlock().front().eraseFromParent();
1763 // 2. Insert a ref edge from 'f' to 'f'.
1764 (void)CastInst::CreatePointerCast(
1765 &F
, PointerType::getUnqual(F
.getContext()), "f.ref",
1766 F
.getEntryBlock().begin());
1767 // 3. Insert a ref edge from 'f' to 'g'.
1768 (void)CastInst::CreatePointerCast(
1769 G
, PointerType::getUnqual(F
.getContext()), "g.ref",
1770 F
.getEntryBlock().begin());
1772 CG
.addSplitFunction(F
, *G
);
1774 ASSERT_FALSE(verifyModule(*F
.getParent(), &errs()));
1776 ASSERT_NO_FATAL_FAILURE(
1777 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, *N
, AM
, UR
, FAM
))
1778 << "Updating the call graph with a demoted, self-referential "
1779 "call edge 'f -> f', and a newly inserted ref edge 'f -> g', "
1780 "caused a fatal failure";
1786 ModulePassManager MPM
;
1787 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1792 // Start with f, end with f -> g1, f -> g2, and f -ref-> (h1 <-ref-> h2).
1793 TEST_F(CGSCCPassManagerTest
, TestInsertionOfNewFunctions2
) {
1794 std::unique_ptr
<Module
> M
= parseIR("define void @f() {\n"
1801 CGSCCPassManager CGPM
;
1802 CGPM
.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC
&C
,
1803 CGSCCAnalysisManager
&AM
,
1805 CGSCCUpdateResult
&UR
) {
1810 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1812 for (LazyCallGraph::Node
*N
: SCCNodes(C
)) {
1813 Function
&F
= N
->getFunction();
1814 if (F
.getName() != "f")
1817 // Create g1 and g2.
1818 auto *G1
= Function::Create(F
.getFunctionType(), F
.getLinkage(),
1819 F
.getAddressSpace(), "g1", F
.getParent());
1820 auto *G2
= Function::Create(F
.getFunctionType(), F
.getLinkage(),
1821 F
.getAddressSpace(), "g2", F
.getParent());
1823 BasicBlock::Create(F
.getParent()->getContext(), "entry", G1
);
1825 BasicBlock::Create(F
.getParent()->getContext(), "entry", G2
);
1826 (void)ReturnInst::Create(G1
->getContext(), G1BB
);
1827 (void)ReturnInst::Create(G2
->getContext(), G2BB
);
1829 // Add 'f -> g1' call edge.
1830 (void)CallInst::Create(G1
, {}, "", F
.getEntryBlock().begin());
1831 // Add 'f -> g2' call edge.
1832 (void)CallInst::Create(G2
, {}, "", F
.getEntryBlock().begin());
1834 CG
.addSplitFunction(F
, *G1
);
1835 CG
.addSplitFunction(F
, *G2
);
1837 // Create mutually recursive functions (ref only) 'h1' and 'h2'.
1838 auto *H1
= Function::Create(F
.getFunctionType(), F
.getLinkage(),
1839 F
.getAddressSpace(), "h1", F
.getParent());
1840 auto *H2
= Function::Create(F
.getFunctionType(), F
.getLinkage(),
1841 F
.getAddressSpace(), "h2", F
.getParent());
1843 BasicBlock::Create(F
.getParent()->getContext(), "entry", H1
);
1845 BasicBlock::Create(F
.getParent()->getContext(), "entry", H2
);
1846 (void)CastInst::CreatePointerCast(
1847 H2
, PointerType::getUnqual(F
.getContext()), "h2.ref", H1BB
);
1848 (void)ReturnInst::Create(H1
->getContext(), H1BB
);
1849 (void)CastInst::CreatePointerCast(
1850 H1
, PointerType::getUnqual(F
.getContext()), "h1.ref", H2BB
);
1851 (void)ReturnInst::Create(H2
->getContext(), H2BB
);
1853 // Add 'f -> h1' ref edge.
1854 (void)CastInst::CreatePointerCast(H1
,
1855 PointerType::getUnqual(F
.getContext()),
1856 "h1.ref", F
.getEntryBlock().begin());
1857 // Add 'f -> h2' ref edge.
1858 (void)CastInst::CreatePointerCast(H2
,
1859 PointerType::getUnqual(F
.getContext()),
1860 "h2.ref", F
.getEntryBlock().begin());
1862 CG
.addSplitRefRecursiveFunctions(F
, SmallVector
<Function
*, 2>({H1
, H2
}));
1864 ASSERT_FALSE(verifyModule(*F
.getParent(), &errs()));
1866 ASSERT_NO_FATAL_FAILURE(
1867 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, *N
, AM
, UR
, FAM
))
1868 << "Updating the call graph with mutually recursive g1 <-> g2, h1 "
1869 "<-> h2 caused a fatal failure";
1875 ModulePassManager MPM
;
1876 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1881 TEST_F(CGSCCPassManagerTest
, TestDeletionOfFunctionInNonTrivialRefSCC
) {
1882 std::unique_ptr
<Module
> M
= parseIR("define void @f1() {\n"
1884 " call void @f2()\n"
1887 "define void @f2() {\n"
1889 " call void @f1()\n"
1894 CGSCCPassManager CGPM
;
1895 CGPM
.addPass(LambdaSCCPassNoPreserve(
1896 [&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
, LazyCallGraph
&CG
,
1897 CGSCCUpdateResult
&UR
) {
1901 LazyCallGraph::Node
*N1
= nullptr;
1903 for (LazyCallGraph::Node
*N
: SCCNodes(C
)) {
1904 Function
&F
= N
->getFunction();
1905 if (F
.getName() != "f1")
1909 Function
&F2
= *F
.getParent()->getFunction("f2");
1911 // Remove f1 <-> f2 references
1912 F
.getEntryBlock().front().eraseFromParent();
1913 F2
.getEntryBlock().front().eraseFromParent();
1915 CallGraphUpdater CGU
;
1916 CGU
.initialize(CG
, C
, AM
, UR
);
1917 CGU
.removeFunction(F2
);
1918 CGU
.reanalyzeFunction(F
);
1923 // Check that updateCGAndAnalysisManagerForCGSCCPass() after
1924 // CallGraphUpdater::removeFunction() succeeds.
1925 updateCGAndAnalysisManagerForCGSCCPass(CG
, *CG
.lookupSCC(*N1
), *N1
, AM
,
1929 ModulePassManager MPM
;
1930 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
1936 TEST_F(CGSCCPassManagerTest
, TestInsertionOfNewNonTrivialCallEdge
) {
1937 std::unique_ptr
<Module
> M
= parseIR("define void @f1() {\n"
1939 " %a = bitcast void ()* @f4 to i8*\n"
1940 " %b = bitcast void ()* @f2 to i8*\n"
1943 "define void @f2() {\n"
1945 " %a = bitcast void ()* @f1 to i8*\n"
1946 " %b = bitcast void ()* @f3 to i8*\n"
1949 "define void @f3() {\n"
1951 " %a = bitcast void ()* @f2 to i8*\n"
1952 " %b = bitcast void ()* @f4 to i8*\n"
1955 "define void @f4() {\n"
1957 " %a = bitcast void ()* @f3 to i8*\n"
1958 " %b = bitcast void ()* @f1 to i8*\n"
1963 CGSCCPassManager CGPM
;
1964 CGPM
.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC
&C
,
1965 CGSCCAnalysisManager
&AM
,
1967 CGSCCUpdateResult
&UR
) {
1972 AM
.getResult
<FunctionAnalysisManagerCGSCCProxy
>(C
, CG
).getManager();
1974 for (LazyCallGraph::Node
*N
: SCCNodes(C
)) {
1975 Function
&F
= N
->getFunction();
1976 if (F
.getName() != "f1")
1979 Function
*F3
= F
.getParent()->getFunction("f3");
1980 ASSERT_TRUE(F3
!= nullptr);
1982 // Create call from f1 to f3.
1983 (void)CallInst::Create(F3
, {}, "",
1984 F
.getEntryBlock().getTerminator()->getIterator());
1986 ASSERT_NO_FATAL_FAILURE(
1987 updateCGAndAnalysisManagerForCGSCCPass(CG
, C
, *N
, AM
, UR
, FAM
))
1988 << "Updating the call graph with mutually recursive g1 <-> g2, h1 "
1989 "<-> h2 caused a fatal failure";
1995 ModulePassManager MPM
;
1996 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
2002 TEST_F(CGSCCPassManagerTest
, TestFunctionPassesAreQueriedForInvalidation
) {
2003 std::unique_ptr
<Module
> M
= parseIR("define void @f() { ret void }");
2004 CGSCCPassManager CGPM
;
2005 bool SCCCalled
= false;
2006 FunctionPassManager FPM
;
2008 FAM
.registerPass([&] { return TestImmutableFunctionAnalysis(ImmRuns
); });
2009 FPM
.addPass(RequireAnalysisPass
<TestImmutableFunctionAnalysis
, Function
>());
2011 LambdaSCCPass([&](LazyCallGraph::SCC
&C
, CGSCCAnalysisManager
&AM
,
2012 LazyCallGraph
&CG
, CGSCCUpdateResult
&UR
) {
2014 return PreservedAnalyses::none();
2016 CGPM
.addPass(createCGSCCToFunctionPassAdaptor(
2017 RequireAnalysisPass
<TestImmutableFunctionAnalysis
, Function
>()));
2018 ModulePassManager MPM
;
2020 MPM
.addPass(createModuleToFunctionPassAdaptor(std::move(FPM
)));
2021 MPM
.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM
)));
2023 ASSERT_EQ(ImmRuns
, 1);
2024 ASSERT_TRUE(SCCCalled
);