34#define DEBUG_TYPE "cgscc"
38STATISTIC(LargestCGSCC,
"Number of functions in the largest SCC");
44 "abort-on-max-devirt-iterations-reached",
45 cl::desc(
"Abort when the max iterations for devirtualization CGSCC repeat "
92 LargestCGSCC.updateMax(
C->size());
102 ResultFAMCP->updateFAM(
FAM);
107 PA.intersect(PassPA);
113 LLVM_DEBUG(
dbgs() <<
"Skipping invalidated root or island SCC!\n");
118 assert(
C->begin() !=
C->end() &&
"Cannot have an empty SCC!");
165 InlinedInternalEdges;
173 InlinedInternalEdges,
186 "Should always start with an empty RefSCC worklist");
203 "Should always start with an empty SCC worklist");
205 LLVM_DEBUG(
dbgs() <<
"Running an SCC pass across the RefSCC: " << *RC
225 if (InvalidSCCSet.
count(
C)) {
229 if (LastUpdatedC ==
C) {
269 assert(!InvalidSCCSet.
count(
C) &&
"Processing an invalid SCC!");
270 assert(
C->begin() !=
C->end() &&
"Cannot have an empty SCC!");
298 PA.intersect(PassPA);
304 LLVM_DEBUG(
dbgs() <<
"Skipping invalidated root or island SCC!\n");
309 assert(
C->begin() !=
C->end() &&
"Cannot have an empty SCC!");
332 <<
"Re-running SCC passes after a refinement of the "
340 }
while (!CWorklist.
empty());
345 InlinedInternalEdges.
clear();
346 }
while (!RCWorklist.
empty());
350 for (
Function *DeadF : DeadFunctions)
351 DeadF->eraseFromParent();
353#if defined(EXPENSIVE_CHECKS)
390 assert(CallHandles.empty() &&
"Must start with a clear set of handles.");
393 CallCount CountLocal = {0, 0};
396 CallCounts.
insert(std::make_pair(&
N.getFunction(), CountLocal))
399 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
400 if (CB->getCalledFunction()) {
416 for (
int Iteration = 0;; ++Iteration) {
428 LLVM_DEBUG(
dbgs() <<
"Skipping invalidated root or island SCC!\n");
443 assert(
C->begin() !=
C->end() &&
"Cannot have an empty SCC!");
448 if (CallBase *CB = dyn_cast<CallBase>(P.second)) {
449 if (CB->getCalledFunction()) {
450 LLVM_DEBUG(dbgs() <<
"Found devirtualized call: " << *CB <<
"\n");
472 for (
auto &Pair : NewCallCounts) {
473 auto &CallCountNew = Pair.second;
474 auto CountIt = CallCounts.find(Pair.first);
475 if (CountIt != CallCounts.end()) {
476 const auto &CallCountOld = CountIt->second;
477 if (CallCountOld.Indirect > CallCountNew.Indirect &&
478 CallCountOld.Direct < CallCountNew.Direct) {
490 if (Iteration >= MaxIterations) {
494 dbgs() <<
"Found another devirtualization after hitting the max "
495 "number of repetitions ("
496 << MaxIterations <<
") on SCC: " << *
C <<
"\n");
501 dbgs() <<
"Repeating an SCC pass after finding a devirtualization in: "
505 CallCounts = std::move(NewCallCounts);
529 LLVM_DEBUG(
dbgs() <<
"Running function passes across an SCC: " <<
C <<
"\n");
569 "Current SCC not updated to the SCC containing the current node!");
586bool CGSCCAnalysisManagerModuleProxy::Result::invalidate(
615 bool AreSCCAnalysesPreserved =
620 for (
auto &RC :
G->postorder_ref_sccs())
622 std::optional<PreservedAnalyses> InnerPA;
627 if (
auto *OuterProxy =
629 for (
const auto &OuterInvalidationPair :
630 OuterProxy->getOuterInvalidations()) {
631 AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;
632 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
636 for (
AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
637 InnerPA->
abandon(InnerAnalysisID);
644 InnerAM->invalidate(
C, *InnerPA);
650 if (!AreSCCAnalysesPreserved)
651 InnerAM->invalidate(
C, PA);
680 Module &M = *
C.begin()->getFunction().getParent();
684 "The CGSCC pass manager requires that the FAM module proxy is run "
685 "on the module prior to entering the CGSCC walk");
718 bool AreFunctionAnalysesPreserved =
725 std::optional<PreservedAnalyses> FunctionPA;
730 if (
auto *OuterProxy =
732 for (
const auto &OuterInvalidationPair :
733 OuterProxy->getOuterInvalidations()) {
734 AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;
735 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
739 for (
AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
740 FunctionPA->
abandon(InnerAnalysisID);
753 if (!AreFunctionAnalysesPreserved)
796 for (
const auto &OuterInvalidationPair :
797 OuterProxy->getOuterInvalidations()) {
798 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
799 for (
AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
800 PA.abandon(InnerAnalysisID);
818template <
typename SCCRangeT>
825 if (NewSCCRange.empty())
830 LLVM_DEBUG(
dbgs() <<
"Enqueuing the existing SCC in the worklist:" << *
C
837 assert(
C != &*NewSCCRange.begin() &&
838 "Cannot insert new SCCs without changing current SCC!");
839 C = &*NewSCCRange.begin();
840 assert(
G.lookupSCC(
N) ==
C &&
"Failed to update current SCC!");
847 FAM = &FAMProxy->getManager();
856 auto PA = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();
865 assert(
C != &NewC &&
"No need to re-visit the current SCC!");
866 assert(OldC != &NewC &&
"Already handled the original SCC!");
868 LLVM_DEBUG(
dbgs() <<
"Enqueuing a newly formed SCC:" << NewC <<
"\n");
892 RefSCC *RC = &InitialRC;
909 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
910 if (
Function *Callee = CB->getCalledFunction()) {
911 if (Visited.
insert(Callee).second && !Callee->isDeclaration()) {
912 Node *CalleeN =
G.lookup(*Callee);
914 "Visited function should already have an associated node");
915 Edge *E =
N->lookup(*CalleeN);
917 "No function transformations should introduce *new* "
918 "call edges! Any new calls should be modeled as "
919 "promoted existing ref edges!");
920 bool Inserted = RetainedEdges.
insert(CalleeN).second;
922 assert(Inserted &&
"We should never visit a function twice.");
924 NewCallEdges.
insert(CalleeN);
925 else if (!E->isCall())
926 PromotedRefTargets.
insert(CalleeN);
934 else if (!Entry->second)
942 for (
Value *
Op :
I.operand_values())
943 if (
auto *OpC = dyn_cast<Constant>(
Op))
944 if (Visited.
insert(OpC).second)
947 auto VisitRef = [&](
Function &Referee) {
948 Node *RefereeN =
G.lookup(Referee);
950 "Visited function should already have an associated node");
951 Edge *E =
N->lookup(*RefereeN);
953 "No function transformations should introduce *new* ref "
954 "edges! Any new ref edges would require IPO which "
955 "function passes aren't allowed to do!");
956 bool Inserted = RetainedEdges.
insert(RefereeN).second;
958 assert(Inserted &&
"We should never visit a function twice.");
960 NewRefEdges.
insert(RefereeN);
961 else if (E->isCall())
962 DemotedCallTargets.
insert(RefereeN);
967 for (
Node *RefTarget : NewRefEdges) {
968 SCC &TargetC = *
G.lookupSCC(*RefTarget);
969 RefSCC &TargetRC = TargetC.getOuterRefSCC();
972#ifdef EXPENSIVE_CHECKS
973 assert((RC == &TargetRC ||
974 RC->isAncestorOf(TargetRC)) &&
"New ref edge is not trivial!");
976 RC->insertTrivialRefEdge(
N, *RefTarget);
980 for (
Node *CallTarget : NewCallEdges) {
981 SCC &TargetC = *
G.lookupSCC(*CallTarget);
982 RefSCC &TargetRC = TargetC.getOuterRefSCC();
985#ifdef EXPENSIVE_CHECKS
986 assert((RC == &TargetRC ||
987 RC->isAncestorOf(TargetRC)) &&
"New call edge is not trivial!");
991 RC->insertTrivialRefEdge(
N, *CallTarget);
995 for (
auto *LibFn :
G.getLibFunctions())
998 if (!Visited.
count(LibFn))
1005 for (
Edge &E : *
N) {
1006 if (RetainedEdges.
count(&E.getNode()))
1009 SCC &TargetC = *
G.lookupSCC(E.getNode());
1010 RefSCC &TargetRC = TargetC.getOuterRefSCC();
1011 if (&TargetRC == RC && E.isCall()) {
1012 if (
C != &TargetC) {
1014 RC->switchTrivialInternalEdgeToRef(
N, E.getNode());
1027 SCC &TargetC = *
G.lookupSCC(*TargetN);
1028 RefSCC &TargetRC = TargetC.getOuterRefSCC();
1032 if (&TargetRC == RC)
1036 << *TargetN <<
"'\n");
1037 RC->removeOutgoingEdge(
N, *TargetN);
1044 for (
Node *RefTarget : DemotedCallTargets) {
1045 SCC &TargetC = *
G.lookupSCC(*RefTarget);
1046 RefSCC &TargetRC = TargetC.getOuterRefSCC();
1050 if (&TargetRC != RC) {
1051#ifdef EXPENSIVE_CHECKS
1052 assert(RC->isAncestorOf(TargetRC) &&
1053 "Cannot potentially form RefSCC cycles here!");
1055 RC->switchOutgoingEdgeToRef(
N, *RefTarget);
1056 LLVM_DEBUG(
dbgs() <<
"Switch outgoing call edge to a ref edge from '" <<
N
1057 <<
"' to '" << *RefTarget <<
"'\n");
1063 if (
C != &TargetC) {
1065 RC->switchTrivialInternalEdgeToRef(
N, *RefTarget);
1079 for (
Node *CallTarget : PromotedRefTargets) {
1080 SCC &TargetC = *
G.lookupSCC(*CallTarget);
1081 RefSCC &TargetRC = TargetC.getOuterRefSCC();
1085 if (&TargetRC != RC) {
1086#ifdef EXPENSIVE_CHECKS
1087 assert(RC->isAncestorOf(TargetRC) &&
1088 "Cannot potentially form RefSCC cycles here!");
1090 RC->switchOutgoingEdgeToCall(
N, *CallTarget);
1091 LLVM_DEBUG(
dbgs() <<
"Switch outgoing ref edge to a call edge from '" <<
N
1092 <<
"' to '" << *CallTarget <<
"'\n");
1095 LLVM_DEBUG(
dbgs() <<
"Switch an internal ref edge to a call edge from '"
1096 <<
N <<
"' to '" << *CallTarget <<
"'\n");
1102 bool HasFunctionAnalysisProxy =
false;
1103 auto InitialSCCIndex = RC->find(*
C) - RC->begin();
1104 bool FormedCycle = RC->switchInternalEdgeToCall(
1106 for (SCC *MergedC : MergedSCCs) {
1107 assert(MergedC != &TargetC &&
"Cannot merge away the target SCC!");
1109 HasFunctionAnalysisProxy |=
1111 *MergedC) !=
nullptr;
1119 auto PA = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();
1129 assert(
G.lookupSCC(
N) ==
C &&
"Failed to update current SCC!");
1134 if (HasFunctionAnalysisProxy)
1140 auto PA = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();
1144 auto NewSCCIndex = RC->find(*
C) - RC->begin();
1153 if (InitialSCCIndex < NewSCCIndex) {
1159 LLVM_DEBUG(
dbgs() <<
"Enqueuing the existing SCC in the worklist: " << *
C
1163 RC->begin() + NewSCCIndex))) {
1165 LLVM_DEBUG(
dbgs() <<
"Enqueuing a newly earlier in post-order SCC: "
1172 assert(&
C->getOuterRefSCC() == RC &&
"Current SCC not in current RefSCC!");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
static LazyCallGraph::SCC & updateCGAndAnalysisManagerForPass(LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM, bool FunctionPass)
static LazyCallGraph::SCC * incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G, LazyCallGraph::Node &N, LazyCallGraph::SCC *C, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR)
Helper function to update both the CGSCCAnalysisManager AM and the CGSCCPassManager's CGSCCUpdateResu...
static void updateNewSCCFunctionAnalyses(LazyCallGraph::SCC &C, LazyCallGraph &G, CGSCCAnalysisManager &AM, FunctionAnalysisManager &FAM)
When a new SCC is created for the graph we first update the FunctionAnalysisManager in the Proxy's re...
This header provides classes for managing passes over SCCs of the call graph.
#define LLVM_EXPORT_TEMPLATE
This header defines various interfaces for pass management in LLVM.
Implements a lazy call graph analysis and related passes for the new pass manager.
CGSCCAnalysisManager CGAM
Function const char * Passes
FunctionAnalysisManager FAM
Provides implementations for PassManager and AnalysisManager template methods.
This file provides a priority worklist.
std::pair< BasicBlock *, BasicBlock * > Edge
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This templated class represents "all analyses that operate over <a particular IR unit>" (e....
API to communicate dependencies between analyses during invalidation.
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Trigger the invalidation of some other analysis pass if not already handled and return whether it was...
A container for analyses that lazily runs them and caches their results.
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
We need a specialized result for the CGSCCAnalysisManagerModuleProxy so it can have access to the cal...
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
Runs the function pass across every function in the module.
This class represents an Operation in the Expression.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
Runs the wrapped pass up to MaxIterations on the SCC, iterating whenever an indirect call is refined.
LLVM_ABI bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA, CGSCCAnalysisManager::Invalidator &Inv)
A proxy from a FunctionAnalysisManager to an SCC.
LLVM_ABI Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &)
Computes the FunctionAnalysisManager and stores it in the result proxy.
FunctionPass class - This class is used to implement most global optimizations.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Result run(IRUnitT &IR, AnalysisManager< IRUnitT, ExtraArgTs... > &AM, ExtraArgTs...)
Run the analysis pass and create our proxy result object.
An analysis pass which computes the call graph for a module.
A class used to represent edges in the call graph.
A node in the call graph.
A RefSCC of the call graph.
An SCC of the call graph.
RefSCC & getOuterRefSCC() const
A lazily constructed view of the call graph of a module.
LLVM_ABI void buildRefSCCs()
static LLVM_ABI void visitReferences(SmallVectorImpl< Constant * > &Worklist, SmallPtrSetImpl< Constant * > &Visited, function_ref< void(Function &)> Callback)
Recursively visits the defined functions whose address is reachable from every constant in the Workli...
LLVM_ABI void removeDeadFunctions(ArrayRef< Function * > DeadFs)
Remove dead functions from the call graph.
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
iterator_range< postorder_ref_scc_iterator > postorder_ref_sccs()
void verify()
Verify that every RefSCC is valid.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Runs the CGSCC pass across every SCC in the module.
A Module instance is used to store all the information related to an LLVM module.
An analysis over an "inner" IR unit that provides access to an analysis manager over a "outer" IR uni...
Pseudo-analysis pass that exposes the PassInstrumentation to pass managers.
This class provides instrumentation entry points for the Pass Manager, doing calls to callbacks regis...
void runAfterPassInvalidated(const PassT &Pass, const PreservedAnalyses &PA) const
AfterPassInvalidated instrumentation point - takes Pass instance that has just been executed.
void runAfterPass(const PassT &Pass, const IRUnitT &IR, const PreservedAnalyses &PA) const
AfterPass instrumentation point - takes Pass instance that has just been executed and constant refere...
bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const
BeforePass instrumentation point - takes Pass instance to be executed and constant reference to IR it...
Manages a sequence of passes over a particular unit of IR.
Pass interface - Implemented by all 'passes'.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
bool areAllPreserved() const
Test whether all analyses are preserved (and none are abandoned).
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
bool allAnalysesInSetPreserved() const
Directly test whether a set of analyses is preserved.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
void intersect(const PreservedAnalyses &Arg)
Intersect this set with another in place.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
bool empty() const
Determine if the PriorityWorklist is empty or not.
bool insert(const T &X)
Insert a new element into the PriorityWorklist.
void insert_range(Range &&R)
bool insert(const value_type &X)
Insert a new element into the SetVector.
static LLVM_ABI AnalysisKey Key
Implements a dense probed hash-table based set with some number of buckets stored inline.
A version of PriorityWorklist that selects small size optimized data structures for the vector and ma...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM Value Representation.
Value handle that is nullable, but tries to track the Value.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI LazyCallGraph::SCC & updateCGAndAnalysisManagerForFunctionPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a function pass.
LLVM_ABI LazyCallGraph::SCC & updateCGAndAnalysisManagerForCGSCCPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a CGSCC pass.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
static cl::opt< bool > AbortOnMaxDevirtIterationsReached("abort-on-max-devirt-iterations-reached", cl::desc("Abort when the max iterations for devirtualization CGSCC repeat " "pass is reached"))
A special type used by analysis passes to provide an address that identifies that particular analysis...
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
SmallMapVector< Value *, WeakTrackingVH, 16 > IndirectVHs
Weak VHs to keep track of indirect calls for the purposes of detecting devirtualization.
SmallPriorityWorklist< LazyCallGraph::SCC *, 1 > & CWorklist
Worklist of the SCCs queued for processing.
SmallPtrSetImpl< LazyCallGraph::SCC * > & InvalidatedSCCs
The set of invalidated SCCs which should be skipped if they are found in CWorklist.
LazyCallGraph::SCC * UpdatedC
If non-null, the updated current SCC being processed.
PreservedAnalyses CrossSCCPA
Preserved analyses across SCCs.
A MapVector that performs no allocations if smaller than a certain size.