diff --git a/lib/Analysis/DataStructure/ComputeClosure.cpp b/lib/Analysis/DataStructure/ComputeClosure.cpp index 671fb9219b1..30c21a33227 100644 --- a/lib/Analysis/DataStructure/ComputeClosure.cpp +++ b/lib/Analysis/DataStructure/ComputeClosure.cpp @@ -31,8 +31,17 @@ static void copyEdgesFromTo(PointerVal Val, DSNode *N) { } } -static void ResolveNodesTo(const PointerVal &FromPtr, +static void ResolveNodesTo(const PointerValSet &FromVals, const PointerValSet &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. + // + assert(!FromVals.empty() && "From should have at least a shadow node!"); + const PointerVal &FromPtr = FromVals[0]; + assert(FromPtr.Index == 0 && "Resolved node return pointer should be index 0!"); DSNode *N = FromPtr.Node; @@ -58,14 +67,7 @@ static void ResolveNodeTo(DSNode *Node, const PointerValSet &ToVals) { assert(Node->getNumLinks() == 1 && "Resolved node can only be a scalar!!"); const PointerValSet &PVS = Node->getLink(0); - - // 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); + ResolveNodesTo(PVS, ToVals); } // isResolvableCallNode - Return true if node is a call node and it is a call @@ -167,40 +169,26 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) { // 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); + vector Args; + RetVals = cloneFunctionIntoSelf(NewFunction, false, Args); CallMap.push_back(make_pair(CallDescriptor(CN->getArgs(), CN->getCall()), 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. - // - 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; - } + assert(Args.size() == CN->getNumArgs() && + "Call node doesn't match function?"); + + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + // 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. + ResolveNodesTo(Args[i], CN->getArgValues(i)); } // Loop through the nodes, deleting alloca nodes in the inlined function. diff --git a/lib/Analysis/DataStructure/EliminateNodes.cpp b/lib/Analysis/DataStructure/EliminateNodes.cpp index 767f7fe006d..6b22f69617d 100644 --- a/lib/Analysis/DataStructure/EliminateNodes.cpp +++ b/lib/Analysis/DataStructure/EliminateNodes.cpp @@ -250,11 +250,6 @@ void FunctionDSGraph::MarkEscapeableNodesReachable( // Recursively mark any shadow nodes pointed to by the newly live shadow // nodes as also alive. // - 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, @@ -273,8 +268,10 @@ void FunctionDSGraph::MarkEscapeableNodesReachable( bool FunctionDSGraph::RemoveUnreachableNodes() { bool Changed = false; - - while (1) { + bool LocalChange = true; + + while (LocalChange) { + LocalChange = false; // Reachable*Nodes - Contains true if there is an edge from a reachable // node to the numbered node... // @@ -296,7 +293,6 @@ bool FunctionDSGraph::RemoveUnreachableNodes() { // a two part process, because we must drop all references before we delete // the shadow nodes [in case cycles exist]. // - bool LocalChange = false; for (unsigned i = 0; i != ShadowNodes.size(); ++i) if (!ReachableShadowNodes[i]) { // Track all unreachable nodes... @@ -311,7 +307,7 @@ bool FunctionDSGraph::RemoveUnreachableNodes() { ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i); ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry --i; // Don't skip the next node. - LocalChange = true; + LocalChange = Changed = true; } for (unsigned i = 0; i != AllocNodes.size(); ++i) @@ -328,13 +324,22 @@ bool FunctionDSGraph::RemoveUnreachableNodes() { ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i); AllocNodes.erase(AllocNodes.begin()+i); // Remove node entry --i; // Don't skip the next node. - LocalChange = true; + LocalChange = Changed = true; } - - if (!LocalChange) return Changed; // No more dead nodes... - - Changed = true; } + + // Loop over the global nodes, removing nodes that have no edges into them. + // + for (std::vector::iterator I = GlobalNodes.begin(); + I != GlobalNodes.end(); ) + if ((*I)->getReferrers().empty()) { // No referrers... + delete *I; + I = GlobalNodes.erase(I); // Remove the node... + Changed = true; + } else { + ++I; + } + return Changed; } diff --git a/lib/Analysis/DataStructure/FunctionRepBuilder.cpp b/lib/Analysis/DataStructure/FunctionRepBuilder.cpp index eda16bc6949..2afede5dfa0 100644 --- a/lib/Analysis/DataStructure/FunctionRepBuilder.cpp +++ b/lib/Analysis/DataStructure/FunctionRepBuilder.cpp @@ -147,19 +147,13 @@ void FunctionRepBuilder::initializeWorkList(Function *Func) { Value *Arg = (Value*)(*I); // Only process arguments that are of pointer type... if (PointerType *PT = dyn_cast(Arg->getType())) { - ArgDSNode *ArgNode = new ArgDSNode(*I); - ArgNodes.push_back(ArgNode); - - // Add a critical shadow value for it to represent what it is pointing - // to and add this to the value map... + // Add a shadow value for it to represent what it is pointing to and add + // this to the value map... ShadowDSNode *Shad = new ShadowDSNode(PT->getElementType(), Func->getParent(), true); ShadowNodes.push_back(Shad); ValueMap[Arg].add(PointerVal(Shad), Arg); - // The value of the argument is the shadow value... - ArgNode->getLink(0).add(Shad); - // Make sure that all users of the argument are processed... addAllUsesToWorkList(Arg); } @@ -332,7 +326,6 @@ void FunctionRepBuilder::visitPHINode(PHINode *PN) { // FunctionDSGraph::FunctionDSGraph(Function *F) : Func(F) { FunctionRepBuilder Builder(this); - ArgNodes = Builder.getArgNodes(); AllocNodes = Builder.getAllocNodes(); ShadowNodes = Builder.getShadowNodes(); GlobalNodes = Builder.getGlobalNodes(); @@ -351,4 +344,3 @@ FunctionDSGraph::FunctionDSGraph(Function *F) : Func(F) { Changed |= RemoveUnreachableNodes(); } } - diff --git a/lib/Analysis/DataStructure/FunctionRepBuilder.h b/lib/Analysis/DataStructure/FunctionRepBuilder.h index 9523a563021..54bfbba86df 100644 --- a/lib/Analysis/DataStructure/FunctionRepBuilder.h +++ b/lib/Analysis/DataStructure/FunctionRepBuilder.h @@ -61,7 +61,6 @@ class FunctionRepBuilder : InstVisitor { // Nodes - Keep track of all of the resultant nodes, because there may not // be edges connecting these to anything. // - std::vector ArgNodes; std::vector AllocNodes; std::vector ShadowNodes; std::vector GlobalNodes; @@ -78,7 +77,6 @@ public: processWorkList(); } - const std::vector &getArgNodes() const { return ArgNodes; } const std::vector &getAllocNodes() const { return AllocNodes; } const std::vector &getShadowNodes() const {return ShadowNodes;} const std::vector &getGlobalNodes() const {return GlobalNodes;} diff --git a/lib/Analysis/DataStructure/NodeImpl.cpp b/lib/Analysis/DataStructure/NodeImpl.cpp index 6c986fe1db7..47a7dc28e65 100644 --- a/lib/Analysis/DataStructure/NodeImpl.cpp +++ b/lib/Analysis/DataStructure/NodeImpl.cpp @@ -11,7 +11,6 @@ #include "llvm/BasicBlock.h" #include "llvm/iMemory.h" #include "llvm/iOther.h" -#include "llvm/Argument.h" #include "Support/STLExtras.h" #include #include @@ -19,25 +18,49 @@ bool AllocDSNode::isEquivalentTo(DSNode *Node) const { if (AllocDSNode *N = dyn_cast(Node)) return getType() == Node->getType(); -// return N->Allocation == Allocation; return false; } bool GlobalDSNode::isEquivalentTo(DSNode *Node) const { - if (GlobalDSNode *G = dyn_cast(Node)) - return G->Val == Val; + if (GlobalDSNode *G = dyn_cast(Node)) { + if (G->Val != Val) return false; + + // Check that the outgoing links are identical... + assert(getNumLinks() == G->getNumLinks() && "Not identical shape?"); + for (unsigned i = 0, e = getNumLinks(); i != e; ++i) + if (getLink(i) != G->getLink(i)) // Check links + return false; + return true; + } return false; } +// Call node equivalency - Two call nodes are identical if all of the outgoing +// links are the same, AND if all of the incoming links are identical. +// bool CallDSNode::isEquivalentTo(DSNode *Node) const { - return false; - if (CallDSNode *C = dyn_cast(Node)) - return C->CI->getCalledFunction() == CI->getCalledFunction() && - C->ArgLinks == ArgLinks; - return false; -} + if (CallDSNode *C = dyn_cast(Node)) { + if (C->CI->getCalledFunction() != CI->getCalledFunction() || + getReferrers().size() != C->getReferrers().size()) + return false; // Quick check... -bool ArgDSNode::isEquivalentTo(DSNode *Node) const { + // Check that the outgoing links are identical... + assert(getNumLinks() == C->getNumLinks() && "Not identical shape?"); + for (unsigned i = 0, e = getNumLinks(); i != e; ++i) + if (getLink(i) != C->getLink(i)) // Check links + return false; + + + std::vector Refs1 = C->getReferrers(); + std::vector Refs2 = getReferrers(); + + sort(Refs1.begin(), Refs1.end()); + sort(Refs2.begin(), Refs2.end()); + if (Refs1 != Refs2) return false; // Incoming edges different? + + // Check that all outgoing links are the same... + return C->ArgLinks == ArgLinks; // Check that the arguments are identical + } return false; } @@ -289,23 +312,10 @@ void CallDSNode::mapNode(map &NodeMap, MapPVS(ArgLinks[i], Old->ArgLinks[i], NodeMap); } -ArgDSNode::ArgDSNode(Argument *FA) - : DSNode(ArgNode, FA->getType()), FuncArg(FA) { -} - -string ArgDSNode::getCaption() const { - stringstream OS; - OS << "arg %" << FuncArg->getName() << "|Ty: "; - WriteTypeSymbolic(OS, getType(), FuncArg->getParent()->getParent()); - return OS.str(); -} - 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 = 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) @@ -347,20 +357,21 @@ void FunctionDSGraph::printFunction(std::ostream &O, // graph... // FunctionDSGraph::FunctionDSGraph(const FunctionDSGraph &DSG) : Func(DSG.Func) { - RetNode = cloneFunctionIntoSelf(DSG, true); + vector Args; + RetNode = cloneFunctionIntoSelf(DSG, true, Args); } // cloneFunctionIntoSelf - Clone the specified method graph into the current // method graph, returning the Return's set of the graph. If ValueMap is set // to true, the ValueMap of the function is cloned into this function as well -// as the data structure graph itself. +// as the data structure graph itself. Regardless, the arguments value sets +// of DSG are copied into Args. // PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG, - bool CloneValueMap) { + bool CloneValueMap, + vector &Args) { map NodeMap; // Map from old graph to new graph... - unsigned StartArgSize = ArgNodes.size(); - ArgNodes.reserve(StartArgSize+DSG.ArgNodes.size()); unsigned StartAllocSize = AllocNodes.size(); AllocNodes.reserve(StartAllocSize+DSG.AllocNodes.size()); unsigned StartShadowSize = ShadowNodes.size(); @@ -370,13 +381,6 @@ PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG, unsigned StartCallSize = CallNodes.size(); CallNodes.reserve(StartCallSize+DSG.CallNodes.size()); - // Clone all of the arg nodes... - for (unsigned i = 0, e = DSG.ArgNodes.size(); i != e; ++i) { - ArgDSNode *New = cast(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(DSG.AllocNodes[i]->clone()); @@ -408,8 +412,6 @@ PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG, // 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.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) @@ -419,6 +421,18 @@ PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG, for (unsigned i = 0, e = DSG.CallNodes.size(); i != e; ++i) CallNodes[i+StartCallSize]->mapNode(NodeMap, DSG.CallNodes[i]); + // Convert over the arguments... + Function *OF = DSG.getFunction(); + for (Function::ArgumentListType::iterator I = OF->getArgumentList().begin(), + E = OF->getArgumentList().end(); I != E; ++I) + if (isa(((Value*)*I)->getType())) { + PointerValSet ArgPVS; + assert(DSG.getValueMap().find((Value*)*I) != DSG.getValueMap().end()); + MapPVS(ArgPVS, DSG.getValueMap().find((Value*)*I)->second, NodeMap); + assert(!ArgPVS.empty() && "Argument has no links!"); + Args.push_back(ArgPVS); + } + if (CloneValueMap) { // Convert value map... the values themselves stay the same, just the nodes @@ -439,8 +453,6 @@ PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG, FunctionDSGraph::~FunctionDSGraph() { RetNode.clear(); ValueMap.clear(); - 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(), @@ -449,7 +461,6 @@ FunctionDSGraph::~FunctionDSGraph() { mem_fun(&DSNode::dropAllReferences)); for_each(CallNodes.begin(), CallNodes.end(), mem_fun(&DSNode::dropAllReferences)); - for_each(ArgNodes.begin(), ArgNodes.end(), deleter); for_each(AllocNodes.begin(), AllocNodes.end(), deleter); for_each(ShadowNodes.begin(), ShadowNodes.end(), deleter); for_each(GlobalNodes.begin(), GlobalNodes.end(), deleter);