Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame^] | 1 | //===- ShadowNodeEliminate.cpp - Optimize away shadow nodes ---------------===// |
| 2 | // |
| 3 | // This file contains two shadow node optimizations: |
| 4 | // 1. UnlinkUndistinguishableShadowNodes - Often, after unification, shadow |
| 5 | // nodes are left around that should not exist anymore. An example is when |
| 6 | // a shadow gets unified with a 'new' node, the following graph gets |
| 7 | // generated: %X -> Shadow, %X -> New. Since all of the edges to the |
| 8 | // shadow node also all go to the New node, we can eliminate the shadow. |
| 9 | // |
| 10 | // 2. RemoveUnreachableShadowNodes - Remove shadow nodes that are not |
| 11 | // reachable from some other node in the graph. Unreachable shadow nodes |
| 12 | // are left lying around because other transforms don't go to the trouble |
| 13 | // or removing them, since this pass exists. |
| 14 | // |
| 15 | //===----------------------------------------------------------------------===// |
| 16 | |
| 17 | #include "llvm/Analysis/DataStructure.h" |
| 18 | #include "llvm/Value.h" |
| 19 | #include "Support/STLExtras.h" |
| 20 | #include <algorithm> |
| 21 | |
| 22 | // removeEdgesTo - Erase all edges in the graph that point to the specified node |
| 23 | static void removeEdgesTo(DSNode *Node) { |
| 24 | while (!Node->getReferrers().empty()) { |
| 25 | PointerValSet *PVS = Node->getReferrers().back(); |
| 26 | PVS->removePointerTo(Node); |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | // UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not |
| 31 | // distinguishable from some other node in the graph... |
| 32 | // |
| 33 | void FunctionDSGraph::UnlinkUndistinguishableShadowNodes() { |
| 34 | // TODO: |
| 35 | } |
| 36 | |
| 37 | |
| 38 | |
| 39 | |
| 40 | |
| 41 | |
| 42 | static void MarkReferredNodesReachable(DSNode *N, vector<ShadowDSNode*> &Nodes, |
| 43 | vector<bool> &Reachable); |
| 44 | |
| 45 | static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS, |
| 46 | vector<ShadowDSNode*> &Nodes, |
| 47 | vector<bool> &Reachable) { |
| 48 | for (unsigned i = 0, e = PVS.size(); i != e; ++i) |
| 49 | if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(PVS[i].Node)) |
| 50 | MarkReferredNodesReachable(Shad, Nodes, Reachable); |
| 51 | } |
| 52 | |
| 53 | static void MarkReferredNodesReachable(DSNode *N, vector<ShadowDSNode*> &Nodes, |
| 54 | vector<bool> &Reachable) { |
| 55 | assert(Nodes.size() == Reachable.size()); |
| 56 | ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N); |
| 57 | |
| 58 | if (Shad) { |
| 59 | vector<ShadowDSNode*>::iterator I = |
| 60 | std::find(Nodes.begin(), Nodes.end(), Shad); |
| 61 | unsigned i = I-Nodes.begin(); |
| 62 | if (Reachable[i]) return; // Recursion detected, abort... |
| 63 | Reachable[i] = true; |
| 64 | } |
| 65 | |
| 66 | for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i) |
| 67 | MarkReferredNodeSetReachable(N->getLink(i), Nodes, Reachable); |
| 68 | |
| 69 | const std::vector<PointerValSet> *Links = N->getAuxLinks(); |
| 70 | if (Links) |
| 71 | for (unsigned i = 0, e = Links->size(); i != e; ++i) |
| 72 | MarkReferredNodeSetReachable((*Links)[i], Nodes, Reachable); |
| 73 | } |
| 74 | |
| 75 | void FunctionDSGraph::RemoveUnreachableShadowNodes() { |
| 76 | while (1) { |
| 77 | |
| 78 | // Reachable - Contains true if there is an edge from a nonshadow node to |
| 79 | // the numbered node... |
| 80 | // |
| 81 | vector<bool> Reachable(ShadowNodes.size()); |
| 82 | |
| 83 | // Mark all shadow nodes that have edges from other nodes as reachable. |
| 84 | // Recursively mark any shadow nodes pointed to by the newly live shadow |
| 85 | // nodes as also alive. |
| 86 | // |
| 87 | for (unsigned i = 0, e = Nodes.size(); i != e; ++i) |
| 88 | // Loop over all of the nodes referred and mark them live if they are |
| 89 | // shadow nodes... |
| 90 | MarkReferredNodesReachable(Nodes[i], ShadowNodes, Reachable); |
| 91 | |
| 92 | // Mark all nodes in the return set as being reachable... |
| 93 | MarkReferredNodeSetReachable(RetNode, ShadowNodes, Reachable); |
| 94 | |
| 95 | // Mark all nodes in the value map as being reachable... |
| 96 | for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(), |
| 97 | E = ValueMap.end(); I != E; ++I) |
| 98 | MarkReferredNodeSetReachable(I->second, ShadowNodes, Reachable); |
| 99 | |
| 100 | |
| 101 | // At this point, all reachable shadow nodes have a true value in the |
| 102 | // Reachable vector. This means that any shadow nodes without an entry in |
| 103 | // the reachable vector are not reachable and should be removed. This is |
| 104 | // a two part process, because we must drop all references before we delete |
| 105 | // the shadow nodes [in case cycles exist]. |
| 106 | // |
| 107 | vector<ShadowDSNode*> DeadNodes; |
| 108 | for (unsigned i = 0; i != ShadowNodes.size(); ++i) |
| 109 | if (!Reachable[i]) { |
| 110 | // Track all unreachable nodes... |
| 111 | #if 0 |
| 112 | cerr << "Unreachable node eliminated:\n"; |
| 113 | ShadowNodes[i]->print(cerr); |
| 114 | #endif |
| 115 | DeadNodes.push_back(ShadowNodes[i]); |
| 116 | ShadowNodes[i]->dropAllReferences(); // Drop references to other nodes |
| 117 | Reachable.erase(Reachable.begin()+i); // Remove from reachable... |
| 118 | ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry |
| 119 | --i; // Don't skip the next node. |
| 120 | } |
| 121 | |
| 122 | if (DeadNodes.empty()) return; // No more dead nodes... |
| 123 | |
| 124 | // All dead nodes are in the DeadNodes vector... delete them now. |
| 125 | for_each(DeadNodes.begin(), DeadNodes.end(), deleter<DSNode>); |
| 126 | } |
| 127 | } |