summaryrefslogtreecommitdiff
path: root/lib/Analysis/DataStructure/Local.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-03-19 22:23:45 +0000
committerChris Lattner <sabre@nondot.org>2005-03-19 22:23:45 +0000
commitf4f62279892c3be475c2a94267f2863de87cfb40 (patch)
treea6bc16de59d851f5956b2051fc3c877e94d38abf /lib/Analysis/DataStructure/Local.cpp
parent6269be8aca9f0787873d6c806e3e4ef0afbe9c89 (diff)
downloadllvm-f4f62279892c3be475c2a94267f2863de87cfb40.tar.gz
llvm-f4f62279892c3be475c2a94267f2863de87cfb40.tar.bz2
llvm-f4f62279892c3be475c2a94267f2863de87cfb40.tar.xz
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/Local.cpp')
-rw-r--r--lib/Analysis/DataStructure/Local.cpp43
1 files changed, 36 insertions, 7 deletions
diff --git a/lib/Analysis/DataStructure/Local.cpp b/lib/Analysis/DataStructure/Local.cpp
index 9cb899cb37..02b5b16a58 100644
--- a/lib/Analysis/DataStructure/Local.cpp
+++ b/lib/Analysis/DataStructure/Local.cpp
@@ -164,8 +164,9 @@ using namespace DS;
//===----------------------------------------------------------------------===//
// DSGraph constructor - Simply use the GraphBuilder to construct the local
// graph.
-DSGraph::DSGraph(const TargetData &td, Function &F, DSGraph *GG)
- : GlobalsGraph(GG), TD(td) {
+DSGraph::DSGraph(EquivalenceClasses<GlobalValue*> &ECs, const TargetData &td,
+ Function &F, DSGraph *GG)
+ : GlobalsGraph(GG), ScalarMap(ECs), TD(td) {
PrintAuxCalls = false;
DEBUG(std::cerr << " [Loc] Calculating graph for: " << F.getName() << "\n");
@@ -1071,21 +1072,49 @@ void GraphBuilder::mergeInGlobalInitializer(GlobalVariable *GV) {
bool LocalDataStructures::runOnModule(Module &M) {
const TargetData &TD = getAnalysis<TargetData>();
- GlobalsGraph = new DSGraph(TD);
-
+ // First step, build the globals graph.
+ GlobalsGraph = new DSGraph(GlobalECs, TD);
{
GraphBuilder GGB(*GlobalsGraph);
- // Add initializers for all of the globals to the globals graph...
- for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
+ // Add initializers for all of the globals to the globals graph.
+ for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+ I != E; ++I)
if (!I->isExternal())
GGB.mergeInGlobalInitializer(I);
}
+ // Next step, iterate through the nodes in the globals graph, unioning
+ // together the globals into equivalence classes.
+ for (DSGraph::node_iterator I = GlobalsGraph->node_begin(),
+ E = GlobalsGraph->node_end(); I != E; ++I)
+ if (I->getGlobals().size() > 1) {
+ // First, build up the equivalence set for this block of globals.
+ const std::vector<GlobalValue*> &GVs = I->getGlobals();
+ GlobalValue *First = GVs[0];
+ for (unsigned i = 1, e = GVs.size(); i != e; ++i)
+ GlobalECs.unionSets(First, GVs[i]);
+
+ // Next, get the leader element.
+ First = GlobalECs.getLeaderValue(First);
+
+ // Next, remove all globals from the scalar map that are not the leader.
+ DSScalarMap &SM = GlobalsGraph->getScalarMap();
+ for (unsigned i = 0, e = GVs.size(); i != e; ++i)
+ if (GVs[i] != First)
+ SM.erase(SM.find(GVs[i]));
+
+ // Finally, change the global node to only contain the leader.
+ I->clearGlobals();
+ I->addGlobal(First);
+ }
+ DEBUG(GlobalsGraph->AssertGraphOK());
+
// Calculate all of the graphs...
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
if (!I->isExternal())
- DSInfo.insert(std::make_pair(I, new DSGraph(TD, *I, GlobalsGraph)));
+ DSInfo.insert(std::make_pair(I, new DSGraph(GlobalECs, TD, *I,
+ GlobalsGraph)));
GlobalsGraph->removeTriviallyDeadNodes();
GlobalsGraph->markIncompleteNodes(DSGraph::MarkFormalArgs);