From: Chris Lattner Date: Thu, 28 Mar 2002 17:56:03 +0000 (+0000) Subject: Many changes X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=1120c8b34ada1f7ce103f617a0dfa4526bf9e207;p=oota-llvm.git 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 --- diff --git a/lib/Analysis/DataStructure/ComputeClosure.cpp b/lib/Analysis/DataStructure/ComputeClosure.cpp index 9fd7d607e14..1f15b681abc 100644 --- a/lib/Analysis/DataStructure/ComputeClosure.cpp +++ b/lib/Analysis/DataStructure/ComputeClosure.cpp @@ -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 &PVSToUpdate(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]); -} - -static void CalculateNodeMapping(ShadowDSNode *Shadow, DSNode *Node, - multimap &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::iterator - NI = NodeMapping.lower_bound(Shadow), - NE = NodeMapping.upper_bound(Shadow); - - for (; NI != NE; ++NI) - if (NI->second == Node) return; // Already processed node, return. +static void copyEdgesFromTo(PointerVal Val, DSNode *N) { + assert(Val.Index == 0 && "copyEdgesFromTo:index != 0 TODO"); - 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(Link[l].Node)) { - PointerValSet &NLink = Node->getLink(i); - for (unsigned ol = 0, ole = NLink.size(); ol != ole; ++ol) - CalculateNodeMapping(ShadOut, NLink[ol].Node, NodeMapping); - } - } - } + const vector &PVSToUpdate(Val.Node->getReferrers()); + for (unsigned i = 0, e = PVSToUpdate.size(); i != e; ++i) + PVSToUpdate[i]->add(N); // TODO: support index } - static void ResolveNodesTo(const PointerVal &FromPtr, const PointerValSet &ToVals) { assert(FromPtr.Index == 0 && "Resolved node return pointer should be index 0!"); - if (!isa(FromPtr.Node)) return; - + assert(isa(FromPtr.Node) && + "Resolved node should be a shadow!"); ShadowDSNode *Shadow = cast(FromPtr.Node); + assert(Shadow->isCriticalNode() && "Shadow node should be a critical node!"); Shadow->resetCriticalMark(); - typedef multimap ShadNodeMapTy; - ShadNodeMapTy NodeMapping; + // Make everything that pointed to the shadow node also point to the values in + // ToVals... + // for (unsigned i = 0, e = ToVals.size(); i != e; ++i) - CalculateNodeMapping(Shadow, ToVals[i].Node, NodeMapping); + copyEdgesFromTo(ToVals[i], Shadow); - // Now loop through the shadow node graph, mirroring the edges in the shadow - // graph onto the realized graph... - // - 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); - - // 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(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 &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(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::iterator NI = std::find_if(Nodes.begin(), Nodes.end(), - isResolvableCallNode); + typedef pair, CallInst *> CallDescriptor; + map CallMap; - map InlineCount; // FIXME + unsigned NumInlines = 0; // Loop over the resolvable call nodes... - while (NI != Nodes.end()) { - CallDSNode *CN = cast(*NI); + vector::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::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,79 +126,64 @@ 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); - - // 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. - // - 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; - } - - // If the function returns a pointer value... Resolve values pointing to - // the shadow nodes pointed to by CN to now point the values in RetVals... - // - 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(Nodes[ArgOffset])) // Scan for next arg node - ArgOffset++; - ArgDSNode *ArgNode = cast(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. + RetVals = cloneFunctionIntoSelf(NewFunction, F == Func); + CallMap[FDesc] = 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. // - ResolveNodeTo(ArgNode, CN->getArgValues(i)); - - if (StartNode) { // Not Self recursion? + 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... - Nodes.erase(Nodes.begin()+ArgOffset); - + ArgNodes.erase(ArgNodes.begin()+StartArgNode); + // ArgNode is no longer useful, delete now! delete ArgNode; - } else { - ArgOffset++; // Step to the next argument... } } + + // 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 = 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 + } } - // 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 the function returns a pointer value... Resolve values pointing to + // the shadow nodes pointed to by CN to now point the values in RetVals... // - if (StartNode) // Don't do this if self recursing... - for (unsigned i = StartNode; i != Nodes.size(); ++i) - if (NewDSNode *NDS = dyn_cast(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 - } - + if (CN->getNumLinks()) ResolveNodeTo(CN, RetVals); // 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); } } diff --git a/lib/Analysis/DataStructure/DataStructure.cpp b/lib/Analysis/DataStructure/DataStructure.cpp index d90d84a06b5..13d3dce174c 100644 --- a/lib/Analysis/DataStructure/DataStructure.cpp +++ b/lib/Analysis/DataStructure/DataStructure.cpp @@ -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 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 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()) diff --git a/lib/Analysis/DataStructure/EliminateNodes.cpp b/lib/Analysis/DataStructure/EliminateNodes.cpp index 3d1319dcf23..ca82ed1cd92 100644 --- a/lib/Analysis/DataStructure/EliminateNodes.cpp +++ b/lib/Analysis/DataStructure/EliminateNodes.cpp @@ -21,157 +21,216 @@ //#define DEBUG_NODE_ELIMINATE 1 +bool AllocDSNode::isEquivalentTo(DSNode *Node) const { + if (AllocDSNode *N = dyn_cast(Node)) + return N->Allocation == Allocation; + return false; +} + +bool GlobalDSNode::isEquivalentTo(DSNode *Node) const { + if (GlobalDSNode *G = dyn_cast(Node)) + return G->Val == Val; + return false; +} + +bool CallDSNode::isEquivalentTo(DSNode *Node) const { + if (CallDSNode *C = dyn_cast(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 N1R = N1->getReferrers(); - std::vector 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). -// -static bool IndistinguishableShadowNode(const ShadowDSNode *SN) { - if (SN->getReferrers().empty()) return true; // Node 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... +// +bool isIndistinguishableNode(DSNode *DN) { + if (DN->getReferrers().empty()) { // No referrers... + if (isa(DN) || isa(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]; - - for (unsigned i = 0, e = Ptr.size(); i != e; ++i) - if (Ptr[i].Index == 0 && Ptr[i].Node != cast(SN) && - NodesAreEquivalent(SN, Ptr[i].Node)) - return true; + const std::vector &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) { + DSNode *N2 = Ptr[i].Node; + if (Ptr[i].Index == 0 && N2 != cast(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 &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; } - -// UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not -// distinguishable from some other node in the graph... -// -bool FunctionDSGraph::UnlinkUndistinguishableShadowNodes() { +template +bool removeIndistinguishableNode(std::vector &Nodes) { 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::iterator I = ShadowNodes.begin(); - I != ShadowNodes.end(); ) - if (IndistinguishableShadowNode(*I)) { + std::vector::iterator I = Nodes.begin(); + while (I != Nodes.end()) { + if (isIndistinguishableNode(*I)) { #ifdef DEBUG_NODE_ELIMINATE - cerr << "Found Indistinguishable Shadow Node:\n"; + cerr << "Found Indistinguishable 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); + I = Nodes.erase(I); Changed = true; } else { ++I; } + } return Changed; } -static void MarkReferredNodesReachable(DSNode *N, vector &Nodes, - vector &Reachable); +// UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not +// distinguishable from some other node in the graph... +// +bool FunctionDSGraph::UnlinkUndistinguishableShadowNodes() { + // Loop over all of the shadow nodes, checking to see if they are + // indistinguishable from some other node. If so, eliminate the node! + // + return + removeIndistinguishableNode(AllocNodes) | + removeIndistinguishableNode(ShadowNodes) | + removeIndistinguishableNode(GlobalNodes); +} + +static void MarkReferredNodesReachable(DSNode *N, + vector &ShadowNodes, + vector &ReachableShadowNodes, + vector &AllocNodes, + vector &ReachableAllocNodes); static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS, - vector &Nodes, - vector &Reachable) { + vector &ShadowNodes, + vector &ReachableShadowNodes, + vector &AllocNodes, + vector &ReachableAllocNodes) { for (unsigned i = 0, e = PVS.size(); i != e; ++i) - if (ShadowDSNode *Shad = dyn_cast(PVS[i].Node)) - MarkReferredNodesReachable(Shad, Nodes, Reachable); + if (isa(PVS[i].Node) || isa(PVS[i].Node)) + MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes, + AllocNodes, ReachableAllocNodes); } -static void MarkReferredNodesReachable(DSNode *N, vector &Nodes, - vector &Reachable) { - assert(Nodes.size() == Reachable.size()); - ShadowDSNode *Shad = dyn_cast(N); +static void MarkReferredNodesReachable(DSNode *N, + vector &ShadowNodes, + vector &ReachableShadowNodes, + vector &AllocNodes, + vector &ReachableAllocNodes) { + assert(ShadowNodes.size() == ReachableShadowNodes.size()); + assert(AllocNodes.size() == ReachableAllocNodes.size()); - if (Shad) { + if (ShadowDSNode *Shad = dyn_cast(N)) { vector::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(N)) { + vector::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 *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 Reachable(ShadowNodes.size()); + vector ReachableShadowNodes(ShadowNodes.size()); + vector 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::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 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]; - Changed = true; + // 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... - // All dead nodes are in the DeadNodes vector... delete them now. - for_each(DeadNodes.begin(), DeadNodes.end(), deleter); + Changed = true; } } diff --git a/lib/Analysis/DataStructure/FunctionRepBuilder.cpp b/lib/Analysis/DataStructure/FunctionRepBuilder.cpp index e2544c82dcf..87d4a332ced 100644 --- a/lib/Analysis/DataStructure/FunctionRepBuilder.cpp +++ b/lib/Analysis/DataStructure/FunctionRepBuilder.cpp @@ -44,7 +44,7 @@ void InitVisitor::visitOperand(Value *V) { if (!Rep->ValueMap.count(V)) // Only process it once... if (GlobalValue *GV = dyn_cast(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(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((*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) { diff --git a/lib/Analysis/DataStructure/FunctionRepBuilder.h b/lib/Analysis/DataStructure/FunctionRepBuilder.h index 6809261b90c..bc561342f2d 100644 --- a/lib/Analysis/DataStructure/FunctionRepBuilder.h +++ b/lib/Analysis/DataStructure/FunctionRepBuilder.h @@ -61,8 +61,11 @@ class FunctionRepBuilder : InstVisitor { // Nodes - Keep track of all of the resultant nodes, because there may not // be edges connecting these to anything. // - std::vector Nodes; + std::vector ArgNodes; + std::vector AllocNodes; std::vector ShadowNodes; + std::vector GlobalNodes; + std::vector 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 &getNodes() const { return Nodes; } - - void addShadowNode(ShadowDSNode *N) { ShadowNodes.push_back(N); } + 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;} + const std::vector &getCallNodes() const { return CallNodes; } + + void addShadowNode(ShadowDSNode *SN) { ShadowNodes.push_back(SN); } const PointerValSet &getRetNode() const { return RetNode; } diff --git a/lib/Analysis/DataStructure/NodeImpl.cpp b/lib/Analysis/DataStructure/NodeImpl.cpp index 967c67eea0f..b8fabf8a747 100644 --- a/lib/Analysis/DataStructure/NodeImpl.cpp +++ b/lib/Analysis/DataStructure/NodeImpl.cpp @@ -20,8 +20,8 @@ // static void MapPVS(PointerValSet &PVSOut, const PointerValSet &PVSIn, - map &NodeMap) { - assert(PVSOut.empty() && "Value set already initialized!"); + map &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 &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(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 &NodeMap, const DSNode *O) { - const CallDSNode *Old = (CallDSNode*)O; + const CallDSNode *Old = cast(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 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 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 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 alloc nodes similarly... + for (unsigned i = 0, e = DSG.AllocNodes.size(); i != e; ++i) { + AllocDSNode *New = cast(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(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(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::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); + 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); + for_each(AllocNodes.begin(), AllocNodes.end(), deleter); for_each(ShadowNodes.begin(), ShadowNodes.end(), deleter); + for_each(GlobalNodes.begin(), GlobalNodes.end(), deleter); + for_each(CallNodes.begin(), CallNodes.end(), deleter); }