31 #define DEBUG_TYPE "cgscc" 46 LazyCallGraph::SCC, LazyCallGraph &>;
54 CGSCCUpdateResult &>::run(LazyCallGraph::SCC &InitialC,
55 CGSCCAnalysisManager &AM,
56 LazyCallGraph &
G, CGSCCUpdateResult &UR) {
65 dbgs() <<
"Starting CGSCC pass manager run.\n";
69 LazyCallGraph::SCC *
C = &InitialC;
71 for (
auto &
Pass : Passes) {
73 dbgs() <<
"Running pass: " <<
Pass->name() <<
" on " << *C <<
"\n";
93 LLVM_DEBUG(
dbgs() <<
"Skipping invalidated root or island SCC!\n");
105 PA.intersect(std::move(PassPA));
121 dbgs() <<
"Finished CGSCC pass manager run.\n";
155 bool AreSCCAnalysesPreserved =
160 for (
auto &RC :
G->postorder_ref_sccs())
167 if (
auto *OuterProxy =
169 for (
const auto &OuterInvalidationPair :
170 OuterProxy->getOuterInvalidations()) {
171 AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;
172 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
176 for (
AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
177 InnerPA->
abandon(InnerAnalysisID);
184 InnerAM->invalidate(
C, *InnerPA);
190 if (!AreSCCAnalysesPreserved)
191 InnerAM->invalidate(
C, PA);
210 AnalysisKey FunctionAnalysisManagerCGSCCProxy::Key;
214 CGSCCAnalysisManager &AM,
222 Module &M = *C.begin()->getFunction().getParent();
224 assert(FAMProxy &&
"The CGSCC pass manager requires that the FAM module " 225 "proxy is run on the module prior to entering the CGSCC " 232 return Result(FAMProxy->getManager());
253 FAM->clear(
N.getFunction(),
N.getFunction().getName());
259 bool AreFunctionAnalysesPreserved =
271 if (
auto *OuterProxy =
273 for (
const auto &OuterInvalidationPair :
274 OuterProxy->getOuterInvalidations()) {
275 AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;
276 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
280 for (
AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
281 FunctionPA->
abandon(InnerAnalysisID);
288 FAM->invalidate(F, *FunctionPA);
294 if (!AreFunctionAnalysesPreserved)
295 FAM->invalidate(F, PA);
337 for (
const auto &OuterInvalidationPair :
338 OuterProxy->getOuterInvalidations()) {
339 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
340 for (
AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
341 PA.abandon(InnerAnalysisID);
345 FAM.invalidate(F, PA);
359 template <
typename SCCRangeT>
366 if (NewSCCRange.begin() == NewSCCRange.end())
371 LLVM_DEBUG(
dbgs() <<
"Enqueuing the existing SCC in the worklist:" << *C
379 "Cannot insert new SCCs without changing current SCC!");
380 C = &*NewSCCRange.
begin();
404 NewSCCRange.end()))) {
405 assert(C != &NewC &&
"No need to re-visit the current SCC!");
406 assert(OldC != &NewC &&
"Already handled the original SCC!");
408 LLVM_DEBUG(
dbgs() <<
"Enqueuing a newly formed SCC:" << NewC <<
"\n");
431 RefSCC *RC = &InitialRC;
456 assert(E &&
"No function transformations should introduce *new* " 457 "call edges! Any new calls should be modeled as " 458 "promoted existing ref edges!");
459 bool Inserted = RetainedEdges.
insert(&CalleeN).second;
461 assert(Inserted &&
"We should never visit a function twice.");
463 PromotedRefTargets.
insert(&CalleeN);
468 for (
Value *
Op :
I.operand_values())
469 if (
auto *C = dyn_cast<Constant>(
Op))
470 if (Visited.
insert(C).second)
473 auto VisitRef = [&](
Function &Referee) {
474 Node &RefereeN = *G.
lookup(Referee);
478 assert(E &&
"No function transformations should introduce *new* ref " 479 "edges! Any new ref edges would require IPO which " 480 "function passes aren't allowed to do!");
481 bool Inserted = RetainedEdges.
insert(&RefereeN).second;
483 assert(Inserted &&
"We should never visit a function twice.");
485 DemotedCallTargets.
insert(&RefereeN);
493 if (!Visited.
count(F))
501 if (RetainedEdges.
count(&
E.getNode()))
506 if (&TargetRC == RC &&
E.isCall()) {
534 << N <<
"' to '" << TargetN <<
"'\n");
540 auto NewRefSCCs = RC->removeInternalRefEdge(N, DeadTargets);
541 if (!NewRefSCCs.empty()) {
551 assert(G.
lookupSCC(N) == C &&
"Changed the SCC when splitting RefSCCs!");
552 RC = &C->getOuterRefSCC();
558 assert(NewRefSCCs.front() == RC &&
559 "New current RefSCC not first in the returned list!");
561 NewRefSCCs.end()))) {
562 assert(NewRC != RC &&
"Should not encounter the current RefSCC further " 563 "in the postorder list of new RefSCCs.");
565 LLVM_DEBUG(
dbgs() <<
"Enqueuing a new RefSCC in the update worklist: " 573 for (Node *RefTarget : DemotedCallTargets) {
579 if (&TargetRC != RC) {
580 assert(RC->isAncestorOf(TargetRC) &&
581 "Cannot potentially form RefSCC cycles here!");
582 RC->switchOutgoingEdgeToRef(N, *RefTarget);
583 LLVM_DEBUG(
dbgs() <<
"Switch outgoing call edge to a ref edge from '" << N
584 <<
"' to '" << *RefTarget <<
"'\n");
592 RC->switchTrivialInternalEdgeToRef(N, *RefTarget);
602 for (Node *CallTarget : PromotedRefTargets) {
603 SCC &TargetC = *G.
lookupSCC(*CallTarget);
608 if (&TargetRC != RC) {
609 assert(RC->isAncestorOf(TargetRC) &&
610 "Cannot potentially form RefSCC cycles here!");
611 RC->switchOutgoingEdgeToCall(N, *CallTarget);
612 LLVM_DEBUG(
dbgs() <<
"Switch outgoing ref edge to a call edge from '" << N
613 <<
"' to '" << *CallTarget <<
"'\n");
616 LLVM_DEBUG(
dbgs() <<
"Switch an internal ref edge to a call edge from '" 617 << N <<
"' to '" << *CallTarget <<
"'\n");
623 bool HasFunctionAnalysisProxy =
false;
624 auto InitialSCCIndex = RC->find(*C) - RC->begin();
625 bool FormedCycle = RC->switchInternalEdgeToCall(
627 for (SCC *MergedC : MergedSCCs) {
628 assert(MergedC != &TargetC &&
"Cannot merge away the target SCC!");
630 HasFunctionAnalysisProxy |=
632 *MergedC) !=
nullptr;
640 auto PA = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();
655 if (HasFunctionAnalysisProxy)
661 auto PA = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();
665 auto NewSCCIndex = RC->find(*C) - RC->begin();
674 if (InitialSCCIndex < NewSCCIndex) {
680 LLVM_DEBUG(
dbgs() <<
"Enqueuing the existing SCC in the worklist: " << *C
684 RC->begin() + NewSCCIndex))) {
686 LLVM_DEBUG(
dbgs() <<
"Enqueuing a newly earlier in post-order SCC: " 694 assert(&C->getOuterRefSCC() == RC &&
"Current SCC not in current RefSCC!");
698 if (RC != &InitialRC)
Pass interface - Implemented by all 'passes'.
void abandon()
Mark an analysis as abandoned.
Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &)
Computes the FunctionAnalysisManager and stores it in the result proxy.
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Trigger the invalidation of some other analysis pass if not already handled and return whether it was...
void removeOutgoingEdge(Node &SourceN, Node &TargetN)
Remove an edge whose source is in this RefSCC and target is not.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents lattice values for constants.
SmallPriorityWorklist< LazyCallGraph::RefSCC *, 1 > & RCWorklist
Worklist of the RefSCCs queued for processing.
A Module instance is used to store all the information related to an LLVM module. ...
LazyCallGraph::SCC & updateCGAndAnalysisManagerForFunctionPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR)
Helper to update the call graph after running a function pass.
void push_back(const T &Elt)
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA, typename AnalysisManager< IRUnitT, ExtraArgTs... >::Invalidator &Inv)
Handler for invalidation of the outer IR unit, IRUnitT.
Implements a lazy call graph analysis and related passes for the new pass manager.
Function & getFunction() const
A proxy from a FunctionAnalysisManager to an SCC.
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
RefSCC * lookupRefSCC(Node &N) const
Lookup a function's RefSCC in the graph.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
RefSCC & getOuterRefSCC() const
LazyCallGraph::SCC * UpdatedC
If non-null, the updated current SCC being processed.
AnalysisManagerT & getManager()
Accessor for the analysis manager.
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
A RefSCC of the call graph.
bool insert(const value_type &X)
Insert a new element into the SetVector.
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
static void updateNewSCCFunctionAnalyses(LazyCallGraph::SCC &C, LazyCallGraph &G, CGSCCAnalysisManager &AM)
When a new SCC is created for the graph and there might be function analysis results cached for the f...
A lazily constructed view of the call graph of a module.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const
BeforePass instrumentation point - takes Pass instance to be executed and constant reference to IR it...
amdgpu Simplify well known AMD library false Value * Callee
A set of analyses that are preserved following a run of a transformation pass.
bool areAllPreserved() const
Test whether all analyses are preserved (and none are abandoned).
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
SmallPtrSetImpl< LazyCallGraph::RefSCC * > & InvalidatedRefSCCs
The set of invalidated RefSCCs which should be skipped if they are found in RCWorklist.
SmallPtrSetImpl< LazyCallGraph::SCC * > & InvalidatedSCCs
The set of invalidated SCCs which should be skipped if they are found in CWorklist.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
LazyCallGraph::RefSCC * UpdatedRC
If non-null, the updated current RefSCC being processed.
A node in the call graph.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
A class used to represent edges in the call graph.
auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly...
iterator erase(const_iterator CI)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
SmallPriorityWorklist< LazyCallGraph::SCC *, 1 > & CWorklist
Worklist of the SCCs queued for processing.
Pseudo-analysis pass that exposes the PassInstrumentation to pass managers.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
A SetVector that performs no allocations if smaller than a certain size.
print lazy value Lazy Value Info Printer Pass
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
void runAfterPass(const PassT &Pass, const IRUnitT &IR) const
AfterPass instrumentation point - takes Pass instance that has just been executed and constant refere...
An analysis over an "inner" IR unit that provides access to an analysis manager over a "outer" IR uni...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
void runAfterPassInvalidated(const PassT &Pass) const
AfterPassInvalidated instrumentation point - takes Pass instance that has just been executed...
Result run(IRUnitT &IR, AnalysisManager< IRUnitT, ExtraArgTs... > &AM, ExtraArgTs...)
Run the analysis pass and create our proxy result object.
ArrayRef< Function * > getLibFunctions() const
Get the sequence of known and defined library functions.
void invalidate(IRUnitT &IR)
Invalidate a specific analysis pass for an IR module.
Node * lookup(const Function &F) const
Lookup a function in the graph which has already been scanned and added.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Result(AnalysisManagerT &InnerAM)
void switchTrivialInternalEdgeToRef(Node &SourceN, Node &TargetN)
Make an existing internal call edge between separate SCCs into a ref edge.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Manages a sequence of passes over a particular unit of IR.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
void preserve()
Mark an analysis as preserved.
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...
An analysis pass which computes the call graph for a module.
This header provides classes for managing passes over SCCs of the call graph.
API to communicate dependencies between analyses during invalidation.
bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA, CGSCCAnalysisManager::Invalidator &Inv)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This templated class represents "all analyses that operate over <a particular IR unit>" (e...
LLVM Value Representation.
An SCC of the call graph.
inst_range instructions(Function *F)
A container for analyses that lazily runs them and caches their results.
This class provides instrumentation entry points for the Pass Manager, doing calls to callbacks regis...
This header defines various interfaces for pass management in LLVM.
static void visitReferences(SmallVectorImpl< Constant *> &Worklist, SmallPtrSetImpl< Constant *> &Visited, CallbackT Callback)
Recursively visits the defined functions whose address is reachable from every constant in the Workli...
A special type used by analysis passes to provide an address that identifies that particular analysis...
bool allAnalysesInSetPreserved() const
Directly test whether a set of analyses is preserved.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...