blob: ab94c60d6d8d1e260fd6164e43ba7ad658e50a7c [file] [log] [blame]
Chris Lattner7d093d42002-03-28 19:16:48 +00001//===- EliminateNodes.cpp - Prune unneccesary nodes in the graph ----------===//
Chris Lattnerbb2a28f2002-03-26 22:39:06 +00002//
Chris Lattner7d093d42002-03-28 19:16:48 +00003// This file contains two node optimizations:
4// 1. UnlinkUndistinguishableNodes - Often, after unification, shadow
Chris Lattnerbb2a28f2002-03-26 22:39:06 +00005// 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//
Chris Lattner7d093d42002-03-28 19:16:48 +000010// 2. RemoveUnreachableNodes - Remove shadow and allocation nodes that are not
11// reachable from some other node in the graph. Unreachable nodes are left
12// lying around often because a method only refers to some allocations with
13// scalar values or an alloca, then when it is inlined, these references
14// disappear and the nodes become homeless and prunable.
Chris Lattnerbb2a28f2002-03-26 22:39:06 +000015//
16//===----------------------------------------------------------------------===//
17
18#include "llvm/Analysis/DataStructure.h"
19#include "llvm/Value.h"
20#include "Support/STLExtras.h"
21#include <algorithm>
22
Chris Lattner2ba3a722002-03-27 19:48:03 +000023//#define DEBUG_NODE_ELIMINATE 1
24
Chris Lattner1120c8b2002-03-28 17:56:03 +000025bool AllocDSNode::isEquivalentTo(DSNode *Node) const {
26 if (AllocDSNode *N = dyn_cast<AllocDSNode>(Node))
27 return N->Allocation == Allocation;
28 return false;
29}
30
31bool GlobalDSNode::isEquivalentTo(DSNode *Node) const {
32 if (GlobalDSNode *G = dyn_cast<GlobalDSNode>(Node))
33 return G->Val == Val;
34 return false;
35}
36
37bool CallDSNode::isEquivalentTo(DSNode *Node) const {
38 if (CallDSNode *C = dyn_cast<CallDSNode>(Node))
39 return C->CI == CI && C->ArgLinks == ArgLinks;
40 return false;
41}
42
43bool ArgDSNode::isEquivalentTo(DSNode *Node) const {
44 return false;
45}
46
Chris Lattner9d42a1d2002-03-27 00:55:13 +000047// NodesAreEquivalent - Check to see if the nodes are equivalent in all ways
48// except node type. Since we know N1 is a shadow node, N2 is allowed to be
49// any type.
50//
Chris Lattner1120c8b2002-03-28 17:56:03 +000051bool ShadowDSNode::isEquivalentTo(DSNode *Node) const {
52 return !isCriticalNode(); // Must not be a critical node...
Chris Lattner9d42a1d2002-03-27 00:55:13 +000053}
54
Chris Lattner1120c8b2002-03-28 17:56:03 +000055
56
57// isIndistinguishableNode - A node is indistinguishable if some other node
58// has exactly the same incoming links to it and if the node considers itself
59// to be the same as the other node...
Chris Lattner9d42a1d2002-03-27 00:55:13 +000060//
Chris Lattner7d093d42002-03-28 19:16:48 +000061static bool isIndistinguishableNode(DSNode *DN) {
Chris Lattner1120c8b2002-03-28 17:56:03 +000062 if (DN->getReferrers().empty()) { // No referrers...
63 if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN))
64 return true; // Node is trivially dead
65 else
66 return false;
67 }
68
Chris Lattner9d42a1d2002-03-27 00:55:13 +000069 // Pick a random referrer... Ptr is the things that the referrer points to.
Chris Lattner1120c8b2002-03-28 17:56:03 +000070 // Since DN is in the Ptr set, look through the set seeing if there are any
71 // other nodes that are exactly equilivant to DN (with the exception of node
72 // type), but are not DN. If anything exists, then DN is indistinguishable.
Chris Lattner9d42a1d2002-03-27 00:55:13 +000073 //
Chris Lattner1120c8b2002-03-28 17:56:03 +000074 const std::vector<PointerValSet*> &Refs = DN->getReferrers();
75 for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
76 const PointerValSet &Ptr = *Refs[R];
Chris Lattner9d42a1d2002-03-27 00:55:13 +000077
Chris Lattner1120c8b2002-03-28 17:56:03 +000078 for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
79 DSNode *N2 = Ptr[i].Node;
80 if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
81 DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {
82
83 // Otherwise, the nodes can be merged. Make sure that N2 contains all
84 // of the outgoing edges (fields) that DN does...
85 //
86 assert(DN->getNumLinks() == N2->getNumLinks() &&
87 "Same type, diff # fields?");
88 for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
89 N2->getLink(i).add(DN->getLink(i));
90
91 // Now make sure that all of the nodes that point to the shadow node
92 // also point to the node that we are merging it with...
93 //
94 const std::vector<PointerValSet*> &Refs = DN->getReferrers();
95 for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
96 PointerValSet &PVS = *Refs[i];
97 // FIXME: this is incorrect if the referring pointer has index != 0
98 //
99 PVS.add(N2);
100 }
101 return true;
102 }
103 }
104 }
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000105
106 // Otherwise, nothing found, perhaps next time....
107 return false;
108}
109
Chris Lattner1120c8b2002-03-28 17:56:03 +0000110template<typename NodeTy>
111bool removeIndistinguishableNode(std::vector<NodeTy*> &Nodes) {
112 bool Changed = false;
113 std::vector<NodeTy*>::iterator I = Nodes.begin();
114 while (I != Nodes.end()) {
115 if (isIndistinguishableNode(*I)) {
116#ifdef DEBUG_NODE_ELIMINATE
117 cerr << "Found Indistinguishable Node:\n";
118 (*I)->print(cerr);
119#endif
120 (*I)->removeAllIncomingEdges();
121 delete *I;
122 I = Nodes.erase(I);
123 Changed = true;
124 } else {
125 ++I;
126 }
127 }
128 return Changed;
129}
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000130
Chris Lattner7d093d42002-03-28 19:16:48 +0000131// UnlinkUndistinguishableNodes - Eliminate shadow nodes that are not
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000132// distinguishable from some other node in the graph...
133//
Chris Lattner7d093d42002-03-28 19:16:48 +0000134bool FunctionDSGraph::UnlinkUndistinguishableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000135 // Loop over all of the shadow nodes, checking to see if they are
136 // indistinguishable from some other node. If so, eliminate the node!
137 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000138 return
139 removeIndistinguishableNode(AllocNodes) |
140 removeIndistinguishableNode(ShadowNodes) |
141 removeIndistinguishableNode(GlobalNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000142}
143
Chris Lattner1120c8b2002-03-28 17:56:03 +0000144static void MarkReferredNodesReachable(DSNode *N,
145 vector<ShadowDSNode*> &ShadowNodes,
146 vector<bool> &ReachableShadowNodes,
147 vector<AllocDSNode*> &AllocNodes,
148 vector<bool> &ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000149
150static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
Chris Lattner1120c8b2002-03-28 17:56:03 +0000151 vector<ShadowDSNode*> &ShadowNodes,
152 vector<bool> &ReachableShadowNodes,
153 vector<AllocDSNode*> &AllocNodes,
154 vector<bool> &ReachableAllocNodes) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000155 for (unsigned i = 0, e = PVS.size(); i != e; ++i)
Chris Lattnercdae0b22002-03-28 18:38:38 +0000156 if (isa<ShadowDSNode>(PVS[i].Node) || isa<AllocDSNode>(PVS[i].Node))
Chris Lattner1120c8b2002-03-28 17:56:03 +0000157 MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes,
158 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000159}
160
Chris Lattner1120c8b2002-03-28 17:56:03 +0000161static void MarkReferredNodesReachable(DSNode *N,
162 vector<ShadowDSNode*> &ShadowNodes,
163 vector<bool> &ReachableShadowNodes,
164 vector<AllocDSNode*> &AllocNodes,
165 vector<bool> &ReachableAllocNodes) {
166 assert(ShadowNodes.size() == ReachableShadowNodes.size());
167 assert(AllocNodes.size() == ReachableAllocNodes.size());
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000168
Chris Lattner1120c8b2002-03-28 17:56:03 +0000169 if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N)) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000170 vector<ShadowDSNode*>::iterator I =
Chris Lattner1120c8b2002-03-28 17:56:03 +0000171 std::find(ShadowNodes.begin(), ShadowNodes.end(), Shad);
172 unsigned i = I-ShadowNodes.begin();
173 if (ReachableShadowNodes[i]) return; // Recursion detected, abort...
174 ReachableShadowNodes[i] = true;
175 } else if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(N)) {
176 vector<AllocDSNode*>::iterator I =
177 std::find(AllocNodes.begin(), AllocNodes.end(), Alloc);
178 unsigned i = I-AllocNodes.begin();
179 if (ReachableAllocNodes[i]) return; // Recursion detected, abort...
180 ReachableAllocNodes[i] = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000181 }
182
183 for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000184 MarkReferredNodeSetReachable(N->getLink(i),
185 ShadowNodes, ReachableShadowNodes,
186 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000187
188 const std::vector<PointerValSet> *Links = N->getAuxLinks();
189 if (Links)
190 for (unsigned i = 0, e = Links->size(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000191 MarkReferredNodeSetReachable((*Links)[i],
192 ShadowNodes, ReachableShadowNodes,
193 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000194}
195
Chris Lattner4dc1f822002-03-28 19:33:00 +0000196void FunctionDSGraph::MarkEscapeableNodesReachable(
197 vector<bool> &ReachableShadowNodes,
198 vector<bool> &ReachableAllocNodes) {
199 // Mark all shadow nodes that have edges from other nodes as reachable.
200 // Recursively mark any shadow nodes pointed to by the newly live shadow
201 // nodes as also alive.
202 //
203 for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
204 MarkReferredNodesReachable(ArgNodes[i],
205 ShadowNodes, ReachableShadowNodes,
206 AllocNodes, ReachableAllocNodes);
207
208 for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
209 MarkReferredNodesReachable(GlobalNodes[i],
210 ShadowNodes, ReachableShadowNodes,
211 AllocNodes, ReachableAllocNodes);
212
213 for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
214 MarkReferredNodesReachable(CallNodes[i],
215 ShadowNodes, ReachableShadowNodes,
216 AllocNodes, ReachableAllocNodes);
217
218 // Mark all nodes in the return set as being reachable...
219 MarkReferredNodeSetReachable(RetNode,
220 ShadowNodes, ReachableShadowNodes,
221 AllocNodes, ReachableAllocNodes);
222}
223
Chris Lattner7d093d42002-03-28 19:16:48 +0000224bool FunctionDSGraph::RemoveUnreachableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000225 bool Changed = false;
Chris Lattnercdae0b22002-03-28 18:38:38 +0000226
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000227 while (1) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000228 // Reachable*Nodes - Contains true if there is an edge from a reachable
229 // node to the numbered node...
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000230 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000231 vector<bool> ReachableShadowNodes(ShadowNodes.size());
232 vector<bool> ReachableAllocNodes (AllocNodes.size());
Chris Lattner4dc1f822002-03-28 19:33:00 +0000233
234 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000235
236 // Mark all nodes in the value map as being reachable...
237 for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
238 E = ValueMap.end(); I != E; ++I)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000239 MarkReferredNodeSetReachable(I->second,
240 ShadowNodes, ReachableShadowNodes,
241 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000242
243 // At this point, all reachable shadow nodes have a true value in the
244 // Reachable vector. This means that any shadow nodes without an entry in
245 // the reachable vector are not reachable and should be removed. This is
246 // a two part process, because we must drop all references before we delete
247 // the shadow nodes [in case cycles exist].
248 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000249 bool LocalChange = false;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000250 for (unsigned i = 0; i != ShadowNodes.size(); ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000251 if (!ReachableShadowNodes[i]) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000252 // Track all unreachable nodes...
Chris Lattner2ba3a722002-03-27 19:48:03 +0000253#if DEBUG_NODE_ELIMINATE
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000254 cerr << "Unreachable node eliminated:\n";
255 ShadowNodes[i]->print(cerr);
256#endif
Chris Lattner1120c8b2002-03-28 17:56:03 +0000257 ShadowNodes[i]->removeAllIncomingEdges();
258 delete ShadowNodes[i];
259
260 // Remove from reachable...
261 ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000262 ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry
263 --i; // Don't skip the next node.
Chris Lattner1120c8b2002-03-28 17:56:03 +0000264 LocalChange = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000265 }
266
Chris Lattner1120c8b2002-03-28 17:56:03 +0000267 for (unsigned i = 0; i != AllocNodes.size(); ++i)
268 if (!ReachableAllocNodes[i]) {
269 // Track all unreachable nodes...
270#if DEBUG_NODE_ELIMINATE
271 cerr << "Unreachable node eliminated:\n";
272 AllocNodes[i]->print(cerr);
273#endif
274 AllocNodes[i]->removeAllIncomingEdges();
275 delete AllocNodes[i];
276
277 // Remove from reachable...
278 ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
279 AllocNodes.erase(AllocNodes.begin()+i); // Remove node entry
280 --i; // Don't skip the next node.
281 LocalChange = true;
282 }
283
284 if (!LocalChange) return Changed; // No more dead nodes...
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000285
286 Changed = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000287 }
288}
Chris Lattner4dc1f822002-03-28 19:33:00 +0000289
290
291
292
293// getEscapingAllocations - Add all allocations that escape the current
294// function to the specified vector.
295//
296void FunctionDSGraph::getEscapingAllocations(vector<AllocDSNode*> &Allocs) {
297 vector<bool> ReachableShadowNodes(ShadowNodes.size());
298 vector<bool> ReachableAllocNodes (AllocNodes.size());
299
300 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
301
302 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
303 if (ReachableAllocNodes[i])
304 Allocs.push_back(AllocNodes[i]);
305}
306
307// getNonEscapingAllocations - Add all allocations that do not escape the
308// current function to the specified vector.
309//
310void FunctionDSGraph::getNonEscapingAllocations(vector<AllocDSNode*> &Allocs) {
311 vector<bool> ReachableShadowNodes(ShadowNodes.size());
312 vector<bool> ReachableAllocNodes (AllocNodes.size());
313
314 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
315
316 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
317 if (!ReachableAllocNodes[i])
318 Allocs.push_back(AllocNodes[i]);
319}