[llvm-commits] [poolalloc] r116902 - in /poolalloc/trunk: include/dsa/DSGraph.h lib/DSA/BottomUpClosure.cpp lib/DSA/DSGraph.cpp lib/DSA/Local.cpp lib/DSA/StdLibPass.cpp lib/DSA/TopDownClosure.cpp
Will Dietz
wdietz2 at illinois.edu
Tue Oct 19 18:34:01 PDT 2010
Author: wdietz2
Date: Tue Oct 19 20:34:01 2010
New Revision: 116902
URL: http://llvm.org/viewvc/llvm-project?rev=116902&view=rev
Log:
Mark things External instead of Incomplete,
also handles a number of additional sources of external.
Modified:
poolalloc/trunk/include/dsa/DSGraph.h
poolalloc/trunk/lib/DSA/BottomUpClosure.cpp
poolalloc/trunk/lib/DSA/DSGraph.cpp
poolalloc/trunk/lib/DSA/Local.cpp
poolalloc/trunk/lib/DSA/StdLibPass.cpp
poolalloc/trunk/lib/DSA/TopDownClosure.cpp
Modified: poolalloc/trunk/include/dsa/DSGraph.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/dsa/DSGraph.h?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/include/dsa/DSGraph.h (original)
+++ poolalloc/trunk/include/dsa/DSGraph.h Tue Oct 19 20:34:01 2010
@@ -507,13 +507,14 @@
};
void markIncompleteNodes(unsigned Flags);
- // recalculateExternalNodes - Clear the external flag on all nodes,
- // then traverse the graph, identifying nodes that may be
- // exposed to external code. The sources of this happening are:
- // --Arguments and return values for external functions
- // --Arguments and return values for externally visible functions
- // --Externally visible globals
- void recalculateExternalNodes(void);
+ // Mark all reachable from external as external.
+ enum ComputeExternalFlags {
+ MarkFormalsExternal = 1, DontMarkFormalsExternal = 0,
+ ProcessCallSites = 2, IgnoreCallSites = 0,
+ ResetExternal = 4, DontResetExternal = 0,
+ MarkGlobalsReachableFromFormals = 8, IgnoreGlobalsReachableFromFormals = 0
+ };
+ void computeExternalFlags(unsigned Flags);
// removeDeadNodes - Use a reachability analysis to eliminate subgraphs that
// are unreachable. This often occurs because the data structure doesn't
Modified: poolalloc/trunk/lib/DSA/BottomUpClosure.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/BottomUpClosure.cpp?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/BottomUpClosure.cpp (original)
+++ poolalloc/trunk/lib/DSA/BottomUpClosure.cpp Tue Oct 19 20:34:01 2010
@@ -133,6 +133,7 @@
// Mark external globals incomplete.
GlobalsGraph->markIncompleteNodes(DSGraph::IgnoreGlobals);
+ GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
//
// Create equivalence classes for aliasing globals so that we only need to
@@ -151,7 +152,7 @@
Graph->maskIncompleteMarkers();
Graph->markIncompleteNodes(DSGraph::MarkFormalArgs |
DSGraph::IgnoreGlobals);
-
+ Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
}
}
@@ -163,7 +164,7 @@
//
callgraph.buildSCCs();
callgraph.buildRoots();
-
+
return false;
}
@@ -746,7 +747,7 @@
std::sort(NodeCallees.begin(), NodeCallees.end());
eraseCS = std::includes(CalledFuncs.begin(), CalledFuncs.end(),
NodeCallees.begin(), NodeCallees.end());
- }
+ }
//
// Update the statistics on resolved indirect function calls.
@@ -794,7 +795,7 @@
// Recompute the Incomplete markers
Graph->maskIncompleteMarkers();
Graph->markIncompleteNodes(DSGraph::MarkFormalArgs);
-
+ Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
//
// Update the callgraph with the new information that we have gleaned.
Modified: poolalloc/trunk/lib/DSA/DSGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/DSGraph.cpp?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/DSGraph.cpp (original)
+++ poolalloc/trunk/lib/DSA/DSGraph.cpp Tue Oct 19 20:34:01 2010
@@ -648,18 +648,6 @@
E = AuxFunctionCalls.end(); I != E; ++I)
markIncomplete(*I);
- // Mark stuff passed into external functions as being incomplete.
- // External functions may not appear in Aux during td, so process
- // them specially
-#if 0
- for (std::list<DSCallSite>::iterator I = FunctionCalls.begin(),
- E = FunctionCalls.end(); I != E; ++I)
- if(I->isDirectCall() && I->getCalleeFunc()->isDeclaration())
- markIncomplete(*I);
-#endif
- // Handle all sources of external
- recalculateExternalNodes();
-
// Mark all global nodes as incomplete.
for (DSScalarMap::global_iterator I = ScalarMap.global_begin(),
E = ScalarMap.global_end(); I != E; ++I)
@@ -676,104 +664,182 @@
}
}
-static void markExternalNode(DSNode *N) {
- // Stop recursion if no node, or if node already marked...
- if (N == 0 || N->isExternalNode()) return;
+// markExternalNode -- Marks the specified node, and all that's reachable from it,
+// as external. Uses 'processedNodes' to track recursion.
+static void markExternalNode(DSNode *N, svset<DSNode *> & processedNodes) {
+ // Stop recursion if no node, or if node already processed
+ if (N == 0 || processedNodes.count(N) ) return;
+
+ processedNodes.insert(N);
// Actually mark the node
N->setExternalMarker();
-
- // External also means incomplete
- N->setIncompleteMarker();
// FIXME: Should we 'collapse' the node as well?
// Recursively process children...
for (DSNode::edge_iterator ii = N->edge_begin(), ee = N->edge_end();
ii != ee; ++ii)
- markExternalNode(ii->second.getNode());
+ markExternalNode(ii->second.getNode(), processedNodes);
}
-static void markExternal(DSCallSite &Call) {
- markExternalNode(Call.getRetVal().getNode());
+// markExternal --marks the specified callsite external, using 'processedNodes' to track recursion.
+// Additionally, we set the externFuncMarker as appropriate.
+static void markExternal(const DSCallSite &Call, svset<DSNode *> & processedNodes) {
+ markExternalNode(Call.getRetVal().getNode(), processedNodes);
- markExternalNode(Call.getVAVal().getNode());
+ markExternalNode(Call.getVAVal().getNode(), processedNodes);
- // All objects pointed to by function arguments are incomplete!
+ // Mark all pointer arguments...
for (unsigned i = 0, e = Call.getNumPtrArgs(); i != e; ++i)
- markExternalNode(Call.getPtrArg(i).getNode());
+ markExternalNode(Call.getPtrArg(i).getNode(), processedNodes);
+
+ // Set the flag indicating this fptr contains external functions.
+ // FIXME: As far as I can tell, we don't actually set this anywhere else,
+ // and I haven't given much thought to where it's appropriate to do so.
+ // For now, setting it because it's not wrong and clearly a step forward
+ // but want to make it clear that I don't claim that this is now set
+ // properly everywhere the way it should.
+ if (Call.isIndirectCall()) {
+ Call.getCalleeNode()->setExternFuncMarker();
+ }
}
-// recalculateExternalNodes - Clear the external flag on all nodes,
-// then traverse the graph, identifying nodes that may be
-// exposed to external code. The sources of this happening are:
-// --Arguments and return values for external functions
-// --Arguments and return values for externally visible functions
-// --Externally visible globals
-void DSGraph::recalculateExternalNodes() {
-
- // Clear the external flag (we use it as marker for recursion)
- maskNodeTypes(~DSNode::ExternalNode);
-
- // Process all CallSites that call functions influenced by external code
- for (std::list<DSCallSite>::iterator I = FunctionCalls.begin(),
- E = FunctionCalls.end(); I != E; ++I) {
- bool shouldBeMarkedExternal = false;
-
- // Figure out what this callsite calls...
- std::vector<const Function *> Functions;
- if (I->isDirectCall())
- Functions.push_back(I->getCalleeFunc());
- else
- I->getCalleeNode()->addFullFunctionList(Functions);
+// propagateExternal -- Walk the given DSGraph making sure that within this graph
+// everything reachable from an already-external node is also marked External.
+static void propagateExternal(DSGraph * G, svset<DSNode *> & processedNodes) {
+ DSGraph::node_iterator I = G->node_begin(),
+ E = G->node_end();
+ for ( ; I != E; ++I ) {
+ if (I->isExternalNode())
+ markExternalNode(&*I, processedNodes);
+ }
+}
- // ...And examine each callee:
- for (std::vector<const Function *>::iterator II = Functions.begin(),
- EE = Functions.end();
- (II != EE) && !shouldBeMarkedExternal; ++II) {
+// computeExternalFlags -- mark all reachable from external as external
+void DSGraph::computeExternalFlags(unsigned Flags) {
- // Calls to external functions should be marked external
- shouldBeMarkedExternal |= (*II)->isDeclaration();
- // Calls to code that is externally visible should be marked
- // external. This might be overkill due to unification and the
- // various passes propagating this information,
- // but for now we /ensure/ the flags are set correctly.
- shouldBeMarkedExternal |= !(*II)->hasInternalLinkage();
- }
-
- if (shouldBeMarkedExternal) {
- markExternal(*I);
+ svset<DSNode *> processedNodes;
+
+ // Reset if indicated
+ if (Flags & ResetExternal) {
+ maskNodeTypes(~DSNode::ExternalNode);
+ }
+
+ if (Flags & MarkGlobalsReachableFromFormals) {
+ DenseSet<const DSNode*> ReachableFromFormals;
+ for (ReturnNodesTy::iterator FI = ReturnNodes.begin(), E = ReturnNodes.end();
+ FI != E; ++FI) {
+ const Function &F = *FI->first;
+ // Find all reachable from arguments...
+ for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end();
+ I != E; ++I)
+ if (isa<PointerType>(I->getType())) {
+ DSNode * N = getNodeForValue(I).getNode();
+ if (N) N->markReachableNodes(ReachableFromFormals);
+ }
+ // ...and the return value...
+ if (!FI->second.isNull())
+ FI->second.getNode()->markReachableNodes(ReachableFromFormals);
+ if (!getVANodeFor(F).isNull())
+ getVANodeFor(F).getNode()->markReachableNodes(ReachableFromFormals);
+ }
+
+ DenseSet<const DSNode*> ReachableFromGlobals;
+
+ for (DSScalarMap::global_iterator I = ScalarMap.global_begin(),
+ E = ScalarMap.global_end(); I != E; ++I) {
+ DSNode * N = getNodeForValue(*I).getNode();
+ if (N) N->markReachableNodes(ReachableFromGlobals);
+ }
+
+ // Find intersection of the two...
+ // FIXME: This works fine for local, but what about in other places where we might newly
+ // discover that something reachable from an externally visible function's argument is
+ // also reachable from a global and as such should be marked external in all graphs
+ // that use it?
+ for (DenseSet<const DSNode*>::iterator I = ReachableFromFormals.begin(),
+ E = ReachableFromFormals.end(); I != E; ++I) {
+ DSNode * N = (DSNode *)*I;
+ if (ReachableFromGlobals.count(N)) {
+ // Reachable from both a global and the formals, mark external!
+ markExternalNode(N, processedNodes);
+ }
}
}
- // Additionally, look at each *function* that is external-related
- // and set the External flag for its arguments and return value.
- for (ReturnNodesTy::iterator FI = ReturnNodes.begin(), E =ReturnNodes.end();
- FI != E; ++FI) {
- const Function &F = *FI->first;
- // If this function is potentially influenced by external code...
- if (!F.hasInternalLinkage() || F.isDeclaration()) {
+ // Make sure that everything reachable from something already external is also external
+ propagateExternal(this, processedNodes);
+
+ // If requested, we mark all functions (their formals) in this
+ // graph (read: SCC) as external.
+ if (Flags & MarkFormalsExternal) {
+ for (ReturnNodesTy::iterator FI = ReturnNodes.begin(), E =ReturnNodes.end();
+ FI != E; ++FI) {
+ const Function &F = *FI->first;
// Mark its arguments, return value (and vanode) as external.
for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end();
I != E; ++I)
if (isa<PointerType>(I->getType()))
- markExternalNode(getNodeForValue(I).getNode());
- markExternalNode(FI->second.getNode());
- markExternalNode(getVANodeFor(F).getNode());
+ markExternalNode(getNodeForValue(I).getNode(), processedNodes);
+ markExternalNode(FI->second.getNode(), processedNodes);
+ markExternalNode(getVANodeFor(F).getNode(), processedNodes);
+ }
+ }
+
+ // If requested, look for callsites to external functions and make
+ // sure that they're marked external as appropriate.
+ if (Flags & ProcessCallSites) {
+ // Get List of all callsites, resolved or not...
+ std::list<DSCallSite> AllCalls;
+ AllCalls.insert(AllCalls.begin(), fc_begin(), fc_end());
+ AllCalls.insert(AllCalls.begin(), afc_begin(), afc_end());
+
+ // ...and use that list to find all CallSites that call external functions
+ // and mark them accordingly.
+ for (std::list<DSCallSite>::iterator I = AllCalls.begin(),
+ E = AllCalls.end(); I != E; ++I) {
+ bool shouldBeMarkedExternal = false;
+
+ // Figure out what this callsite calls...
+ std::vector<const Function *> Functions;
+ if (I->isDirectCall())
+ Functions.push_back(I->getCalleeFunc());
+ else
+ I->getCalleeNode()->addFullFunctionList(Functions);
+
+ // ...And examine each callee:
+ for (std::vector<const Function *>::iterator II = Functions.begin(),
+ EE = Functions.end();
+ (II != EE) && !shouldBeMarkedExternal; ++II) {
+
+ // Calls to external functions should be marked external
+ shouldBeMarkedExternal |= (*II)->isDeclaration();
+ }
+
+ // If this callsite can call external code, it better be the case that the pointer arguments
+ // and the return values are all marked external (and what's reachable from them)
+ if (shouldBeMarkedExternal) {
+ markExternal(*I, processedNodes);
+ }
}
}
- // Now handle all external globals...
+ // Finally handle all external globals...
for (DSScalarMap::global_iterator I = ScalarMap.global_begin(),
- E = ScalarMap.global_end(); I != E; ++I)
+ E = ScalarMap.global_end(); I != E; ++I)
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) {
// If the global is external... mark it as such!
// FIXME: It's unclear to me that a global we initialize
- // can't be externally visible. For now preserving original
- // behavior (and additionally marking external as well as incomplete).
- if (!GV->hasInitializer())
- markExternalNode(ScalarMap[GV].getNode());
+ // can't be externally visible. For now following original
+ // behavior and marking external.
+ DSNode * N = ScalarMap[GV].getNode();
+ if (!GV->hasInitializer() || N->isExternalNode())
+ markExternalNode(N, processedNodes);
}
+
+ // FIXME: Sync with globals graph?
+ // For now, trust the caller to do this as appropriate.
}
static inline void killIfUselessEdge(DSNodeHandle &Edge) {
Modified: poolalloc/trunk/lib/DSA/Local.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/Local.cpp?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/Local.cpp (original)
+++ poolalloc/trunk/lib/DSA/Local.cpp Tue Oct 19 20:34:01 2010
@@ -159,10 +159,18 @@
for (Function::arg_iterator I = f.arg_begin(), E = f.arg_end();
I != E; ++I) {
if (isa<PointerType>(I->getType())) {
+ // WD: Why do we set the external marker so early in the analysis?
+ // Functions we have definitions for, but are externally reachable have no external contexts
+ // that we'd want to BU external information into (since those contexts are by definition
+ // ones we don't have code for). Shouldn't this just be set in TD?
+#if 0
DSNode * Node = getValueDest(I).getNode();
if (!f.hasInternalLinkage())
Node->setExternalMarker();
+#else
+ getValueDest(I).getNode();
+#endif
}
}
@@ -194,7 +202,19 @@
}
g.markIncompleteNodes(DSGraph::MarkFormalArgs);
-
+
+ // Compute sources of external
+ unsigned EFlags = 0
+ | DSGraph::DontMarkFormalsExternal
+ | DSGraph::ProcessCallSites;
+ // Mark globals reachable from formals as external if we don't have
+ // internal linkage.
+ if (!f.hasInternalLinkage()) {
+ EFlags |= DSGraph::MarkGlobalsReachableFromFormals;
+ }
+
+ g.computeExternalFlags(EFlags);
+
// Remove any nodes made dead due to merging...
g.removeDeadNodes(DSGraph::KeepUnreachableGlobals);
}
@@ -1236,6 +1256,7 @@
GlobalsGraph->removeTriviallyDeadNodes();
GlobalsGraph->markIncompleteNodes(DSGraph::MarkFormalArgs);
+ GlobalsGraph->computeExternalFlags(DSGraph::ProcessCallSites);
// Now that we've computed all of the graphs, and merged all of the info into
// the globals graph, see if we have further constrained the globals in the
Modified: poolalloc/trunk/lib/DSA/StdLibPass.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/StdLibPass.cpp?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/StdLibPass.cpp (original)
+++ poolalloc/trunk/lib/DSA/StdLibPass.cpp Tue Oct 19 20:34:01 2010
@@ -388,7 +388,7 @@
//
eraseCallsTo(F);
}
-
+
//
// Merge return values and checked pointer values for SAFECode run-time
// checks.
@@ -397,5 +397,22 @@
processRuntimeCheck (M, "sc.boundscheckui");
processRuntimeCheck (M, "sc.exactcheck2");
+ // In Local we marked nodes passed to/returned from 'StdLib' functions as External, because at
+ // that point they were. However they no longer are necessarily so, and we need to update accordingly.
+ GlobalsGraph->computeExternalFlags(DSGraph::ResetExternal);
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
+ if (!I->isDeclaration()) {
+ DSGraph * G = getDSGraph(*I);
+ unsigned EFlags = 0
+ | DSGraph::ResetExternal
+ | DSGraph::DontMarkFormalsExternal
+ | DSGraph::ProcessCallSites;
+ if (!I->hasInternalLinkage()) {
+ EFlags |= DSGraph::MarkGlobalsReachableFromFormals;
+ }
+ G->computeExternalFlags(EFlags);
+ }
+ GlobalsGraph->computeExternalFlags(DSGraph::ProcessCallSites);
+
return false;
}
Modified: poolalloc/trunk/lib/DSA/TopDownClosure.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/TopDownClosure.cpp?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/TopDownClosure.cpp (original)
+++ poolalloc/trunk/lib/DSA/TopDownClosure.cpp Tue Oct 19 20:34:01 2010
@@ -89,7 +89,8 @@
for (DSScalarMap::global_iterator I=GGSM.global_begin(), E=GGSM.global_end();
I != E; ++I) {
DSNode *N = GGSM.find(*I)->second.getNode();
- if (N->isIncompleteNode())
+ if (N->isIncompleteNode()) assert(N->isExternalNode());
+ if (N->isIncompleteNode() || N->isExternalNode())
markReachableFunctionsExternallyAccessible(N, Visited);
}
@@ -150,6 +151,7 @@
ArgsRemainIncomplete.clear();
GlobalsGraph->removeTriviallyDeadNodes();
+ GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
// CBU contains the correct call graph.
// Restore it, so that subsequent passes and clients can get it.
@@ -274,10 +276,16 @@
}
// Recompute the Incomplete markers. Depends on whether args are complete
- unsigned Flags
- = HasIncompleteArgs ? DSGraph::MarkFormalArgs : DSGraph::IgnoreFormalArgs;
- Flags |= DSGraph::IgnoreGlobals | DSGraph::MarkVAStart;
- DSG->markIncompleteNodes(Flags);
+ unsigned IncFlags = DSGraph::IgnoreFormalArgs;
+ IncFlags |= DSGraph::IgnoreGlobals | DSGraph::MarkVAStart;
+ DSG->markIncompleteNodes(IncFlags);
+
+ // If this graph contains functions that are externally callable, now is the time to mark
+ // their arguments and return values as external. At this point TD is inlining all caller information,
+ // and that means External callers too.
+ unsigned ExtFlags
+ = HasIncompleteArgs ? DSGraph::MarkFormalsExternal : DSGraph::DontMarkFormalsExternal;
+ DSG->computeExternalFlags(ExtFlags);
//
// Delete dead nodes. Treat globals that are unreachable as dead also.
More information about the llvm-commits
mailing list