mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-06 06:33:24 +00:00
Many changes
* Simplify a lot of the inlining stuff. There are still problems, but not many * Break up the Function representation to have a vector for every different node type so it is fast to find nodes of a particular flavor. * Do more intelligent merging of call values * Allow elimination of unreachable shadow and allocation nodes * Generalize indistinguishability testing to allow merging of identical calls. * Increase shadow node merging power git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2010 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1d8ec6194a
commit
1120c8b34a
@ -15,119 +15,37 @@
|
||||
#include "llvm/Assembly/Writer.h"
|
||||
#endif
|
||||
|
||||
// copyEdgesFromTo - Make a copy of all of the edges to Node to also point
|
||||
// PV. If there are edges out of Node, the edges are added to the subgraph
|
||||
// starting at PV.
|
||||
// Make all of the pointers that point to Val also point to N.
|
||||
//
|
||||
static void copyEdgesFromTo(DSNode *Node, const PointerValSet &PVS) {
|
||||
// Make all of the pointers that pointed to Node now also point to PV...
|
||||
const vector<PointerValSet*> &PVSToUpdate(Node->getReferrers());
|
||||
static void copyEdgesFromTo(PointerVal Val, DSNode *N) {
|
||||
assert(Val.Index == 0 && "copyEdgesFromTo:index != 0 TODO");
|
||||
|
||||
const vector<PointerValSet*> &PVSToUpdate(Val.Node->getReferrers());
|
||||
for (unsigned i = 0, e = PVSToUpdate.size(); i != e; ++i)
|
||||
for (unsigned pn = 0, pne = PVS.size(); pn != pne; ++pn)
|
||||
PVSToUpdate[i]->add(PVS[pn]);
|
||||
PVSToUpdate[i]->add(N); // TODO: support index
|
||||
}
|
||||
|
||||
static void CalculateNodeMapping(ShadowDSNode *Shadow, DSNode *Node,
|
||||
multimap<ShadowDSNode *, DSNode *> &NodeMapping) {
|
||||
#ifdef DEBUG_IP_CLOSURE
|
||||
cerr << "Mapping " << (void*)Shadow << " to " << (void*)Node << "\n";
|
||||
cerr << "Type = '" << Shadow->getType() << "' and '"
|
||||
<< Node->getType() << "'\n";
|
||||
cerr << "Shadow Node:\n";
|
||||
Shadow->print(cerr);
|
||||
cerr << "\nMapped Node:\n";
|
||||
Node->print(cerr);
|
||||
#endif
|
||||
assert(Shadow->getType() == Node->getType() &&
|
||||
"Shadow and mapped nodes disagree about type!");
|
||||
|
||||
multimap<ShadowDSNode *, DSNode *>::iterator
|
||||
NI = NodeMapping.lower_bound(Shadow),
|
||||
NE = NodeMapping.upper_bound(Shadow);
|
||||
|
||||
for (; NI != NE; ++NI)
|
||||
if (NI->second == Node) return; // Already processed node, return.
|
||||
|
||||
NodeMapping.insert(make_pair(Shadow, Node)); // Add a mapping...
|
||||
|
||||
// Loop over all of the outgoing links in the shadow node...
|
||||
//
|
||||
assert(Node->getNumLinks() == Shadow->getNumLinks() &&
|
||||
"Same type, but different number of links?");
|
||||
for (unsigned i = 0, e = Shadow->getNumLinks(); i != e; ++i) {
|
||||
PointerValSet &Link = Shadow->getLink(i);
|
||||
|
||||
// Loop over all of the values coming out of this pointer...
|
||||
for (unsigned l = 0, le = Link.size(); l != le; ++l) {
|
||||
// If the outgoing node points to a shadow node, map the shadow node to
|
||||
// all of the outgoing values in Node.
|
||||
//
|
||||
if (ShadowDSNode *ShadOut = dyn_cast<ShadowDSNode>(Link[l].Node)) {
|
||||
PointerValSet &NLink = Node->getLink(i);
|
||||
for (unsigned ol = 0, ole = NLink.size(); ol != ole; ++ol)
|
||||
CalculateNodeMapping(ShadOut, NLink[ol].Node, NodeMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ResolveNodesTo(const PointerVal &FromPtr,
|
||||
const PointerValSet &ToVals) {
|
||||
assert(FromPtr.Index == 0 &&
|
||||
"Resolved node return pointer should be index 0!");
|
||||
if (!isa<ShadowDSNode>(FromPtr.Node)) return;
|
||||
|
||||
assert(isa<ShadowDSNode>(FromPtr.Node) &&
|
||||
"Resolved node should be a shadow!");
|
||||
ShadowDSNode *Shadow = cast<ShadowDSNode>(FromPtr.Node);
|
||||
assert(Shadow->isCriticalNode() && "Shadow node should be a critical node!");
|
||||
Shadow->resetCriticalMark();
|
||||
|
||||
typedef multimap<ShadowDSNode *, DSNode *> ShadNodeMapTy;
|
||||
ShadNodeMapTy NodeMapping;
|
||||
for (unsigned i = 0, e = ToVals.size(); i != e; ++i)
|
||||
CalculateNodeMapping(Shadow, ToVals[i].Node, NodeMapping);
|
||||
|
||||
// Now loop through the shadow node graph, mirroring the edges in the shadow
|
||||
// graph onto the realized graph...
|
||||
// Make everything that pointed to the shadow node also point to the values in
|
||||
// ToVals...
|
||||
//
|
||||
for (ShadNodeMapTy::iterator I = NodeMapping.begin(),
|
||||
E = NodeMapping.end(); I != E; ++I) {
|
||||
DSNode *Node = I->second;
|
||||
ShadowDSNode *ShadNode = I->first;
|
||||
PointerValSet PVSx;
|
||||
PVSx.add(Node);
|
||||
copyEdgesFromTo(ShadNode, PVSx);
|
||||
for (unsigned i = 0, e = ToVals.size(); i != e; ++i)
|
||||
copyEdgesFromTo(ToVals[i], Shadow);
|
||||
|
||||
// Must loop over edges in the shadow graph, adding edges in the real graph
|
||||
// that correspond to to the edges, but are mapped into real values by the
|
||||
// NodeMapping.
|
||||
//
|
||||
for (unsigned i = 0, e = Node->getNumLinks(); i != e; ++i) {
|
||||
const PointerValSet &ShadLinks = ShadNode->getLink(i);
|
||||
PointerValSet &NewLinks = Node->getLink(i);
|
||||
|
||||
// Add a link to all of the nodes pointed to by the shadow field...
|
||||
for (unsigned l = 0, le = ShadLinks.size(); l != le; ++l) {
|
||||
DSNode *ShadLink = ShadLinks[l].Node;
|
||||
|
||||
if (ShadowDSNode *SL = dyn_cast<ShadowDSNode>(ShadLink)) {
|
||||
// Loop over all of the values in the range
|
||||
ShadNodeMapTy::iterator St = NodeMapping.lower_bound(SL),
|
||||
En = NodeMapping.upper_bound(SL);
|
||||
if (St != En) {
|
||||
for (; St != En; ++St)
|
||||
NewLinks.add(PointerVal(St->second, ShadLinks[l].Index));
|
||||
} else {
|
||||
// We must retain the shadow node...
|
||||
NewLinks.add(ShadLinks[l]);
|
||||
}
|
||||
} else {
|
||||
// Otherwise, add a direct link to the data structure pointed to by
|
||||
// the shadow node...
|
||||
NewLinks.add(ShadLinks[l]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Make everything that pointed to the shadow node now also point to the
|
||||
// values it is equivalent to...
|
||||
const vector<PointerValSet*> &PVSToUpdate(Shadow->getReferrers());
|
||||
for (unsigned i = 0, e = PVSToUpdate.size(); i != e; ++i)
|
||||
PVSToUpdate[i]->add(ToVals);
|
||||
}
|
||||
|
||||
|
||||
@ -137,20 +55,21 @@ static void ResolveNodesTo(const PointerVal &FromPtr,
|
||||
static void ResolveNodeTo(DSNode *Node, const PointerValSet &ToVals) {
|
||||
assert(Node->getNumLinks() == 1 && "Resolved node can only be a scalar!!");
|
||||
|
||||
PointerValSet PVS = Node->getLink(0);
|
||||
const PointerValSet &PVS = Node->getLink(0);
|
||||
|
||||
for (unsigned i = 0, e = PVS.size(); i != e; ++i)
|
||||
ResolveNodesTo(PVS[i], ToVals);
|
||||
// Only resolve the first pointer, although there many be many pointers here.
|
||||
// The problem is that the inlined function might return one of the arguments
|
||||
// to the function, and if so, extra values can be added to the arg or call
|
||||
// node that point to what the other one got resolved to. Since these will
|
||||
// be added to the end of the PVS pointed in, we just ignore them.
|
||||
//
|
||||
ResolveNodesTo(PVS[0], ToVals);
|
||||
}
|
||||
|
||||
// isResolvableCallNode - Return true if node is a call node and it is a call
|
||||
// node that we can inline...
|
||||
//
|
||||
static bool isResolvableCallNode(DSNode *N) {
|
||||
// Only operate on call nodes...
|
||||
CallDSNode *CN = dyn_cast<CallDSNode>(N);
|
||||
if (CN == 0) return false;
|
||||
|
||||
static bool isResolvableCallNode(CallDSNode *CN) {
|
||||
// Only operate on call nodes with direct method calls
|
||||
Function *F = CN->getCall()->getCalledFunction();
|
||||
if (F == 0) return false;
|
||||
@ -164,35 +83,42 @@ static bool isResolvableCallNode(DSNode *N) {
|
||||
// of their corresponding method data structure graph...
|
||||
//
|
||||
void FunctionDSGraph::computeClosure(const DataStructure &DS) {
|
||||
vector<DSNode*>::iterator NI = std::find_if(Nodes.begin(), Nodes.end(),
|
||||
isResolvableCallNode);
|
||||
typedef pair<vector<PointerValSet>, CallInst *> CallDescriptor;
|
||||
map<CallDescriptor, PointerValSet> CallMap;
|
||||
|
||||
map<Function*, unsigned> InlineCount; // FIXME
|
||||
unsigned NumInlines = 0;
|
||||
|
||||
// Loop over the resolvable call nodes...
|
||||
while (NI != Nodes.end()) {
|
||||
CallDSNode *CN = cast<CallDSNode>(*NI);
|
||||
vector<CallDSNode*>::iterator NI;
|
||||
NI = std::find_if(CallNodes.begin(), CallNodes.end(), isResolvableCallNode);
|
||||
while (NI != CallNodes.end()) {
|
||||
CallDSNode *CN = *NI;
|
||||
Function *F = CN->getCall()->getCalledFunction();
|
||||
//if (F == Func) return; // Do not do self inlining
|
||||
|
||||
// FIXME: Gross hack to prevent explosions when inlining a recursive func.
|
||||
if (InlineCount[F]++ > 2) return;
|
||||
if (NumInlines++ == 30) { // CUTE hack huh?
|
||||
cerr << "Infinite (?) recursion halted\n";
|
||||
return;
|
||||
}
|
||||
|
||||
Nodes.erase(NI); // Remove the call node from the graph
|
||||
CallNodes.erase(NI); // Remove the call node from the graph
|
||||
|
||||
unsigned CallNodeOffset = NI-Nodes.begin();
|
||||
unsigned CallNodeOffset = NI-CallNodes.begin();
|
||||
|
||||
// StartNode - The first node of the incorporated graph, last node of the
|
||||
// preexisting data structure graph...
|
||||
// Find out if we have already incorporated this node... if so, it will be
|
||||
// in the CallMap...
|
||||
//
|
||||
unsigned StartNode = Nodes.size();
|
||||
CallDescriptor FDesc(CN->getArgs(), CN->getCall());
|
||||
map<CallDescriptor, PointerValSet>::iterator CMI = CallMap.find(FDesc);
|
||||
|
||||
// Hold the set of values that correspond to the incorporated methods
|
||||
// return set.
|
||||
//
|
||||
PointerValSet RetVals;
|
||||
|
||||
if (F != Func) { // If this is not a recursive call...
|
||||
if (CMI != CallMap.end()) {
|
||||
// We have already inlined an identical function call!
|
||||
RetVals = CMI->second;
|
||||
} else {
|
||||
// Get the datastructure graph for the new method. Note that we are not
|
||||
// allowed to modify this graph because it will be the cached graph that
|
||||
// is returned by other users that want the local datastructure graph for
|
||||
@ -200,23 +126,58 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
|
||||
//
|
||||
const FunctionDSGraph &NewFunction = DS.getDSGraph(F);
|
||||
|
||||
unsigned StartShadowNodes = ShadowNodes.size();
|
||||
// StartNode - The first node of the incorporated graph, last node of the
|
||||
// preexisting data structure graph...
|
||||
//
|
||||
unsigned StartArgNode = ArgNodes.size();
|
||||
unsigned StartAllocNode = AllocNodes.size();
|
||||
|
||||
// Incorporate a copy of the called function graph into the current graph,
|
||||
// allowing us to do local transformations to local graph to link
|
||||
// arguments to call values, and call node to return value...
|
||||
//
|
||||
RetVals = cloneFunctionIntoSelf(NewFunction, false);
|
||||
RetVals = cloneFunctionIntoSelf(NewFunction, F == Func);
|
||||
CallMap[FDesc] = RetVals;
|
||||
|
||||
// Only detail is that we need to reset all of the critical shadow nodes
|
||||
// in the incorporated graph, because they are now no longer critical.
|
||||
// If the call node has arguments, process them now!
|
||||
if (CN->getNumArgs()) {
|
||||
// The ArgNodes of the incorporated graph should be the nodes starting
|
||||
// at StartNode, ordered the same way as the call arguments. The arg
|
||||
// nodes are seperated by a single shadow node, but that shadow node
|
||||
// might get eliminated in the process of optimization.
|
||||
//
|
||||
for (unsigned i = 0, e = CN->getNumArgs(); i != e; ++i) {
|
||||
// Get the arg node of the incorporated method...
|
||||
ArgDSNode *ArgNode = ArgNodes[StartArgNode];
|
||||
|
||||
// Now we make all of the nodes inside of the incorporated method
|
||||
// point to the real arguments values, not to the shadow nodes for the
|
||||
// argument.
|
||||
//
|
||||
ResolveNodeTo(ArgNode, CN->getArgValues(i));
|
||||
|
||||
// Remove the argnode from the set of nodes in this method...
|
||||
ArgNodes.erase(ArgNodes.begin()+StartArgNode);
|
||||
|
||||
// ArgNode is no longer useful, delete now!
|
||||
delete ArgNode;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through the nodes, deleting alloca nodes in the inlined function.
|
||||
// Since the memory has been released, we cannot access their pointer
|
||||
// fields (with defined results at least), so it is not possible to use
|
||||
// any pointers to the alloca. Drop them now, and remove the alloca's
|
||||
// since they are dead (we just removed all links to them).
|
||||
//
|
||||
for (unsigned i = StartShadowNodes, e = ShadowNodes.size(); i != e; ++i)
|
||||
ShadowNodes[i]->resetCriticalMark();
|
||||
|
||||
} else { // We are looking at a recursive function!
|
||||
StartNode = 0; // Arg nodes start at 0 now...
|
||||
RetVals = RetNode;
|
||||
for (unsigned i = StartAllocNode; i != AllocNodes.size(); ++i)
|
||||
if (AllocNodes[i]->isAllocaNode()) {
|
||||
AllocDSNode *NDS = AllocNodes[i];
|
||||
NDS->removeAllIncomingEdges(); // These edges are invalid now
|
||||
delete NDS; // Node is dead
|
||||
AllocNodes.erase(AllocNodes.begin()+i); // Remove slot in Nodes array
|
||||
--i; // Don't skip the next node
|
||||
}
|
||||
}
|
||||
|
||||
// If the function returns a pointer value... Resolve values pointing to
|
||||
@ -224,56 +185,6 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
|
||||
//
|
||||
if (CN->getNumLinks()) ResolveNodeTo(CN, RetVals);
|
||||
|
||||
// If the call node has arguments, process them now!
|
||||
if (CN->getNumArgs()) {
|
||||
// The ArgNodes of the incorporated graph should be the nodes starting at
|
||||
// StartNode, ordered the same way as the call arguments. The arg nodes
|
||||
// are seperated by a single shadow node, but that shadow node might get
|
||||
// eliminated in the process of optimization.
|
||||
//
|
||||
unsigned ArgOffset = StartNode;
|
||||
for (unsigned i = 0, e = CN->getNumArgs(); i != e; ++i) {
|
||||
// Get the arg node of the incorporated method...
|
||||
while (!isa<ArgDSNode>(Nodes[ArgOffset])) // Scan for next arg node
|
||||
ArgOffset++;
|
||||
ArgDSNode *ArgNode = cast<ArgDSNode>(Nodes[ArgOffset]);
|
||||
|
||||
// Now we make all of the nodes inside of the incorporated method point
|
||||
// to the real arguments values, not to the shadow nodes for the
|
||||
// argument.
|
||||
//
|
||||
ResolveNodeTo(ArgNode, CN->getArgValues(i));
|
||||
|
||||
if (StartNode) { // Not Self recursion?
|
||||
// Remove the argnode from the set of nodes in this method...
|
||||
Nodes.erase(Nodes.begin()+ArgOffset);
|
||||
|
||||
// ArgNode is no longer useful, delete now!
|
||||
delete ArgNode;
|
||||
} else {
|
||||
ArgOffset++; // Step to the next argument...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through the nodes, deleting alloc nodes in the inlined function...
|
||||
// Since the memory has been released, we cannot access their pointer
|
||||
// fields (with defined results at least), so it is not possible to use any
|
||||
// pointers to the alloca. Drop them now, and remove the alloca's since
|
||||
// they are dead (we just removed all links to them). Only do this if we
|
||||
// are not self recursing though. :)
|
||||
//
|
||||
if (StartNode) // Don't do this if self recursing...
|
||||
for (unsigned i = StartNode; i != Nodes.size(); ++i)
|
||||
if (NewDSNode *NDS = dyn_cast<NewDSNode>(Nodes[i]))
|
||||
if (NDS->isAllocaNode()) {
|
||||
NDS->removeAllIncomingEdges(); // These edges are invalid now!
|
||||
delete NDS; // Node is dead
|
||||
Nodes.erase(Nodes.begin()+i); // Remove slot in Nodes array
|
||||
--i; // Don't skip the next node
|
||||
}
|
||||
|
||||
|
||||
// Now the call node is completely destructable. Eliminate it now.
|
||||
delete CN;
|
||||
|
||||
@ -291,6 +202,6 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
|
||||
//if (F == Func) return; // Only do one self inlining
|
||||
|
||||
// Move on to the next call node...
|
||||
NI = std::find_if(Nodes.begin(), Nodes.end(), isResolvableCallNode);
|
||||
NI = std::find_if(CallNodes.begin(), CallNodes.end(), isResolvableCallNode);
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +90,28 @@ const PointerValSet &PointerValSet::operator=(const PointerValSet &PVS) {
|
||||
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
|
||||
|
||||
vector<PointerVal> S1(Vals), S2(PVS.Vals);
|
||||
sort(S1.begin(), S1.end());
|
||||
sort(S2.begin(), S2.end());
|
||||
return S1 < S2;
|
||||
}
|
||||
|
||||
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...
|
||||
|
||||
vector<PointerVal> S1(Vals), S2(PVS.Vals);
|
||||
sort(S1.begin(), S1.end());
|
||||
sort(S2.begin(), S2.end());
|
||||
return S1 == S2;
|
||||
}
|
||||
|
||||
|
||||
bool PointerValSet::add(const PointerVal &PV, Value *Pointer) {
|
||||
if (std::find(Vals.begin(), Vals.end(), PV) != Vals.end())
|
||||
|
@ -21,157 +21,216 @@
|
||||
|
||||
//#define DEBUG_NODE_ELIMINATE 1
|
||||
|
||||
bool AllocDSNode::isEquivalentTo(DSNode *Node) const {
|
||||
if (AllocDSNode *N = dyn_cast<AllocDSNode>(Node))
|
||||
return N->Allocation == Allocation;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GlobalDSNode::isEquivalentTo(DSNode *Node) const {
|
||||
if (GlobalDSNode *G = dyn_cast<GlobalDSNode>(Node))
|
||||
return G->Val == Val;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CallDSNode::isEquivalentTo(DSNode *Node) const {
|
||||
if (CallDSNode *C = dyn_cast<CallDSNode>(Node))
|
||||
return C->CI == CI && C->ArgLinks == ArgLinks;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ArgDSNode::isEquivalentTo(DSNode *Node) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// NodesAreEquivalent - Check to see if the nodes are equivalent in all ways
|
||||
// except node type. Since we know N1 is a shadow node, N2 is allowed to be
|
||||
// any type.
|
||||
//
|
||||
static bool NodesAreEquivalent(const ShadowDSNode *N1, const DSNode *N2) {
|
||||
assert(N1 != N2 && "A node is always equivalent to itself!");
|
||||
|
||||
// Perform simple, fast checks first...
|
||||
if (N1->getType() != N2->getType() || // Must have same type...
|
||||
N1->isCriticalNode()) // Must not be a critical node...
|
||||
return false;
|
||||
|
||||
#if 0
|
||||
return true;
|
||||
#else
|
||||
|
||||
// The shadow node is considered equivalent if it has a subset of the incoming
|
||||
// edges that N2 does...
|
||||
if (N1->getReferrers().size() > N2->getReferrers().size()) return false;
|
||||
|
||||
// Check to see if the referring (incoming) pointers are all the same...
|
||||
std::vector<PointerValSet*> N1R = N1->getReferrers();
|
||||
std::vector<PointerValSet*> N2R = N2->getReferrers();
|
||||
sort(N1R.begin(), N1R.end());
|
||||
sort(N2R.begin(), N2R.end());
|
||||
|
||||
// The nodes are equivalent if the incoming edges to N1 are a subset of N2.
|
||||
unsigned i1 = 0, e1 = N1R.size();
|
||||
unsigned i2 = 0, e2 = N2R.size();
|
||||
for (; i1 != e1 && i2 < e2; ++i1, ++i2) {
|
||||
while (N1R[i1] > N2R[i2] && i2 < e2)
|
||||
++i2;
|
||||
|
||||
if (N1R[i1] < N2R[i2]) return false; // Error case...
|
||||
}
|
||||
|
||||
return i1 == e1 && i2 <= e2;
|
||||
#endif
|
||||
bool ShadowDSNode::isEquivalentTo(DSNode *Node) const {
|
||||
return !isCriticalNode(); // Must not be a critical node...
|
||||
}
|
||||
|
||||
// IndistinguishableShadowNode - A shadow node is indistinguishable if some
|
||||
// other node (shadow or otherwise) has exactly the same incoming and outgoing
|
||||
// links to it (or if there are no edges coming in, in which it is trivially
|
||||
// dead).
|
||||
|
||||
|
||||
// isIndistinguishableNode - A node is indistinguishable if some other node
|
||||
// has exactly the same incoming links to it and if the node considers itself
|
||||
// to be the same as the other node...
|
||||
//
|
||||
static bool IndistinguishableShadowNode(const ShadowDSNode *SN) {
|
||||
if (SN->getReferrers().empty()) return true; // Node is trivially dead
|
||||
|
||||
bool isIndistinguishableNode(DSNode *DN) {
|
||||
if (DN->getReferrers().empty()) { // No referrers...
|
||||
if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN))
|
||||
return true; // Node is trivially dead
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pick a random referrer... Ptr is the things that the referrer points to.
|
||||
// Since SN is in the Ptr set, look through the set seeing if there are any
|
||||
// other nodes that are exactly equilivant to SN (with the exception of node
|
||||
// type), but are not SN. If anything exists, then SN is indistinguishable.
|
||||
// Since DN is in the Ptr set, look through the set seeing if there are any
|
||||
// other nodes that are exactly equilivant to DN (with the exception of node
|
||||
// type), but are not DN. If anything exists, then DN is indistinguishable.
|
||||
//
|
||||
const PointerValSet &Ptr = *SN->getReferrers()[0];
|
||||
const std::vector<PointerValSet*> &Refs = DN->getReferrers();
|
||||
for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
|
||||
const PointerValSet &Ptr = *Refs[R];
|
||||
|
||||
for (unsigned i = 0, e = Ptr.size(); i != e; ++i)
|
||||
if (Ptr[i].Index == 0 && Ptr[i].Node != cast<DSNode>(SN) &&
|
||||
NodesAreEquivalent(SN, Ptr[i].Node))
|
||||
return true;
|
||||
for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
|
||||
DSNode *N2 = Ptr[i].Node;
|
||||
if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
|
||||
DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {
|
||||
|
||||
// Otherwise, the nodes can be merged. Make sure that N2 contains all
|
||||
// of the outgoing edges (fields) that DN does...
|
||||
//
|
||||
assert(DN->getNumLinks() == N2->getNumLinks() &&
|
||||
"Same type, diff # fields?");
|
||||
for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
|
||||
N2->getLink(i).add(DN->getLink(i));
|
||||
|
||||
// Now make sure that all of the nodes that point to the shadow node
|
||||
// also point to the node that we are merging it with...
|
||||
//
|
||||
const std::vector<PointerValSet*> &Refs = DN->getReferrers();
|
||||
for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
|
||||
PointerValSet &PVS = *Refs[i];
|
||||
// FIXME: this is incorrect if the referring pointer has index != 0
|
||||
//
|
||||
PVS.add(N2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, nothing found, perhaps next time....
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename NodeTy>
|
||||
bool removeIndistinguishableNode(std::vector<NodeTy*> &Nodes) {
|
||||
bool Changed = false;
|
||||
std::vector<NodeTy*>::iterator I = Nodes.begin();
|
||||
while (I != Nodes.end()) {
|
||||
if (isIndistinguishableNode(*I)) {
|
||||
#ifdef DEBUG_NODE_ELIMINATE
|
||||
cerr << "Found Indistinguishable Node:\n";
|
||||
(*I)->print(cerr);
|
||||
#endif
|
||||
(*I)->removeAllIncomingEdges();
|
||||
delete *I;
|
||||
I = Nodes.erase(I);
|
||||
Changed = true;
|
||||
} else {
|
||||
++I;
|
||||
}
|
||||
}
|
||||
return Changed;
|
||||
}
|
||||
|
||||
// UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not
|
||||
// distinguishable from some other node in the graph...
|
||||
//
|
||||
bool FunctionDSGraph::UnlinkUndistinguishableShadowNodes() {
|
||||
bool Changed = false;
|
||||
// Loop over all of the shadow nodes, checking to see if they are
|
||||
// indistinguishable from some other node. If so, eliminate the node!
|
||||
//
|
||||
for (vector<ShadowDSNode*>::iterator I = ShadowNodes.begin();
|
||||
I != ShadowNodes.end(); )
|
||||
if (IndistinguishableShadowNode(*I)) {
|
||||
#ifdef DEBUG_NODE_ELIMINATE
|
||||
cerr << "Found Indistinguishable Shadow Node:\n";
|
||||
(*I)->print(cerr);
|
||||
#endif
|
||||
(*I)->removeAllIncomingEdges();
|
||||
// Don't need to dropAllRefs, because nothing can point to it now
|
||||
delete *I;
|
||||
|
||||
I = ShadowNodes.erase(I);
|
||||
Changed = true;
|
||||
} else {
|
||||
++I;
|
||||
}
|
||||
return Changed;
|
||||
return
|
||||
removeIndistinguishableNode(AllocNodes) |
|
||||
removeIndistinguishableNode(ShadowNodes) |
|
||||
removeIndistinguishableNode(GlobalNodes);
|
||||
}
|
||||
|
||||
static void MarkReferredNodesReachable(DSNode *N, vector<ShadowDSNode*> &Nodes,
|
||||
vector<bool> &Reachable);
|
||||
static void MarkReferredNodesReachable(DSNode *N,
|
||||
vector<ShadowDSNode*> &ShadowNodes,
|
||||
vector<bool> &ReachableShadowNodes,
|
||||
vector<AllocDSNode*> &AllocNodes,
|
||||
vector<bool> &ReachableAllocNodes);
|
||||
|
||||
static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
|
||||
vector<ShadowDSNode*> &Nodes,
|
||||
vector<bool> &Reachable) {
|
||||
vector<ShadowDSNode*> &ShadowNodes,
|
||||
vector<bool> &ReachableShadowNodes,
|
||||
vector<AllocDSNode*> &AllocNodes,
|
||||
vector<bool> &ReachableAllocNodes) {
|
||||
for (unsigned i = 0, e = PVS.size(); i != e; ++i)
|
||||
if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(PVS[i].Node))
|
||||
MarkReferredNodesReachable(Shad, Nodes, Reachable);
|
||||
if (isa<ShadowDSNode>(PVS[i].Node) || isa<ShadowDSNode>(PVS[i].Node))
|
||||
MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes,
|
||||
AllocNodes, ReachableAllocNodes);
|
||||
}
|
||||
|
||||
static void MarkReferredNodesReachable(DSNode *N, vector<ShadowDSNode*> &Nodes,
|
||||
vector<bool> &Reachable) {
|
||||
assert(Nodes.size() == Reachable.size());
|
||||
ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N);
|
||||
static void MarkReferredNodesReachable(DSNode *N,
|
||||
vector<ShadowDSNode*> &ShadowNodes,
|
||||
vector<bool> &ReachableShadowNodes,
|
||||
vector<AllocDSNode*> &AllocNodes,
|
||||
vector<bool> &ReachableAllocNodes) {
|
||||
assert(ShadowNodes.size() == ReachableShadowNodes.size());
|
||||
assert(AllocNodes.size() == ReachableAllocNodes.size());
|
||||
|
||||
if (Shad) {
|
||||
if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N)) {
|
||||
vector<ShadowDSNode*>::iterator I =
|
||||
std::find(Nodes.begin(), Nodes.end(), Shad);
|
||||
unsigned i = I-Nodes.begin();
|
||||
if (Reachable[i]) return; // Recursion detected, abort...
|
||||
Reachable[i] = true;
|
||||
std::find(ShadowNodes.begin(), ShadowNodes.end(), Shad);
|
||||
unsigned i = I-ShadowNodes.begin();
|
||||
if (ReachableShadowNodes[i]) return; // Recursion detected, abort...
|
||||
ReachableShadowNodes[i] = true;
|
||||
} else if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(N)) {
|
||||
vector<AllocDSNode*>::iterator I =
|
||||
std::find(AllocNodes.begin(), AllocNodes.end(), Alloc);
|
||||
unsigned i = I-AllocNodes.begin();
|
||||
if (ReachableAllocNodes[i]) return; // Recursion detected, abort...
|
||||
ReachableAllocNodes[i] = true;
|
||||
}
|
||||
|
||||
for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
|
||||
MarkReferredNodeSetReachable(N->getLink(i), Nodes, Reachable);
|
||||
MarkReferredNodeSetReachable(N->getLink(i),
|
||||
ShadowNodes, ReachableShadowNodes,
|
||||
AllocNodes, ReachableAllocNodes);
|
||||
|
||||
const std::vector<PointerValSet> *Links = N->getAuxLinks();
|
||||
if (Links)
|
||||
for (unsigned i = 0, e = Links->size(); i != e; ++i)
|
||||
MarkReferredNodeSetReachable((*Links)[i], Nodes, Reachable);
|
||||
MarkReferredNodeSetReachable((*Links)[i],
|
||||
ShadowNodes, ReachableShadowNodes,
|
||||
AllocNodes, ReachableAllocNodes);
|
||||
}
|
||||
|
||||
bool FunctionDSGraph::RemoveUnreachableShadowNodes() {
|
||||
bool Changed = false;
|
||||
while (1) {
|
||||
|
||||
// Reachable - Contains true if there is an edge from a nonshadow node to
|
||||
// the numbered node...
|
||||
// Reachable*Nodes - Contains true if there is an edge from a reachable
|
||||
// node to the numbered node...
|
||||
//
|
||||
vector<bool> Reachable(ShadowNodes.size());
|
||||
vector<bool> ReachableShadowNodes(ShadowNodes.size());
|
||||
vector<bool> ReachableAllocNodes (AllocNodes.size());
|
||||
|
||||
// Mark all shadow nodes that have edges from other nodes as reachable.
|
||||
// Recursively mark any shadow nodes pointed to by the newly live shadow
|
||||
// nodes as also alive.
|
||||
//
|
||||
for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
|
||||
// Loop over all of the nodes referred and mark them live if they are
|
||||
// shadow nodes...
|
||||
MarkReferredNodesReachable(Nodes[i], ShadowNodes, Reachable);
|
||||
for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
|
||||
MarkReferredNodesReachable(ArgNodes[i],
|
||||
ShadowNodes, ReachableShadowNodes,
|
||||
AllocNodes, ReachableAllocNodes);
|
||||
|
||||
for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
|
||||
MarkReferredNodesReachable(GlobalNodes[i],
|
||||
ShadowNodes, ReachableShadowNodes,
|
||||
AllocNodes, ReachableAllocNodes);
|
||||
|
||||
for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
|
||||
MarkReferredNodesReachable(CallNodes[i],
|
||||
ShadowNodes, ReachableShadowNodes,
|
||||
AllocNodes, ReachableAllocNodes);
|
||||
|
||||
// Mark all nodes in the return set as being reachable...
|
||||
MarkReferredNodeSetReachable(RetNode, ShadowNodes, Reachable);
|
||||
MarkReferredNodeSetReachable(RetNode,
|
||||
ShadowNodes, ReachableShadowNodes,
|
||||
AllocNodes, ReachableAllocNodes);
|
||||
|
||||
// Mark all nodes in the value map as being reachable...
|
||||
for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
|
||||
E = ValueMap.end(); I != E; ++I)
|
||||
MarkReferredNodeSetReachable(I->second, ShadowNodes, Reachable);
|
||||
|
||||
MarkReferredNodeSetReachable(I->second,
|
||||
ShadowNodes, ReachableShadowNodes,
|
||||
AllocNodes, ReachableAllocNodes);
|
||||
|
||||
// At this point, all reachable shadow nodes have a true value in the
|
||||
// Reachable vector. This means that any shadow nodes without an entry in
|
||||
@ -179,26 +238,43 @@ bool FunctionDSGraph::RemoveUnreachableShadowNodes() {
|
||||
// a two part process, because we must drop all references before we delete
|
||||
// the shadow nodes [in case cycles exist].
|
||||
//
|
||||
vector<ShadowDSNode*> DeadNodes;
|
||||
bool LocalChange = false;
|
||||
for (unsigned i = 0; i != ShadowNodes.size(); ++i)
|
||||
if (!Reachable[i]) {
|
||||
if (!ReachableShadowNodes[i]) {
|
||||
// Track all unreachable nodes...
|
||||
#if DEBUG_NODE_ELIMINATE
|
||||
cerr << "Unreachable node eliminated:\n";
|
||||
ShadowNodes[i]->print(cerr);
|
||||
#endif
|
||||
DeadNodes.push_back(ShadowNodes[i]);
|
||||
ShadowNodes[i]->dropAllReferences(); // Drop references to other nodes
|
||||
Reachable.erase(Reachable.begin()+i); // Remove from reachable...
|
||||
ShadowNodes[i]->removeAllIncomingEdges();
|
||||
delete ShadowNodes[i];
|
||||
|
||||
// Remove from reachable...
|
||||
ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
|
||||
ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry
|
||||
--i; // Don't skip the next node.
|
||||
LocalChange = true;
|
||||
}
|
||||
|
||||
if (DeadNodes.empty()) return Changed; // No more dead nodes...
|
||||
for (unsigned i = 0; i != AllocNodes.size(); ++i)
|
||||
if (!ReachableAllocNodes[i]) {
|
||||
// Track all unreachable nodes...
|
||||
#if DEBUG_NODE_ELIMINATE
|
||||
cerr << "Unreachable node eliminated:\n";
|
||||
AllocNodes[i]->print(cerr);
|
||||
#endif
|
||||
AllocNodes[i]->removeAllIncomingEdges();
|
||||
delete AllocNodes[i];
|
||||
|
||||
// Remove from reachable...
|
||||
ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
|
||||
AllocNodes.erase(AllocNodes.begin()+i); // Remove node entry
|
||||
--i; // Don't skip the next node.
|
||||
LocalChange = true;
|
||||
}
|
||||
|
||||
if (!LocalChange) return Changed; // No more dead nodes...
|
||||
|
||||
Changed = true;
|
||||
|
||||
// All dead nodes are in the DeadNodes vector... delete them now.
|
||||
for_each(DeadNodes.begin(), DeadNodes.end(), deleter<DSNode>);
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ void InitVisitor::visitOperand(Value *V) {
|
||||
if (!Rep->ValueMap.count(V)) // Only process it once...
|
||||
if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
|
||||
GlobalDSNode *N = new GlobalDSNode(GV);
|
||||
Rep->Nodes.push_back(N);
|
||||
Rep->GlobalNodes.push_back(N);
|
||||
Rep->ValueMap[V].add(N);
|
||||
Rep->addAllUsesToWorkList(GV);
|
||||
|
||||
@ -60,7 +60,7 @@ void InitVisitor::visitOperand(Value *V) {
|
||||
//
|
||||
void InitVisitor::visitCallInst(CallInst *CI) {
|
||||
CallDSNode *C = new CallDSNode(CI);
|
||||
Rep->Nodes.push_back(C);
|
||||
Rep->CallNodes.push_back(C);
|
||||
Rep->CallMap[CI] = C;
|
||||
|
||||
if (isa<PointerType>(CI->getType())) {
|
||||
@ -95,8 +95,8 @@ void InitVisitor::visitCallInst(CallInst *CI) {
|
||||
// global vars...
|
||||
//
|
||||
void InitVisitor::visitAllocationInst(AllocationInst *AI) {
|
||||
NewDSNode *N = new NewDSNode(AI);
|
||||
Rep->Nodes.push_back(N);
|
||||
AllocDSNode *N = new AllocDSNode(AI);
|
||||
Rep->AllocNodes.push_back(N);
|
||||
|
||||
Rep->ValueMap[AI].add(N, AI);
|
||||
|
||||
@ -144,7 +144,7 @@ void FunctionRepBuilder::initializeWorkList(Function *Func) {
|
||||
// Only process arguments that are of pointer type...
|
||||
if (isa<PointerType>((*I)->getType())) {
|
||||
ArgDSNode *Arg = new ArgDSNode(*I);
|
||||
Nodes.push_back(Arg);
|
||||
ArgNodes.push_back(Arg);
|
||||
|
||||
// Add a critical shadow value for it to represent what it is pointing
|
||||
// to and add this to the value map...
|
||||
@ -326,10 +326,13 @@ void FunctionRepBuilder::visitPHINode(PHINode *PN) {
|
||||
//
|
||||
FunctionDSGraph::FunctionDSGraph(Function *F) : Func(F) {
|
||||
FunctionRepBuilder Builder(this);
|
||||
Nodes = Builder.getNodes();
|
||||
ArgNodes = Builder.getArgNodes();
|
||||
AllocNodes = Builder.getAllocNodes();
|
||||
ShadowNodes = Builder.getShadowNodes();
|
||||
RetNode = Builder.getRetNode();
|
||||
ValueMap = Builder.getValueMap();
|
||||
GlobalNodes = Builder.getGlobalNodes();
|
||||
CallNodes = Builder.getCallNodes();
|
||||
RetNode = Builder.getRetNode();
|
||||
ValueMap = Builder.getValueMap();
|
||||
|
||||
bool Changed = true;
|
||||
while (Changed) {
|
||||
|
@ -61,8 +61,11 @@ class FunctionRepBuilder : InstVisitor<FunctionRepBuilder> {
|
||||
// Nodes - Keep track of all of the resultant nodes, because there may not
|
||||
// be edges connecting these to anything.
|
||||
//
|
||||
std::vector<DSNode*> Nodes;
|
||||
std::vector<ArgDSNode*> ArgNodes;
|
||||
std::vector<AllocDSNode*> AllocNodes;
|
||||
std::vector<ShadowDSNode*> ShadowNodes;
|
||||
std::vector<GlobalDSNode*> GlobalNodes;
|
||||
std::vector<CallDSNode*> CallNodes;
|
||||
|
||||
// addAllUsesToWorkList - Add all of the instructions users of the specified
|
||||
// value to the work list for further processing...
|
||||
@ -75,11 +78,13 @@ public:
|
||||
processWorkList();
|
||||
}
|
||||
|
||||
void addNode(DSNode *N) { Nodes.push_back(N); }
|
||||
const std::vector<DSNode*> &getNodes() const { return Nodes; }
|
||||
|
||||
void addShadowNode(ShadowDSNode *N) { ShadowNodes.push_back(N); }
|
||||
const std::vector<ArgDSNode*> &getArgNodes() const { return ArgNodes; }
|
||||
const std::vector<AllocDSNode*> &getAllocNodes() const { return AllocNodes; }
|
||||
const std::vector<ShadowDSNode*> &getShadowNodes() const {return ShadowNodes;}
|
||||
const std::vector<GlobalDSNode*> &getGlobalNodes() const {return GlobalNodes;}
|
||||
const std::vector<CallDSNode*> &getCallNodes() const { return CallNodes; }
|
||||
|
||||
void addShadowNode(ShadowDSNode *SN) { ShadowNodes.push_back(SN); }
|
||||
|
||||
const PointerValSet &getRetNode() const { return RetNode; }
|
||||
|
||||
|
@ -20,8 +20,8 @@
|
||||
//
|
||||
|
||||
static void MapPVS(PointerValSet &PVSOut, const PointerValSet &PVSIn,
|
||||
map<const DSNode*, DSNode*> &NodeMap) {
|
||||
assert(PVSOut.empty() && "Value set already initialized!");
|
||||
map<const DSNode*, DSNode*> &NodeMap, bool ReinitOk = false){
|
||||
assert((ReinitOk || PVSOut.empty()) && "Value set already initialized!");
|
||||
|
||||
for (unsigned i = 0, e = PVSIn.size(); i != e; ++i)
|
||||
PVSOut.add(PointerVal(NodeMap[PVSIn[i].Node], PVSIn[i].Index));
|
||||
@ -148,16 +148,16 @@ void DSNode::mapNode(map<const DSNode*, DSNode*> &NodeMap, const DSNode *Old) {
|
||||
MapPVS(FieldLinks[j], Old->FieldLinks[j], NodeMap);
|
||||
}
|
||||
|
||||
NewDSNode::NewDSNode(AllocationInst *V)
|
||||
AllocDSNode::AllocDSNode(AllocationInst *V)
|
||||
: DSNode(NewNode, V->getType()->getElementType()), Allocation(V) {
|
||||
}
|
||||
|
||||
bool NewDSNode::isAllocaNode() const {
|
||||
bool AllocDSNode::isAllocaNode() const {
|
||||
return isa<AllocaInst>(Allocation);
|
||||
}
|
||||
|
||||
|
||||
string NewDSNode::getCaption() const {
|
||||
string AllocDSNode::getCaption() const {
|
||||
stringstream OS;
|
||||
OS << (isMallocNode() ? "new " : "alloca ");
|
||||
|
||||
@ -175,7 +175,7 @@ GlobalDSNode::GlobalDSNode(GlobalValue *V)
|
||||
string GlobalDSNode::getCaption() const {
|
||||
stringstream OS;
|
||||
WriteTypeSymbolic(OS, getType(), Val->getParent());
|
||||
return "global " + OS.str();
|
||||
return "global " + OS.str() + " %" + Val->getName();
|
||||
}
|
||||
|
||||
|
||||
@ -243,7 +243,7 @@ string CallDSNode::getCaption() const {
|
||||
|
||||
void CallDSNode::mapNode(map<const DSNode*, DSNode*> &NodeMap,
|
||||
const DSNode *O) {
|
||||
const CallDSNode *Old = (CallDSNode*)O;
|
||||
const CallDSNode *Old = cast<CallDSNode>(O);
|
||||
DSNode::mapNode(NodeMap, Old); // Map base portions first...
|
||||
|
||||
assert(ArgLinks.size() == Old->ArgLinks.size() && "# Arguments changed!?");
|
||||
@ -266,10 +266,16 @@ void FunctionDSGraph::printFunction(std::ostream &O,
|
||||
const char *Label) const {
|
||||
O << "\tsubgraph cluster_" << Label << "_Function" << (void*)this << " {\n";
|
||||
O << "\t\tlabel=\"" << Label << " Function\\ " << Func->getName() << "\";\n";
|
||||
for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
|
||||
Nodes[i]->print(O);
|
||||
for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
|
||||
ArgNodes[i]->print(O);
|
||||
for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
|
||||
AllocNodes[i]->print(O);
|
||||
for (unsigned i = 0, e = ShadowNodes.size(); i != e; ++i)
|
||||
ShadowNodes[i]->print(O);
|
||||
for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
|
||||
GlobalNodes[i]->print(O);
|
||||
for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
|
||||
CallNodes[i]->print(O);
|
||||
|
||||
if (RetNode.size()) {
|
||||
O << "\t\tNode" << (void*)this << Label
|
||||
@ -315,14 +321,30 @@ FunctionDSGraph::FunctionDSGraph(const FunctionDSGraph &DSG) : Func(DSG.Func) {
|
||||
PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG,
|
||||
bool CloneValueMap) {
|
||||
map<const DSNode*, DSNode*> NodeMap; // Map from old graph to new graph...
|
||||
unsigned StartSize = Nodes.size(); // We probably already have nodes...
|
||||
Nodes.reserve(StartSize+DSG.Nodes.size());
|
||||
unsigned StartArgSize = ArgNodes.size();
|
||||
ArgNodes.reserve(StartArgSize+DSG.ArgNodes.size());
|
||||
unsigned StartAllocSize = AllocNodes.size();
|
||||
AllocNodes.reserve(StartAllocSize+DSG.AllocNodes.size());
|
||||
unsigned StartShadowSize = ShadowNodes.size();
|
||||
ShadowNodes.reserve(StartShadowSize+DSG.ShadowNodes.size());
|
||||
unsigned StartGlobalSize = GlobalNodes.size();
|
||||
GlobalNodes.reserve(StartGlobalSize+DSG.GlobalNodes.size());
|
||||
unsigned StartCallSize = CallNodes.size();
|
||||
CallNodes.reserve(StartCallSize+DSG.CallNodes.size());
|
||||
|
||||
// Clone all of the nodes, keeping track of the mapping...
|
||||
for (unsigned i = 0, e = DSG.Nodes.size(); i != e; ++i)
|
||||
Nodes.push_back(NodeMap[DSG.Nodes[i]] = DSG.Nodes[i]->clone());
|
||||
// Clone all of the arg nodes...
|
||||
for (unsigned i = 0, e = DSG.ArgNodes.size(); i != e; ++i) {
|
||||
ArgDSNode *New = cast<ArgDSNode>(DSG.ArgNodes[i]->clone());
|
||||
NodeMap[DSG.ArgNodes[i]] = New;
|
||||
ArgNodes.push_back(New);
|
||||
}
|
||||
|
||||
// Clone all of the alloc nodes similarly...
|
||||
for (unsigned i = 0, e = DSG.AllocNodes.size(); i != e; ++i) {
|
||||
AllocDSNode *New = cast<AllocDSNode>(DSG.AllocNodes[i]->clone());
|
||||
NodeMap[DSG.AllocNodes[i]] = New;
|
||||
AllocNodes.push_back(New);
|
||||
}
|
||||
|
||||
// Clone all of the shadow nodes similarly...
|
||||
for (unsigned i = 0, e = DSG.ShadowNodes.size(); i != e; ++i) {
|
||||
@ -331,14 +353,34 @@ PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG,
|
||||
ShadowNodes.push_back(New);
|
||||
}
|
||||
|
||||
// Clone all of the global nodes...
|
||||
for (unsigned i = 0, e = DSG.GlobalNodes.size(); i != e; ++i) {
|
||||
GlobalDSNode *New = cast<GlobalDSNode>(DSG.GlobalNodes[i]->clone());
|
||||
NodeMap[DSG.GlobalNodes[i]] = New;
|
||||
GlobalNodes.push_back(New);
|
||||
}
|
||||
|
||||
// Clone all of the call nodes...
|
||||
for (unsigned i = 0, e = DSG.CallNodes.size(); i != e; ++i) {
|
||||
CallDSNode *New = cast<CallDSNode>(DSG.CallNodes[i]->clone());
|
||||
NodeMap[DSG.CallNodes[i]] = New;
|
||||
CallNodes.push_back(New);
|
||||
}
|
||||
|
||||
// Convert all of the links over in the nodes now that the map has been filled
|
||||
// in all the way...
|
||||
//
|
||||
for (unsigned i = 0, e = DSG.Nodes.size(); i != e; ++i)
|
||||
Nodes[i+StartSize]->mapNode(NodeMap, DSG.Nodes[i]);
|
||||
|
||||
for (unsigned i = 0, e = DSG.ArgNodes.size(); i != e; ++i)
|
||||
ArgNodes[i+StartArgSize]->mapNode(NodeMap, DSG.ArgNodes[i]);
|
||||
for (unsigned i = 0, e = DSG.AllocNodes.size(); i != e; ++i)
|
||||
AllocNodes[i+StartAllocSize]->mapNode(NodeMap, DSG.AllocNodes[i]);
|
||||
for (unsigned i = 0, e = DSG.ShadowNodes.size(); i != e; ++i)
|
||||
ShadowNodes[i+StartShadowSize]->mapNode(NodeMap, DSG.ShadowNodes[i]);
|
||||
for (unsigned i = 0, e = DSG.GlobalNodes.size(); i != e; ++i)
|
||||
GlobalNodes[i+StartGlobalSize]->mapNode(NodeMap, DSG.GlobalNodes[i]);
|
||||
for (unsigned i = 0, e = DSG.CallNodes.size(); i != e; ++i)
|
||||
CallNodes[i+StartCallSize]->mapNode(NodeMap, DSG.CallNodes[i]);
|
||||
|
||||
|
||||
if (CloneValueMap) {
|
||||
// Convert value map... the values themselves stay the same, just the nodes
|
||||
@ -346,7 +388,7 @@ PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG,
|
||||
//
|
||||
for (std::map<Value*,PointerValSet>::const_iterator I =DSG.ValueMap.begin(),
|
||||
E = DSG.ValueMap.end(); I != E; ++I)
|
||||
MapPVS(ValueMap[I->first], I->second, NodeMap);
|
||||
MapPVS(ValueMap[I->first], I->second, NodeMap, true);
|
||||
}
|
||||
|
||||
// Convert over return node...
|
||||
@ -359,10 +401,20 @@ PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG,
|
||||
FunctionDSGraph::~FunctionDSGraph() {
|
||||
RetNode.clear();
|
||||
ValueMap.clear();
|
||||
for_each(Nodes.begin(), Nodes.end(), mem_fun(&DSNode::dropAllReferences));
|
||||
for_each(ArgNodes.begin(), ArgNodes.end(),
|
||||
mem_fun(&DSNode::dropAllReferences));
|
||||
for_each(AllocNodes.begin(), AllocNodes.end(),
|
||||
mem_fun(&DSNode::dropAllReferences));
|
||||
for_each(ShadowNodes.begin(), ShadowNodes.end(),
|
||||
mem_fun(&DSNode::dropAllReferences));
|
||||
for_each(Nodes.begin(), Nodes.end(), deleter<DSNode>);
|
||||
for_each(GlobalNodes.begin(), GlobalNodes.end(),
|
||||
mem_fun(&DSNode::dropAllReferences));
|
||||
for_each(CallNodes.begin(), CallNodes.end(),
|
||||
mem_fun(&DSNode::dropAllReferences));
|
||||
for_each(ArgNodes.begin(), ArgNodes.end(), deleter<DSNode>);
|
||||
for_each(AllocNodes.begin(), AllocNodes.end(), deleter<DSNode>);
|
||||
for_each(ShadowNodes.begin(), ShadowNodes.end(), deleter<DSNode>);
|
||||
for_each(GlobalNodes.begin(), GlobalNodes.end(), deleter<DSNode>);
|
||||
for_each(CallNodes.begin(), CallNodes.end(), deleter<DSNode>);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user