diff options
author | Chris Lattner <sabre@nondot.org> | 2005-03-19 22:23:45 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2005-03-19 22:23:45 +0000 |
commit | f4f62279892c3be475c2a94267f2863de87cfb40 (patch) | |
tree | a6bc16de59d851f5956b2051fc3c877e94d38abf /lib/Analysis/DataStructure/DataStructure.cpp | |
parent | 6269be8aca9f0787873d6c806e3e4ef0afbe9c89 (diff) |
Create an equivalence class of global variables that DSA will never be able
to tell apart anyway, and only track the leader for of these equivalence
classes in our graphs.
This dramatically reduces the number of GlobalValue*'s that appear in scalar
maps, which A) reduces memory usage, by eliminating many many scalarmap entries
and B) reduces time for operations that need to execute an operation for each
global in the scalar map.
As an example, this reduces the memory used to analyze 176.gcc from 1GB to
511MB, which (while it's still way too much) is better because it doesn't hit
swap anymore. On eon, this shrinks the local graphs from 14MB to 6.8MB,
shrinks the bu+td graphs of povray from 50M to 40M, shrinks the TD graphs of
130.li from 8.8M to 3.6M, etc.
This change also speeds up DSA on large programs where this makes a big
difference. For example, 130.li goes from 1.17s -> 0.56s, 134.perl goes
from 2.14 -> 0.93s, povray goes from 15.63s->7.99s (!!!).
This also apparently either fixes the problem that caused DSA to crash on
perlbmk and gcc, or it hides it, because DSA now works on these. These
both take entirely too much time in the TD pass (147s for perl, 538s for
gcc, vs 7.67/5.9s in the bu pass for either one), but this is a known
problem that I'll deal with later.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@20696 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/DataStructure/DataStructure.cpp')
-rw-r--r-- | lib/Analysis/DataStructure/DataStructure.cpp | 42 |
1 files changed, 15 insertions, 27 deletions
diff --git a/lib/Analysis/DataStructure/DataStructure.cpp b/lib/Analysis/DataStructure/DataStructure.cpp index 43170fdc24..5f8b3bfb91 100644 --- a/lib/Analysis/DataStructure/DataStructure.cpp +++ b/lib/Analysis/DataStructure/DataStructure.cpp @@ -115,7 +115,7 @@ void DSNode::assertOK() const { assert(ParentGraph && "Node has no parent?"); const DSScalarMap &SM = ParentGraph->getScalarMap(); for (unsigned i = 0, e = Globals.size(); i != e; ++i) { - assert(SM.count(Globals[i])); + assert(SM.global_count(Globals[i])); assert(SM.find(Globals[i])->second.getNode() == this); } } @@ -143,6 +143,10 @@ void DSNode::forwardNode(DSNode *To, unsigned Offset) { // marks the node with the 'G' flag if it does not already have it. // void DSNode::addGlobal(GlobalValue *GV) { + // First, check to make sure this is the leader if the global is in an + // equivalence class. + GV = getParentGraph()->getScalarMap().getLeaderForGlobal(GV); + // Keep the list sorted. std::vector<GlobalValue*>::iterator I = std::lower_bound(Globals.begin(), Globals.end(), GV); @@ -1091,14 +1095,16 @@ std::string DSGraph::getFunctionNames() const { } -DSGraph::DSGraph(const DSGraph &G) : GlobalsGraph(0), TD(G.TD) { +DSGraph::DSGraph(const DSGraph &G, EquivalenceClasses<GlobalValue*> &ECs) + : GlobalsGraph(0), ScalarMap(ECs), TD(G.TD) { PrintAuxCalls = false; NodeMapTy NodeMap; cloneInto(G, ScalarMap, ReturnNodes, NodeMap); } -DSGraph::DSGraph(const DSGraph &G, NodeMapTy &NodeMap) - : GlobalsGraph(0), TD(G.TD) { +DSGraph::DSGraph(const DSGraph &G, NodeMapTy &NodeMap, + EquivalenceClasses<GlobalValue*> &ECs) + : GlobalsGraph(0), ScalarMap(ECs), TD(G.TD) { PrintAuxCalls = false; cloneInto(G, ScalarMap, ReturnNodes, NodeMap); } @@ -1865,8 +1871,9 @@ void DSGraph::removeDeadNodes(unsigned Flags) { DSGraph::StripIncompleteBit); // Mark all nodes reachable by (non-global) scalar nodes as alive... - { TIME_REGION(Y, "removeDeadNodes:scalarscan"); - for (DSScalarMap::iterator I = ScalarMap.begin(), E = ScalarMap.end(); I !=E;) +{ TIME_REGION(Y, "removeDeadNodes:scalarscan"); + for (DSScalarMap::iterator I = ScalarMap.begin(), E = ScalarMap.end(); + I != E; ++I) if (isa<GlobalValue>(I->first)) { // Keep track of global nodes assert(!I->second.isNull() && "Null global node?"); assert(I->second.getNode()->isGlobalNode() && "Should be a global node!"); @@ -1881,29 +1888,10 @@ void DSGraph::removeDeadNodes(unsigned Flags) { else GGCloner.getClonedNH(I->second); } - ++I; } else { - DSNode *N = I->second.getNode(); -#if 0 - // Check to see if this is a worthless node generated for non-pointer - // values, such as integers. Consider an addition of long types: A+B. - // Assuming we can track all uses of the value in this context, and it is - // NOT used as a pointer, we can delete the node. We will be able to - // detect this situation if the node pointed to ONLY has Unknown bit set - // in the node. In this case, the node is not incomplete, does not point - // to any other nodes (no mod/ref bits set), and is therefore - // uninteresting for data structure analysis. If we run across one of - // these, prune the scalar pointing to it. - // - if (N->getNodeFlags() == DSNode::UnknownNode && !isa<Argument>(I->first)) - ScalarMap.erase(I++); - else { -#endif - N->markReachableNodes(Alive); - ++I; - //} + I->second.getNode()->markReachableNodes(Alive); } - } +} // The return values are alive as well. for (ReturnNodesTy::iterator I = ReturnNodes.begin(), E = ReturnNodes.end(); |