summaryrefslogtreecommitdiff
path: root/llvm/include/llvm/Analysis/CGSCCPassManager.h
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/include/llvm/Analysis/CGSCCPassManager.h')
-rw-r--r--llvm/include/llvm/Analysis/CGSCCPassManager.h87
1 files changed, 65 insertions, 22 deletions
diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h
index 933f2210dafce..eb0d3ae8fedfc 100644
--- a/llvm/include/llvm/Analysis/CGSCCPassManager.h
+++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -95,7 +95,6 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/LazyCallGraph.h"
-#include "llvm/IR/CallSite.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/PassManager.h"
@@ -381,10 +380,15 @@ class FunctionAnalysisManagerCGSCCProxy
public:
class Result {
public:
+ explicit Result() : FAM(nullptr) {}
explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
+ void updateFAM(FunctionAnalysisManager &FAM) { this->FAM = &FAM; }
/// Accessor for the analysis manager.
- FunctionAnalysisManager &getManager() { return *FAM; }
+ FunctionAnalysisManager &getManager() {
+ assert(FAM);
+ return *FAM;
+ }
bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
CGSCCAnalysisManager::Invalidator &Inv);
@@ -416,7 +420,19 @@ using CGSCCAnalysisManagerFunctionProxy =
/// update result struct for the overall CGSCC walk.
LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass(
LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
- CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR);
+ CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+ FunctionAnalysisManager &FAM);
+
+/// Helper to update the call graph after running a CGSCC pass.
+///
+/// CGSCC passes can only mutate the call graph in specific ways. This
+/// routine provides a helper that updates the call graph in those ways
+/// including returning whether any changes were made and populating a CG
+/// update result struct for the overall CGSCC walk.
+LazyCallGraph::SCC &updateCGAndAnalysisManagerForCGSCCPass(
+ LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
+ CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+ FunctionAnalysisManager &FAM);
/// Adaptor that maps from a SCC to its functions.
///
@@ -484,7 +500,11 @@ public:
if (!PI.runBeforePass<Function>(Pass, F))
continue;
- PreservedAnalyses PassPA = Pass.run(F, FAM);
+ PreservedAnalyses PassPA;
+ {
+ TimeTraceScope TimeScope(Pass.name());
+ PassPA = Pass.run(F, FAM);
+ }
PI.runAfterPass<Function>(Pass, F);
@@ -503,7 +523,7 @@ public:
auto PAC = PA.getChecker<LazyCallGraphAnalysis>();
if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) {
CurrentC = &updateCGAndAnalysisManagerForFunctionPass(CG, *CurrentC, *N,
- AM, UR);
+ AM, UR, FAM);
assert(
CG.lookupSCC(*N) == CurrentC &&
"Current SCC not updated to the SCC containing the current node!");
@@ -591,8 +611,8 @@ public:
CallCounts.insert(std::make_pair(&N.getFunction(), CountLocal))
.first->second;
for (Instruction &I : instructions(N.getFunction()))
- if (auto CS = CallSite(&I)) {
- if (CS.getCalledFunction()) {
+ if (auto *CB = dyn_cast<CallBase>(&I)) {
+ if (CB->getCalledFunction()) {
++Count.Direct;
} else {
++Count.Indirect;
@@ -634,17 +654,17 @@ public:
auto IsDevirtualizedHandle = [&](WeakTrackingVH &CallH) {
if (!CallH)
return false;
- auto CS = CallSite(CallH);
- if (!CS)
+ auto *CB = dyn_cast<CallBase>(CallH);
+ if (!CB)
return false;
// If the call is still indirect, leave it alone.
- Function *F = CS.getCalledFunction();
+ Function *F = CB->getCalledFunction();
if (!F)
return false;
LLVM_DEBUG(dbgs() << "Found devirtualized call from "
- << CS.getParent()->getParent()->getName() << " to "
+ << CB->getParent()->getParent()->getName() << " to "
<< F->getName() << "\n");
// We now have a direct call where previously we had an indirect call,
@@ -706,6 +726,7 @@ public:
// Update the analysis manager with each run and intersect the total set
// of preserved analyses so we're ready to iterate.
AM.invalidate(*C, PassPA);
+
PA.intersect(std::move(PassPA));
}
@@ -741,6 +762,10 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
// Get the call graph for this module.
LazyCallGraph &CG = AM.getResult<LazyCallGraphAnalysis>(M);
+ // Get Function analysis manager from its proxy.
+ FunctionAnalysisManager &FAM =
+ AM.getCachedResult<FunctionAnalysisManagerModuleProxy>(M)->getManager();
+
// We keep worklists to allow us to push more work onto the pass manager as
// the passes are run.
SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> RCWorklist;
@@ -795,6 +820,12 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
LLVM_DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC
<< "\n");
+ // The top of the worklist may *also* be the same SCC we just ran over
+ // (and invalidated for). Keep track of that last SCC we processed due
+ // to SCC update to avoid redundant processing when an SCC is both just
+ // updated itself and at the top of the worklist.
+ LazyCallGraph::SCC *LastUpdatedC = nullptr;
+
// Push the initial SCCs in reverse post-order as we'll pop off the
// back and so see this in post-order.
for (LazyCallGraph::SCC &C : llvm::reverse(*RC))
@@ -810,17 +841,22 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
LLVM_DEBUG(dbgs() << "Skipping an invalid SCC...\n");
continue;
}
+ if (LastUpdatedC == C) {
+ LLVM_DEBUG(dbgs() << "Skipping redundant run on SCC: " << *C << "\n");
+ continue;
+ }
if (&C->getOuterRefSCC() != RC) {
LLVM_DEBUG(dbgs() << "Skipping an SCC that is now part of some other "
"RefSCC...\n");
continue;
}
- // Ensure we can proxy analysis updates from from the CGSCC analysis
- // manager into the Function analysis manager by getting a proxy here.
- // FIXME: This seems like a bit of a hack. We should find a cleaner
- // or more costructive way to ensure this happens.
- (void)CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG);
+ // Ensure we can proxy analysis updates from the CGSCC analysis manager
+ // into the the Function analysis manager by getting a proxy here.
+ // This also needs to update the FunctionAnalysisManager, as this may be
+ // the first time we see this SCC.
+ CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG).updateFAM(
+ FAM);
// Each time we visit a new SCC pulled off the worklist,
// a transformation of a child SCC may have also modified this parent
@@ -837,11 +873,6 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
// invalidate the analyses for any SCCs other than themselves which
// are mutated. However, that seems to lose the robustness of the
// pass-manager driven invalidation scheme.
- //
- // FIXME: This is redundant in one case -- the top of the worklist may
- // *also* be the same SCC we just ran over (and invalidated for). In
- // that case, we'll end up doing a redundant invalidation here as
- // a consequence.
CGAM.invalidate(*C, UR.CrossSCCPA);
do {
@@ -851,6 +882,7 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
assert(&C->getOuterRefSCC() == RC &&
"Processing an SCC in a different RefSCC!");
+ LastUpdatedC = UR.UpdatedC;
UR.UpdatedRC = nullptr;
UR.UpdatedC = nullptr;
@@ -860,7 +892,11 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
if (!PI.runBeforePass<LazyCallGraph::SCC>(Pass, *C))
continue;
- PreservedAnalyses PassPA = Pass.run(*C, CGAM, CG, UR);
+ PreservedAnalyses PassPA;
+ {
+ TimeTraceScope TimeScope(Pass.name());
+ PassPA = Pass.run(*C, CGAM, CG, UR);
+ }
if (UR.InvalidatedSCCs.count(C))
PI.runAfterPassInvalidated<LazyCallGraph::SCC>(Pass);
@@ -871,6 +907,13 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
C = UR.UpdatedC ? UR.UpdatedC : C;
RC = UR.UpdatedRC ? UR.UpdatedRC : RC;
+ if (UR.UpdatedC) {
+ // If we're updating the SCC, also update the FAM inside the proxy's
+ // result.
+ CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG).updateFAM(
+ FAM);
+ }
+
// If the CGSCC pass wasn't able to provide a valid updated SCC,
// the current SCC may simply need to be skipped if invalid.
if (UR.InvalidatedSCCs.count(C)) {