diff options
author | Chris Lattner <sabre@nondot.org> | 2002-07-10 22:38:08 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2002-07-10 22:38:08 +0000 |
commit | c68c31b2d3623f01bfcd1405ec005536d0815970 (patch) | |
tree | 66273844623a573132a299237a273ba5a69b09e4 /lib/Analysis/DataStructure/DataStructure.cpp | |
parent | 43199a036d5c191fc8c9ab4ba5a641ffeb3154d2 (diff) |
New implementation of data structure analysis. Only local analysis has been
implemented so far.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2871 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/DataStructure/DataStructure.cpp')
-rw-r--r-- | lib/Analysis/DataStructure/DataStructure.cpp | 222 |
1 files changed, 92 insertions, 130 deletions
diff --git a/lib/Analysis/DataStructure/DataStructure.cpp b/lib/Analysis/DataStructure/DataStructure.cpp index 7575a5da5b..84e2cfbc47 100644 --- a/lib/Analysis/DataStructure/DataStructure.cpp +++ b/lib/Analysis/DataStructure/DataStructure.cpp @@ -1,165 +1,127 @@ -//===- DataStructure.cpp - Analysis for data structure identification -------=// +//===- DataStructure.cpp - Implement the core data structure analysis -----===// // -// Implement the LLVM data structure analysis library. +// This file implements the core data structure functionality. // //===----------------------------------------------------------------------===// #include "llvm/Analysis/DataStructure.h" #include "llvm/Module.h" -#include <fstream> +#include "llvm/DerivedTypes.h" #include <algorithm> +#include "Support/STLExtras.h" -//===----------------------------------------------------------------------===// -// DataStructure Class Implementation -// +AnalysisID LocalDataStructures::ID(AnalysisID::create<LocalDataStructures>()); -AnalysisID DataStructure::ID(AnalysisID::create<DataStructure>()); +//===----------------------------------------------------------------------===// +// DSNode Implementation +//===----------------------------------------------------------------------===// -// releaseMemory - If the pass pipeline is done with this pass, we can release -// our memory... here... -void DataStructure::releaseMemory() { - for (InfoMap::iterator I = DSInfo.begin(), E = DSInfo.end(); I != E; ++I) { - delete I->second.first; - delete I->second.second; +DSNode::DSNode(enum NodeTy NT, const Type *T) : Ty(T), NodeType(NT) { + // If this node has any fields, allocate them now, but leave them null. + switch (T->getPrimitiveID()) { + case Type::PointerTyID: Links.resize(1); break; + case Type::ArrayTyID: Links.resize(1); break; + case Type::StructTyID: + Links.resize(cast<StructType>(T)->getNumContainedTypes()); + break; + default: break; } +} - // Empty map so next time memory is released, data structures are not - // re-deleted. - DSInfo.clear(); +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 = + std::find(Referrers.rbegin(), Referrers.rend(), H); + assert(I != Referrers.rend() && "Referrer not pointing to node!"); + Referrers.erase(I.base()-1); } -// FIXME REMOVE -#include <sys/time.h> -#include "Support/CommandLine.h" - -cl::Flag Time("t", "Print analysis time..."); - - -// print - Print out the analysis results... -void DataStructure::print(std::ostream &O, Module *M) const { - if (Time) { - timeval TV1, TV2; - gettimeofday(&TV1, 0); - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) - if (!I->isExternal() && I->getName() == "main") { - //getDSGraph(*I); - getClosedDSGraph(I); - } - gettimeofday(&TV2, 0); - std::cerr << "Analysis took " - << (TV2.tv_sec-TV1.tv_sec)*1000000+(TV2.tv_usec-TV1.tv_usec) - << " microseconds.\n"; +// addEdgeTo - Add an edge from the current node to the specified node. This +// can cause merging of nodes in the graph. +// +void DSNode::addEdgeTo(unsigned LinkNo, DSNode *N) { + assert(LinkNo < Links.size() && "LinkNo out of range!"); + if (N == 0 || Links[LinkNo] == N) return; // Nothing to do + if (Links[LinkNo] == 0) { // No merging to perform + Links[LinkNo] = N; + return; } - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) - if (!I->isExternal()) { - - std::string Filename = "ds." + I->getName() + ".dot"; - O << "Writing '" << Filename << "'..."; - std::ofstream F(Filename.c_str()); - - if (F.good()) { - F << "digraph DataStructures {\n" - << "\tnode [shape=Mrecord];\n" - << "\tedge [arrowtail=\"dot\"];\n" - << "\tsize=\"10,7.5\";\n" - << "\trotate=\"90\";\n"; - - getDSGraph(I).printFunction(F, "Local"); - getClosedDSGraph(I).printFunction(F, "Closed"); - - F << "}\n"; - } else { - O << " error opening file for writing!\n"; - } - - if (Time) - O << " [" << getDSGraph(I).getGraphSize() << ", " - << getClosedDSGraph(I).getGraphSize() << "]\n"; - else - O << "\n"; - } + // Merge the two nodes... + Links[LinkNo]->mergeWith(N); } -//===----------------------------------------------------------------------===// -// PointerVal Class Implementation +// mergeWith - Merge this node into the specified node, moving all links to and +// from the argument node into the current node. The specified node may be a +// null pointer (in which case, nothing happens). // - -void PointerVal::print(std::ostream &O) const { - if (Node) { - O << " Node: " << Node->getCaption() << "[" << Index << "]\n"; - } else { - O << " NULL NODE\n"; +void DSNode::mergeWith(DSNode *N) { + if (N == 0 || N == this) return; // Noop + assert(N->Ty == Ty && N->Links.size() == Links.size() && + "Cannot merge nodes of two different types!"); + + // Remove all edges pointing at N, causing them to point to 'this' instead. + while (!N->Referrers.empty()) + *N->Referrers.back() = this; + + // Make all of the outgoing links of N now be outgoing links of this. This + // can cause recursive merging! + // + for (unsigned i = 0, e = Links.size(); i != e; ++i) { + addEdgeTo(i, N->Links[i]); + N->Links[i] = 0; // Reduce unneccesary edges in graph. N is dead } -} - -//===----------------------------------------------------------------------===// -// PointerValSet Class Implementation -// -void PointerValSet::addRefs() { - for (unsigned i = 0, e = Vals.size(); i != e; ++i) - Vals[i].Node->addReferrer(this); + NodeType |= N->NodeType; + N->NodeType = 0; // N is now a dead node. } -void PointerValSet::dropRefs() { - for (unsigned i = 0, e = Vals.size(); i != e; ++i) - Vals[i].Node->removeReferrer(this); -} - -const PointerValSet &PointerValSet::operator=(const PointerValSet &PVS) { - dropRefs(); - Vals.clear(); - Vals = PVS.Vals; - addRefs(); - return *this; -} - -// operator< - Allow insertion into a map... -bool PointerValSet::operator<(const PointerValSet &PVS) const { - if (Vals.size() < PVS.Vals.size()) return true; - if (Vals.size() > PVS.Vals.size()) return false; - if (Vals.size() == 1) return Vals[0] < PVS.Vals[0]; // Most common case +//===----------------------------------------------------------------------===// +// DSGraph Implementation +//===----------------------------------------------------------------------===// - std::vector<PointerVal> S1(Vals), S2(PVS.Vals); - sort(S1.begin(), S1.end()); - sort(S2.begin(), S2.end()); - return S1 < S2; -} +DSGraph::~DSGraph() { + FunctionCalls.clear(); + ValueMap.clear(); + RetNode = 0; -bool PointerValSet::operator==(const PointerValSet &PVS) const { - if (Vals.size() != PVS.Vals.size()) return false; - if (Vals.size() == 1) return Vals[0] == PVS.Vals[0]; // Most common case... +#ifndef NDEBUG + // Drop all intra-node references, so that assertions don't fail... + std::for_each(Nodes.begin(), Nodes.end(), + std::mem_fun(&DSNode::dropAllReferences)); +#endif - std::vector<PointerVal> S1(Vals), S2(PVS.Vals); - sort(S1.begin(), S1.end()); - sort(S2.begin(), S2.end()); - return S1 == S2; + // Delete all of the nodes themselves... + std::for_each(Nodes.begin(), Nodes.end(), deleter<DSNode>); } +//===----------------------------------------------------------------------===// +// LocalDataStructures Implementation +//===----------------------------------------------------------------------===// -bool PointerValSet::add(const PointerVal &PV, Value *Pointer) { - if (std::find(Vals.begin(), Vals.end(), PV) != Vals.end()) - return false; - Vals.push_back(PV); - if (Pointer) PV.Node->addPointer(Pointer); - PV.Node->addReferrer(this); - return true; -} +// releaseMemory - If the pass pipeline is done with this pass, we can release +// our memory... here... +// +void LocalDataStructures::releaseMemory() { + for (std::map<Function*, DSGraph*>::iterator I = DSInfo.begin(), + E = DSInfo.end(); I != E; ++I) + delete I->second; -// removePointerTo - Remove a single pointer val that points to the specified -// node... -void PointerValSet::removePointerTo(DSNode *Node) { - std::vector<PointerVal>::iterator I = std::find(Vals.begin(), Vals.end(), Node); - assert(I != Vals.end() && "Couldn't remove nonexistent edge!"); - Vals.erase(I); - Node->removeReferrer(this); + // Empty map so next time memory is released, data structures are not + // re-deleted. + DSInfo.clear(); } +bool LocalDataStructures::run(Module &M) { + // Calculate all of the graphs... + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isExternal()) { + std::map<Function*, DSGraph*>::iterator DI = DSInfo.find(I); + if (DI == DSInfo.end() || DI->second == 0) + DSInfo.insert(std::make_pair(&*I, new DSGraph(*I))); + } -void PointerValSet::print(std::ostream &O) const { - for (unsigned i = 0, e = Vals.size(); i != e; ++i) - Vals[i].print(O); + return false; } - |