aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/DataStructure/DataStructure.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2002-07-18 18:22:40 +0000
committerChris Lattner <sabre@nondot.org>2002-07-18 18:22:40 +0000
commite221976b37705d2947baee553ce9947d6d9e9e3f (patch)
treef0cf14c0b54f95efa5b4729aa8b8fead04f422f6 /lib/Analysis/DataStructure/DataStructure.cpp
parent2a2c490154375269345edf08bf5ed3ff210376a0 (diff)
* Inline CopyFunctionCallsList
* Don't clone OrigCallList * Rename removeDeadNodes -> removeTriviallyDeadNodes * Implement new removeDeadNodes method git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2970 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/DataStructure/DataStructure.cpp')
-rw-r--r--lib/Analysis/DataStructure/DataStructure.cpp123
1 files changed, 88 insertions, 35 deletions
diff --git a/lib/Analysis/DataStructure/DataStructure.cpp b/lib/Analysis/DataStructure/DataStructure.cpp
index 89904c1019..befbd55040 100644
--- a/lib/Analysis/DataStructure/DataStructure.cpp
+++ b/lib/Analysis/DataStructure/DataStructure.cpp
@@ -8,9 +8,13 @@
#include "llvm/DerivedTypes.h"
#include "Support/STLExtras.h"
#include "Support/StatisticReporter.h"
+#include "Support/STLExtras.h"
#include <algorithm>
+#include <set>
#include "llvm/Analysis/DataStructure.h"
+using std::vector;
+
AnalysisID LocalDataStructures::ID(AnalysisID::create<LocalDataStructures>());
//===----------------------------------------------------------------------===//
@@ -37,7 +41,7 @@ DSNode::DSNode(const DSNode &N)
void DSNode::removeReferrer(DSNodeHandle *H) {
// Search backwards, because we depopulate the list from the back for
// efficiency (because it's a vector).
- std::vector<DSNodeHandle*>::reverse_iterator I =
+ vector<DSNodeHandle*>::reverse_iterator I =
std::find(Referrers.rbegin(), Referrers.rend(), H);
assert(I != Referrers.rend() && "Referrer not pointing to node!");
Referrers.erase(I.base()-1);
@@ -48,7 +52,7 @@ void DSNode::removeReferrer(DSNodeHandle *H) {
//
void DSNode::addGlobal(GlobalValue *GV) {
// Keep the list sorted.
- std::vector<GlobalValue*>::iterator I =
+ vector<GlobalValue*>::iterator I =
std::lower_bound(Globals.begin(), Globals.end(), GV);
if (I == Globals.end() || *I != GV) {
@@ -103,7 +107,7 @@ void DSNode::mergeWith(DSNode *N) {
// Merge the globals list...
if (!N->Globals.empty()) {
// Save the current globals off to the side...
- std::vector<GlobalValue*> OldGlobals(Globals);
+ vector<GlobalValue*> OldGlobals(Globals);
// Resize the globals vector to be big enough to hold both of them...
Globals.resize(Globals.size()+N->Globals.size());
@@ -149,24 +153,6 @@ DSGraph::~DSGraph() {
void DSGraph::dump() const { print(std::cerr); }
-// Helper function used to clone a function list.
-// Each call really shd have an explicit representation as a separate class.
-void
-CopyFunctionCallsList(const std::vector<std::vector<DSNodeHandle> >& fromCalls,
- std::vector<std::vector<DSNodeHandle> >& toCalls,
- std::map<const DSNode*, DSNode*>& NodeMap) {
-
- unsigned FC = toCalls.size(); // FirstCall
- toCalls.reserve(FC+fromCalls.size());
- for (unsigned i = 0, ei = fromCalls.size(); i != ei; ++i) {
- toCalls.push_back(std::vector<DSNodeHandle>());
- toCalls[FC+i].reserve(fromCalls[i].size());
- for (unsigned j = 0, ej = fromCalls[i].size(); j != ej; ++j)
- toCalls[FC+i].push_back(NodeMap[fromCalls[i][j]]);
- }
-}
-
-
// cloneInto - Clone the specified DSGraph into the current graph, returning the
// Return node of the graph. The translated ValueMap for the old function is
// filled into the OldValMap member. If StripLocals is set to true, Scalar and
@@ -175,7 +161,7 @@ CopyFunctionCallsList(const std::vector<std::vector<DSNodeHandle> >& fromCalls,
//
DSNode *DSGraph::cloneInto(const DSGraph &G,
std::map<Value*, DSNodeHandle> &OldValMap,
- std::map<const DSNode*, DSNode*>& OldNodeMap,
+ std::map<const DSNode*, DSNode*> &OldNodeMap,
bool StripLocals) {
assert(OldNodeMap.size()==0 && "Return argument OldNodeMap should be empty");
@@ -208,9 +194,15 @@ DSNode *DSGraph::cloneInto(const DSGraph &G,
E = G.ValueMap.end(); I != E; ++I)
OldValMap[I->first] = OldNodeMap[I->second];
- // Copy the current function calls list and the orig function calls list ...
- CopyFunctionCallsList(G.FunctionCalls, FunctionCalls, OldNodeMap);
- CopyFunctionCallsList(G.OrigFunctionCalls, OrigFunctionCalls, OldNodeMap);
+ // Copy the function calls list...
+ unsigned FC = FunctionCalls.size(); // FirstCall
+ FunctionCalls.reserve(FC+G.FunctionCalls.size());
+ for (unsigned i = 0, e = G.FunctionCalls.size(); i != e; ++i) {
+ FunctionCalls.push_back(std::vector<DSNodeHandle>());
+ FunctionCalls[FC+i].reserve(G.FunctionCalls[i].size());
+ for (unsigned j = 0, e = G.FunctionCalls[i].size(); j != e; ++j)
+ FunctionCalls[FC+i].push_back(OldNodeMap[G.FunctionCalls[i][j]]);
+ }
// Copy the list of unresolved callers
PendingCallers.insert(PendingCallers.end(),
@@ -258,10 +250,9 @@ void DSGraph::markIncompleteNodes() {
// Mark stuff passed into functions calls as being incomplete...
for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
- std::vector<DSNodeHandle> &Args = FunctionCalls[i];
- if (Args[0]) // If the call returns a pointer...
- // Then the return value is certainly incomplete!
- markIncompleteNode(Args[0]);
+ vector<DSNodeHandle> &Args = FunctionCalls[i];
+ // Then the return value is certainly incomplete!
+ markIncompleteNode(Args[0]);
// The call does not make the function argument incomplete...
@@ -308,19 +299,19 @@ bool DSGraph::isNodeDead(DSNode *N) {
}
-// removeDeadNodes - After the graph has been constructed, this method removes
-// all unreachable nodes that are created because they got merged with other
-// nodes in the graph. These nodes will all be trivially unreachable, so we
-// don't have to perform any non-trivial analysis here.
+// removeTriviallyDeadNodes - After the graph has been constructed, this method
+// removes all unreachable nodes that are created because they got merged with
+// other nodes in the graph. These nodes will all be trivially unreachable, so
+// we don't have to perform any non-trivial analysis here.
//
-void DSGraph::removeDeadNodes() {
+void DSGraph::removeTriviallyDeadNodes() {
for (unsigned i = 0; i != Nodes.size(); ++i)
if (isNodeDead(Nodes[i])) { // This node is dead!
delete Nodes[i]; // Free memory...
Nodes.erase(Nodes.begin()+i--); // Remove from node list...
}
- // Remove identical function calls
+ // Remove trivially identical function calls
unsigned NumFns = FunctionCalls.size();
std::sort(FunctionCalls.begin(), FunctionCalls.end());
FunctionCalls.erase(std::unique(FunctionCalls.begin(), FunctionCalls.end()),
@@ -332,6 +323,68 @@ void DSGraph::removeDeadNodes() {
}
+// markAlive - Simple graph traverser that recursively walks the graph marking
+// stuff to be alive.
+//
+static void markAlive(DSNode *N, std::set<DSNode*> &Alive) {
+ if (N == 0 || Alive.count(N)) return;
+
+ Alive.insert(N);
+ for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
+ markAlive(N->getLink(i), Alive);
+}
+
+
+// removeDeadNodes - Use a more powerful reachability analysis to eliminate
+// subgraphs that are unreachable. This often occurs because the data
+// structure doesn't "escape" into it's caller, and thus should be eliminated
+// from the caller's graph entirely. This is only appropriate to use when
+// inlining graphs.
+//
+void DSGraph::removeDeadNodes() {
+ // Reduce the amount of work we have to do...
+ removeTriviallyDeadNodes();
+
+ // FIXME: Merge nontrivially identical call nodes...
+
+ // Alive - a set that holds all nodes found to be reachable/alive.
+ std::set<DSNode*> Alive;
+
+ // Mark all nodes reachable by call nodes as alive...
+ for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i)
+ for (unsigned j = 0, e = FunctionCalls[i].size(); j != e; ++j)
+ markAlive(FunctionCalls[i][j], Alive);
+
+ for (unsigned i = 0, e = OrigFunctionCalls.size(); i != e; ++i)
+ for (unsigned j = 0, e = OrigFunctionCalls[i].size(); j != e; ++j)
+ markAlive(OrigFunctionCalls[i][j], Alive);
+
+ // Mark all nodes reachable by scalar, global, or incomplete nodes as
+ // reachable...
+ for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
+ if (Nodes[i]->NodeType & (DSNode::ScalarNode | DSNode::GlobalNode))
+ markAlive(Nodes[i], Alive);
+
+ // Loop over all unreachable nodes, dropping their references...
+ std::vector<DSNode*> DeadNodes;
+ DeadNodes.reserve(Nodes.size()); // Only one allocation is allowed.
+ for (unsigned i = 0; i != Nodes.size(); ++i)
+ if (!Alive.count(Nodes[i])) {
+ DSNode *N = Nodes[i];
+ Nodes.erase(Nodes.begin()+i--); // Erase node from alive list.
+ DeadNodes.push_back(N); // Add node to our list of dead nodes
+ N->dropAllReferences(); // Drop all outgoing edges
+ }
+
+ // The return value is alive as well...
+ markAlive(RetNode, Alive);
+
+ // Delete all dead nodes...
+ std::for_each(DeadNodes.begin(), DeadNodes.end(), deleter<DSNode>);
+}
+
+
+
// maskNodeTypes - Apply a mask to all of the node types in the graph. This
// is useful for clearing out markers like Scalar or Incomplete.
//