summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2017-07-09 13:16:55 +0000
committerChandler Carruth <chandlerc@gmail.com>2017-07-09 13:16:55 +0000
commit7c8964d885b2cf3f3f9f4aedaf16c15d9bcdf1a3 (patch)
treeb0cd04db2eae265af3c7d9f6e98a07fab1452135 /llvm/lib
parent170e6ccdf9f57e3df91fcc89a10510f102a5d89f (diff)
downloadbcm5719-llvm-7c8964d885b2cf3f3f9f4aedaf16c15d9bcdf1a3.tar.gz
bcm5719-llvm-7c8964d885b2cf3f3f9f4aedaf16c15d9bcdf1a3.zip
[PM] Add unittesting of the call graph update logic with complex
dependencies between analyses. This uncovers even more issues with the proxies and the splitting apart of SCCs which are fixed in this patch. I discovered this while trying to add more rigorous testing for a change I'm making to the call graph update invalidation logic. llvm-svn: 307497
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/CGSCCPassManager.cpp57
1 files changed, 51 insertions, 6 deletions
diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp
index b0a7d306b26..8205bba0f57 100644
--- a/llvm/lib/Analysis/CGSCCPassManager.cpp
+++ b/llvm/lib/Analysis/CGSCCPassManager.cpp
@@ -262,6 +262,51 @@ bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
} // End llvm namespace
+/// When a new SCC is created for the graph and there might be function
+/// analysis results cached for the functions now in that SCC two forms of
+/// updates are required.
+///
+/// First, a proxy from the SCC to the FunctionAnalysisManager needs to be
+/// created so that any subsequent invalidation events to the SCC are
+/// propagated to the function analysis results cached for functions within it.
+///
+/// Second, if any of the functions within the SCC have analysis results with
+/// outer analysis dependencies, then those dependencies would point to the
+/// *wrong* SCC's analysis result. We forcibly invalidate the necessary
+/// function analyses so that they don't retain stale handles.
+static void updateNewSCCFunctionAnalyses(LazyCallGraph::SCC &C,
+ LazyCallGraph &G,
+ CGSCCAnalysisManager &AM) {
+ // Get the relevant function analysis manager.
+ auto &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, G).getManager();
+
+ // Now walk the functions in this SCC and invalidate any function analysis
+ // results that might have outer dependencies on an SCC analysis.
+ for (LazyCallGraph::Node &N : C) {
+ Function &F = N.getFunction();
+
+ auto *OuterProxy =
+ FAM.getCachedResult<CGSCCAnalysisManagerFunctionProxy>(F);
+ if (!OuterProxy)
+ // No outer analyses were queried, nothing to do.
+ continue;
+
+ // Forcibly abandon all the inner analyses with dependencies, but
+ // invalidate nothing else.
+ auto PA = PreservedAnalyses::all();
+ for (const auto &OuterInvalidationPair :
+ OuterProxy->getOuterInvalidations()) {
+ const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
+ for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
+ PA.abandon(InnerAnalysisID);
+ }
+
+ // Now invalidate anything we found.
+ FAM.invalidate(F, PA);
+ }
+}
+
namespace {
/// Helper function to update both the \c CGSCCAnalysisManager \p AM and the \c
/// CGSCCPassManager's \c CGSCCUpdateResult \p UR based on a range of newly
@@ -314,9 +359,9 @@ incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G,
PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
AM.invalidate(*OldC, PA);
- // Ensure we have a proxy for the now-current SCC if needed.
+ // Ensure the now-current SCC's function analyses are updated.
if (NeedFAMProxy)
- (void)AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G);
+ updateNewSCCFunctionAnalyses(*C, G, AM);
for (SCC &NewC :
reverse(make_range(std::next(NewSCCRange.begin()), NewSCCRange.end()))) {
@@ -326,12 +371,12 @@ incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G,
if (DebugLogging)
dbgs() << "Enqueuing a newly formed SCC:" << NewC << "\n";
- // Ensure new SCCs have a FAM proxy if needed.
+ // Ensure new SCCs' function analyses are updated.
if (NeedFAMProxy)
- (void)AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G);
+ updateNewSCCFunctionAnalyses(*C, G, AM);
- // And propagate an invalidation to the new SCC as only the current will
- // get one from the pass manager infrastructure.
+ // Also propagate a normal invalidation to the new SCC as only the current
+ // will get one from the pass manager infrastructure.
AM.invalidate(NewC, PA);
}
return C;
OpenPOWER on IntegriCloud