[llvm-commits] [poolalloc] r98781 - in /poolalloc/trunk: include/dsa/DSCallGraph.h include/dsa/DataStructure.h include/dsa/svset.h lib/DSA/BottomUpClosure.cpp lib/DSA/CompleteBottomUp.cpp lib/DSA/DataStructure.cpp lib/DSA/Local.cpp
Andrew Lenharth
andrewl at lenharth.org
Wed Mar 17 17:03:53 PDT 2010
Author: alenhar2
Date: Wed Mar 17 19:03:53 2010
New Revision: 98781
URL: http://llvm.org/viewvc/llvm-project?rev=98781&view=rev
Log:
Use generic EquivalenceClass to store SCCs and clean up the mess that was DSSCCGraph
Modified:
poolalloc/trunk/include/dsa/DSCallGraph.h
poolalloc/trunk/include/dsa/DataStructure.h
poolalloc/trunk/include/dsa/svset.h
poolalloc/trunk/lib/DSA/BottomUpClosure.cpp
poolalloc/trunk/lib/DSA/CompleteBottomUp.cpp
poolalloc/trunk/lib/DSA/DataStructure.cpp
poolalloc/trunk/lib/DSA/Local.cpp
Modified: poolalloc/trunk/include/dsa/DSCallGraph.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/dsa/DSCallGraph.h?rev=98781&r1=98780&r2=98781&view=diff
==============================================================================
--- poolalloc/trunk/include/dsa/DSCallGraph.h (original)
+++ poolalloc/trunk/include/dsa/DSCallGraph.h Wed Mar 17 19:03:53 2010
@@ -18,10 +18,10 @@
#include "dsa/keyiterator.h"
#include <map>
-#include "llvm/Function.h"
-#include "llvm/DerivedTypes.h"
+//Fix in 2.8, EQC includes cassert
+#include <cassert>
+#include "llvm/ADT/EquivalenceClasses.h"
#include "llvm/Support/CallSite.h"
-#include "llvm/Support/FormattedStream.h"
class DSCallGraph {
@@ -31,31 +31,44 @@
typedef std::map<const llvm::Function*, FuncSet> SimpleCalleesTy;
private:
+ //ActualCallees contains CallSite -> Function mappings
ActualCalleesTy ActualCallees;
+ //SimpleCallees contains Function -> Function mappings
SimpleCalleesTy SimpleCallees;
+ //These are used for returning empty sets when the caller has no callees
FuncSet EmptyActual;
FuncSet EmptySimple;
+ //An equivalence class is exactly an SCC
+ llvm::EquivalenceClasses<const llvm::Function*> SCCs;
+
+ //Functions we know about that aren't called
+ svset<const llvm::Function*> knownRoots;
+
+ //Types for SCC construction
+ typedef std::map<const llvm::Function*, unsigned> TFMap;
+ typedef std::vector<const llvm::Function*> TFStack;
+
+ // Tarjan's SCC algorithm
+ unsigned tarjan_rec(const llvm::Function* F, TFStack& Stack, unsigned &NextID,
+ TFMap& ValMap);
+
+ void removeECFunctions();
+
public:
DSCallGraph() {}
typedef ActualCalleesTy::mapped_type::const_iterator callee_iterator;
- typedef KeyIterator<ActualCalleesTy::const_iterator> key_iterator;
+ typedef KeyIterator<ActualCalleesTy::const_iterator> callee_key_iterator;
typedef SimpleCalleesTy::mapped_type::const_iterator flat_iterator;
typedef KeyIterator<SimpleCalleesTy::const_iterator> flat_key_iterator;
+ typedef FuncSet::const_iterator root_iterator;
+ typedef llvm::EquivalenceClasses<const llvm::Function*>::member_iterator scc_iterator;
- void insert(llvm::CallSite CS, const llvm::Function* F) {
- if (F) {
- ActualCallees[CS].insert(F);
- SimpleCallees[CS.getInstruction()->getParent()->getParent()].insert(F);
- //Create an empty set for the callee, hence all called functions get to be
- // in the call graph also. This simplifies SCC formation
- SimpleCallees[F];
- }
- }
-
+ void insert(llvm::CallSite CS, const llvm::Function* F);
+
template<class Iterator>
void insert(llvm::CallSite CS, Iterator _begin, Iterator _end) {
for (; _begin != _end; ++_begin)
@@ -76,12 +89,12 @@
return ii->second.end();
}
- key_iterator key_begin() const {
- return key_iterator(ActualCallees.begin());
+ callee_key_iterator key_begin() const {
+ return callee_key_iterator(ActualCallees.begin());
}
- key_iterator key_end() const {
- return key_iterator(ActualCallees.end());
+ callee_key_iterator key_end() const {
+ return callee_key_iterator(ActualCallees.end());
}
flat_iterator flat_callee_begin(const llvm::Function* F) const {
@@ -106,6 +119,24 @@
return flat_key_iterator(SimpleCallees.end());
}
+ root_iterator root_begin() const {
+ return knownRoots.begin();
+ }
+
+ root_iterator root_end() const {
+ return knownRoots.end();
+ }
+
+ scc_iterator scc_begin(const llvm::Function* F) const {
+ assert(F == SCCs.getLeaderValue(F) && "Requested non-leader");
+ return SCCs.member_begin(SCCs.findValue(F));
+ }
+
+ scc_iterator scc_end(const llvm::Function* F) const {
+ assert(F == SCCs.getLeaderValue(F) && "Requested non-leader");
+ return SCCs.member_end();
+ }
+
unsigned callee_size(llvm::CallSite CS) const {
ActualCalleesTy::const_iterator ii = ActualCallees.find(CS);
@@ -122,196 +153,19 @@
return sum;
}
- void clear() {
- ActualCallees.clear();
- }
-
-};
-
-class DSSCCGraph {
-public:
- //SCCs, each element is an SCC
- std::map<unsigned, DSCallGraph::FuncSet> SCCs;
- //mapping of functions in SCCs to SCCs index
- std::map<const llvm::Function*, unsigned> invmap;
-
- unsigned nextSCC;
+ void buildSCCs();
- //Functions we know about that aren't called
- svset<unsigned> knownRoots;
-
- std::map<unsigned, svset<unsigned> > SCCCallees;
- std::map<unsigned, svset<unsigned> > ExtCallees;
-
- DSCallGraph oldGraph;
-
-private:
- typedef std::map<const llvm::Function*, unsigned> TFMap;
- typedef std::vector<const llvm::Function*> TFStack;
+ void buildRoots();
- bool hasPointers(const llvm::Function* F) {
- if (F->isVarArg()) return true;
- if (F->getReturnType()->isPointerTy()) return true;
- for (llvm::Function::const_arg_iterator ii = F->arg_begin(), ee = F->arg_end();
- ii != ee; ++ii)
- if (ii->getType()->isPointerTy()) return true;
- return false;
- }
+ void dump();
- unsigned tarjan_rec(const llvm::Function* F, TFStack& Stack, unsigned &NextID,
- TFMap& ValMap, DSCallGraph& cg) {
- assert(!ValMap.count(F) && "Shouldn't revisit functions!");
- unsigned Min = NextID++, MyID = Min;
- ValMap[F] = Min;
- Stack.push_back(F);
-
- // The edges out of the current node are the call site targets...
- for (DSCallGraph::flat_iterator ii = cg.flat_callee_begin(F),
- ee = cg.flat_callee_end(F); ii != ee; ++ii) {
- if (hasPointers(*ii) && !(*ii)->isDeclaration()) {
- unsigned M = Min;
- // Have we visited the destination function yet?
- TFMap::iterator It = ValMap.find(*ii);
- if (It == ValMap.end()) // No, visit it now.
- M = tarjan_rec(*ii, Stack, NextID, ValMap, cg);
- else if (std::find(Stack.begin(), Stack.end(), *ii) != Stack.end())
- M = It->second;
- if (M < Min) Min = M;
- }
- }
-
- assert(ValMap[F] == MyID && "SCC construction assumption wrong!");
- if (Min != MyID)
- return Min; // This is part of a larger SCC!
-
- // If this is a new SCC, process it now.
- ++nextSCC;
-
- const llvm::Function* NF = 0;
- do {
- NF = Stack.back();
- Stack.pop_back();
- assert(NF && "Null Function");
- assert(invmap.find(NF) == invmap.end() && "Function already in invmap");
- invmap[NF] = nextSCC;
- assert(SCCs[nextSCC].find(NF) == SCCs[nextSCC].end() &&
- "Function already in SCC");
- SCCs[nextSCC].insert(NF);
- } while (NF != F);
-
- return MyID;
- }
-
- void buildSCC(DSCallGraph& DSG) {
- TFStack Stack;
- TFMap ValMap;
- unsigned NextID = 1;
-
- for (DSCallGraph::flat_key_iterator ii = DSG.flat_key_begin(),
- ee = DSG.flat_key_end(); ii != ee; ++ii)
- if (!ValMap.count(*ii))
- tarjan_rec(*ii, Stack, NextID, ValMap, DSG);
- }
-
- void buildCallGraph(DSCallGraph& DSG) {
- for(DSCallGraph::flat_key_iterator ii = DSG.flat_key_begin(),
- ee = DSG.flat_key_end(); ii != ee; ++ii) {
- assert (*ii && "Null Function");
- assert(invmap.find(*ii) != invmap.end() && "Unknown Function");
- for (DSCallGraph::flat_iterator fi = DSG.flat_callee_begin(*ii),
- fe = DSG.flat_callee_end(*ii); fi != fe; ++fi) {
- assert(*fi && "Null Function");
- assert(invmap.find(*fi) != invmap.end() && "Unknown Function");
- if (invmap[*ii] != invmap[*fi]) // No self calls
- if (hasPointers(*fi)) {
- if ((*fi)->isDeclaration())
- ExtCallees[invmap[*ii]].insert(invmap[*fi]);
- else
- SCCCallees[invmap[*ii]].insert(invmap[*fi]);
- }
- }
- }
- }
-
- void buildRoots() {
- svset<unsigned> knownCallees;
- svset<unsigned> knownCallers;
- for (std::map<unsigned, svset<unsigned> >::iterator
- ii = SCCCallees.begin(), ee = SCCCallees.end(); ii != ee; ++ii) {
- knownCallees.insert(ii->second.begin(), ii->second.end());
- knownCallers.insert(ii->first);
- }
- for (svset<unsigned>::iterator ii = knownCallers.begin(),
- ee = knownCallers.end(); ii != ee; ++ii)
- if (!knownCallees.count(*ii))
- knownRoots.insert(*ii);
- }
-
- void assertMapValid() {
- for (std::map<unsigned, DSCallGraph::FuncSet>::iterator ii = SCCs.begin(),
- ee = SCCs.end(); ii != ee; ++ii) {
- for (DSCallGraph::FuncSet::iterator i = ii->second.begin(),
- e = ii->second.end(); i != e; ++i) {
- assert(*i && "Null Function in map");
- assert(invmap.find(*i) != invmap.end() && "Function not in invmap");
- assert(invmap[*i] == ii->first && "invmap doesn't match map");
- }
- }
-
- for (std::map<const llvm::Function*, unsigned>::iterator ii = invmap.begin(),
- ee = invmap.end(); ii != ee; ++ii) {
- assert(ii->first && "Null Function in invmap");
- assert(SCCs.find(ii->second) != SCCs.end() && "Function in invmap but not in map");
- assert(SCCs[ii->second].count(ii->first) && "SCC doesn't contain function");
- }
+ void assertSCCRoot(const llvm::Function* F) {
+ assert(F == SCCs.getLeaderValue(F) && "Not Leader?");
}
-public:
-
- DSSCCGraph(DSCallGraph& DSG) :nextSCC(0) {
- oldGraph = DSG;
-
- buildSCC(DSG);
- assertMapValid();
-
- buildCallGraph(DSG);
-
- buildRoots();
-
- }
-
- void dump() {
- //function map
- for (std::map<unsigned, DSCallGraph::FuncSet>::iterator ii = SCCs.begin(),
- ee = SCCs.end(); ii != ee; ++ii) {
- llvm::errs() << "Functions in " << ii->first << ":";
- for (DSCallGraph::FuncSet::iterator i = ii->second.begin(),
- e = ii->second.end(); i != e; ++i)
- llvm::errs() << " " << *i << "(" << invmap[*i] << ")";
- llvm::errs() << "\n";
- }
-
-// for (std::map<const llvm::Function*, unsigned>::iterator ii = invmap.begin(),
-// ee = invmap.end(); ii != ee; ++ii)
-// llvm::errs() << ii->first << " -> " << ii->second << "\n";
-
- //SCC map
- for (std::map<unsigned, svset<unsigned> >::iterator ii = SCCCallees.begin(),
- ee = SCCCallees.end(); ii != ee; ++ii) {
- llvm::errs() << "CallGraph[" << ii->first << "]";
- for (svset<unsigned>::iterator i = ii->second.begin(),
- e = ii->second.end(); i != e; ++i)
- llvm::errs() << " " << *i;
- llvm::errs() << "\n";
- }
-
- //Functions we know about that aren't called
- llvm::errs() << "Roots:";
- for (svset<unsigned>::iterator ii = knownRoots.begin(),
- ee = knownRoots.end(); ii != ee; ++ii)
- llvm::errs() << " " << *ii;
- llvm::errs() << "\n";
- }
+ //common helper, no good reason for it to be here rather than elsewhere
+ static bool hasPointers(const llvm::Function* F);
+ static bool hasPointers(llvm::CallSite& CS);
};
Modified: poolalloc/trunk/include/dsa/DataStructure.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/dsa/DataStructure.h?rev=98781&r1=98780&r2=98781&view=diff
==============================================================================
--- poolalloc/trunk/include/dsa/DataStructure.h (original)
+++ poolalloc/trunk/include/dsa/DataStructure.h Wed Mar 17 19:03:53 2010
@@ -235,11 +235,12 @@
bool runOnModuleInternal(Module &M);
private:
- void mergeSCCs(DSSCCGraph& DSG);
+ void mergeSCCs();
- DSGraph* postOrder(DSSCCGraph& DSG, unsigned scc, svset<unsigned>& marked);
+ DSGraph* postOrder(const Function*,
+ svset<const Function*>& marked);
- void calculateGraph(DSGraph* G, DSSCCGraph& DSG);
+ void calculateGraph(DSGraph* G);
void CloneAuxIntoGlobal(DSGraph* G);
void cloneGlobalsInto(DSGraph* G);
Modified: poolalloc/trunk/include/dsa/svset.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/dsa/svset.h?rev=98781&r1=98780&r2=98781&view=diff
==============================================================================
--- poolalloc/trunk/include/dsa/svset.h (original)
+++ poolalloc/trunk/include/dsa/svset.h Wed Mar 17 19:03:53 2010
@@ -134,6 +134,11 @@
return std::make_pair(i, insertion);
}
+ /// Insert a value into the sorted vector.
+ iterator insert(iterator position, const value_type& x) {
+ return insert(x).first;
+ }
+
/// Insert a range.
template < typename Iterator >
void insert(Iterator _begin, Iterator _end) {
Modified: poolalloc/trunk/lib/DSA/BottomUpClosure.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/BottomUpClosure.cpp?rev=98781&r1=98780&r2=98781&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/BottomUpClosure.cpp (original)
+++ poolalloc/trunk/lib/DSA/BottomUpClosure.cpp Wed Mar 17 19:03:53 2010
@@ -55,25 +55,26 @@
// entry-points correctly. As a bonus, we can be more aggressive at propagating
// information upwards, as long as we don't remove unresolved call sites.
bool BUDataStructures::runOnModuleInternal(Module& M) {
- //Find SCCs and make SCC call graph
- DSSCCGraph DSG(callgraph);
+ llvm::errs() << "BU is currently being worked in in very invasive ways.\n"
+ << "It is probably broken right now\n";
- errs() << "DSNode: " << sizeof(DSNode) << "\nDSCallSite: "
- << sizeof(DSCallSite) << "\n";
+ //Find SCCs and make SCC call graph
+ callgraph.buildSCCs();
+ callgraph.buildRoots();
-// DSG.dump();
+ // callgraph.dump();
//merge SCCs
- mergeSCCs(DSG);
+ mergeSCCs();
//Post order traversal:
{
//errs() << *DSG.knownRoots.begin() << " -> " << *DSG.knownRoots.rbegin() << "\n";
- svset<unsigned> marked;
- for (svset<unsigned>::const_iterator ii = DSG.knownRoots.begin(),
- ee = DSG.knownRoots.end(); ii != ee; ++ii) {
- //errs() << *ii << " ";
- DSGraph* G = postOrder(DSG, *ii, marked);
+ svset<const Function*> marked;
+ for (DSCallGraph::root_iterator ii = callgraph.root_begin(),
+ ee = callgraph.root_end(); ii != ee; ++ii) {
+ errs() << (*ii)->getName() << " ";
+ DSGraph* G = postOrder(*ii, marked);
CloneAuxIntoGlobal(G);
}
}
@@ -164,22 +165,23 @@
return false;
}
-void BUDataStructures::mergeSCCs(DSSCCGraph& DSG) {
+void BUDataStructures::mergeSCCs() {
- for (std::map<unsigned, DSCallGraph::FuncSet>::iterator ii = DSG.SCCs.begin(),
- ee = DSG.SCCs.end(); ii != ee; ++ii) {
+ for (DSCallGraph::flat_key_iterator ii = callgraph.flat_key_begin(),
+ ee = callgraph.flat_key_end(); ii != ee; ++ii) {
+ // Externals can be singleton SCCs
+ if ((*ii)->isDeclaration()) continue;
+ DSGraph* SCCGraph = getOrCreateGraph(*ii);
+ unsigned SCCSize = 1;
+ callgraph.assertSCCRoot(*ii);
- DSGraph* SCCGraph = 0;
- unsigned SCCSize = 0;
- for (DSCallGraph::FuncSet::iterator Fi = ii->second.begin(),
- Fe = ii->second.end(); Fi != Fe; ++Fi) {
+ for (DSCallGraph::scc_iterator Fi = callgraph.scc_begin(*ii),
+ Fe = callgraph.scc_end(*ii); Fi != Fe; ++Fi) {
const Function* F = *Fi;
if (F->isDeclaration()) continue;
+ if (F == *ii) continue;
++SCCSize;
DSGraph* NFG = getOrCreateGraph(F);
- if (!SCCGraph) {
- SCCGraph = NFG;
- }
if (NFG != SCCGraph) {
++NumSCCMerges;
// Update the Function -> DSG map.
@@ -195,17 +197,22 @@
}
}
-DSGraph* BUDataStructures::postOrder(DSSCCGraph& DSG, unsigned scc,
- svset<unsigned>& marked) {
- DSGraph* G = getDSGraph(**DSG.SCCs[scc].begin());
- if (marked.count(scc)) return G;
-
- for(svset<unsigned>::iterator ii = DSG.SCCCallees[scc].begin(),
- ee = DSG.SCCCallees[scc].end(); ii != ee; ++ii)
- postOrder(DSG, *ii, marked);
+DSGraph* BUDataStructures::postOrder(const Function* F,
+ svset<const Function*>& marked) {
+ callgraph.assertSCCRoot(F);
+ DSGraph* G = getDSGraph(*F);
+ if (marked.count(F)) return G;
+
+ for(DSCallGraph::flat_iterator ii = callgraph.flat_callee_begin(F),
+ ee = callgraph.flat_callee_end(F); ii != ee; ++ii) {
+ callgraph.assertSCCRoot(*ii);
+ assert (*ii != F && "Simple loop in callgraph");
+ if (!(*ii)->isDeclaration())
+ postOrder(*ii, marked);
+ }
- marked.insert(scc);
- calculateGraph(G, DSG);
+ marked.insert(F);
+ calculateGraph(G);
return G;
}
@@ -262,7 +269,7 @@
}
}
-void BUDataStructures::calculateGraph(DSGraph* Graph, DSSCCGraph& DSG) {
+void BUDataStructures::calculateGraph(DSGraph* Graph) {
DEBUG(Graph->AssertGraphOK(); Graph->getGlobalsGraph()->AssertGraphOK());
// If this graph contains the main function, clone the globals graph into this
@@ -281,8 +288,8 @@
// Note that this is *required* for correctness. If a callee contains a use
// of a global, we have to make sure to link up nodes due to global-argument
// bindings.
- if (ContainsMain)
- cloneGlobalsInto(Graph);
+// if (ContainsMain)
+// cloneGlobalsInto(Graph);
// Move our call site list into TempFCs so that inline call sites go into the
// new call site list and doesn't invalidate our iterators!
@@ -305,8 +312,8 @@
continue;
}
- std::copy(DSG.oldGraph.callee_begin(CS.getCallSite()),
- DSG.oldGraph.callee_end(CS.getCallSite()),
+ std::copy(callgraph.callee_begin(CS.getCallSite()),
+ callgraph.callee_end(CS.getCallSite()),
std::back_inserter(CalledFuncs));
std::vector<const Function*>::iterator ErasePoint =
Modified: poolalloc/trunk/lib/DSA/CompleteBottomUp.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/CompleteBottomUp.cpp?rev=98781&r1=98780&r2=98781&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/CompleteBottomUp.cpp (original)
+++ poolalloc/trunk/lib/DSA/CompleteBottomUp.cpp Wed Mar 17 19:03:53 2010
@@ -49,7 +49,7 @@
DSGraph::ScalarMapTy& SM = G->getScalarMap();
//mege nodes in the global graph for these functions
- for (DSCallGraph::key_iterator ii = callgraph.key_begin(),
+ for (DSCallGraph::callee_key_iterator ii = callgraph.key_begin(),
ee = callgraph.key_end(); ii != ee; ++ii) {
DSCallGraph::callee_iterator csi = callgraph.callee_begin(*ii),
cse = callgraph.callee_end(*ii);
Modified: poolalloc/trunk/lib/DSA/DataStructure.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/DataStructure.cpp?rev=98781&r1=98780&r2=98781&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/DataStructure.cpp (original)
+++ poolalloc/trunk/lib/DSA/DataStructure.cpp Wed Mar 17 19:03:53 2010
@@ -1268,7 +1268,8 @@
// Empty map so next time memory is released, data structures are not
// re-deleted.
DSInfo.clear();
- callgraph.clear();
+ //FIXME:
+// callgraph.clear();
delete GlobalsGraph;
GlobalsGraph = 0;
}
Modified: poolalloc/trunk/lib/DSA/Local.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/Local.cpp?rev=98781&r1=98780&r2=98781&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/Local.cpp (original)
+++ poolalloc/trunk/lib/DSA/Local.cpp Wed Mar 17 19:03:53 2010
@@ -749,7 +749,14 @@
if (visitAllocation(CS))
return;
+ //Can't do much about inline asm (yet!)
if (isa<InlineAsm>(CS.getCalledValue())) return;
+
+ //uninteresting call
+ if (!DSCallGraph::hasPointers(CS))
+ return;
+
+
// if (InlineAsm* IASM = dyn_cast<InlineAsm>(CS.getCalledValue())) {
// if (IASM->hasSideEffects())
// errs() << ASM w/ Side Effects\n";
More information about the llvm-commits
mailing list