blob: 767f7fe006dc5c980e9b82396359e593d8ee53f3 [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
Chris Lattner44cf3902002-03-31 07:14:52 +000018#include "llvm/Analysis/DataStructureGraph.h"
Chris Lattnerbb2a28f2002-03-26 22:39:06 +000019#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 Lattner0b7c85c2002-03-31 19:57:44 +000025static void DestroyFirstNodeOfPair(DSNode *N1, DSNode *N2) {
26#ifdef DEBUG_NODE_ELIMINATE
27 cerr << "Found Indistinguishable Node:\n";
28 N1->print(cerr);
29#endif
30
31 // The nodes can be merged. Make sure that N2 contains all of the
32 // outgoing edges (fields) that N1 does...
33 //
34 assert(N1->getNumLinks() == N2->getNumLinks() &&
35 "Same type, diff # fields?");
36 for (unsigned i = 0, e = N1->getNumLinks(); i != e; ++i)
37 N2->getLink(i).add(N1->getLink(i));
38
39 // Now make sure that all of the nodes that point to N1 also point to the node
40 // that we are merging it with...
41 //
42 const std::vector<PointerValSet*> &Refs = N1->getReferrers();
43 for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
44 PointerValSet &PVS = *Refs[i];
45
46 bool RanOnce = false;
47 for (unsigned j = 0, je = PVS.size(); j != je; ++j)
48 if (PVS[j].Node == N1) {
49 RanOnce = true;
50 PVS.add(PointerVal(N2, PVS[j].Index));
51 }
52
53 assert(RanOnce && "Node on user set but cannot find the use!");
54 }
55
Chris Lattnerf30185f2002-04-01 00:13:56 +000056 // If we are about to eliminate a call node that returns a pointer, make the
57 // shadow node it points to not be critical anymore!
58 //
59 if (isa<CallDSNode>(N1) && N1->getNumLinks()) {
60 assert(N1->getNumLinks() == 1 && "Call node can only return one pointer!");
61 PointerValSet &PVS = N1->getLink(0);
62
63 for (unsigned i = 0, e = PVS.size(); i != e; ++i)
64 if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(PVS[i].Node))
65 if (Shad->isCriticalNode()) {
66 Shad->resetCriticalMark(); // Only unmark _ONE_ node..
67 break;
68 }
69
70 }
71
72
Chris Lattner0b7c85c2002-03-31 19:57:44 +000073 N1->removeAllIncomingEdges();
74 delete N1;
75}
Chris Lattner1120c8b2002-03-28 17:56:03 +000076
77// isIndistinguishableNode - A node is indistinguishable if some other node
78// has exactly the same incoming links to it and if the node considers itself
79// to be the same as the other node...
Chris Lattner9d42a1d2002-03-27 00:55:13 +000080//
Chris Lattner7d093d42002-03-28 19:16:48 +000081static bool isIndistinguishableNode(DSNode *DN) {
Chris Lattner1120c8b2002-03-28 17:56:03 +000082 if (DN->getReferrers().empty()) { // No referrers...
83 if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN))
84 return true; // Node is trivially dead
85 else
86 return false;
87 }
88
Chris Lattner9d42a1d2002-03-27 00:55:13 +000089 // Pick a random referrer... Ptr is the things that the referrer points to.
Chris Lattner1120c8b2002-03-28 17:56:03 +000090 // Since DN is in the Ptr set, look through the set seeing if there are any
91 // other nodes that are exactly equilivant to DN (with the exception of node
92 // type), but are not DN. If anything exists, then DN is indistinguishable.
Chris Lattner9d42a1d2002-03-27 00:55:13 +000093 //
Chris Lattner44cf3902002-03-31 07:14:52 +000094
95 DSNode *IndFrom = 0;
Chris Lattner1120c8b2002-03-28 17:56:03 +000096 const std::vector<PointerValSet*> &Refs = DN->getReferrers();
97 for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
98 const PointerValSet &Ptr = *Refs[R];
Chris Lattner9d42a1d2002-03-27 00:55:13 +000099
Chris Lattner1120c8b2002-03-28 17:56:03 +0000100 for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
101 DSNode *N2 = Ptr[i].Node;
102 if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
103 DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {
104
Chris Lattner44cf3902002-03-31 07:14:52 +0000105 IndFrom = N2;
106 R = RE-1;
107 break;
Chris Lattner1120c8b2002-03-28 17:56:03 +0000108 }
109 }
110 }
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000111
Chris Lattner44cf3902002-03-31 07:14:52 +0000112 // If we haven't found an equivalent node to merge with, see if one of the
113 // nodes pointed to by this node is equivalent to this one...
114 //
115 if (IndFrom == 0) {
116 unsigned NumOutgoing = DN->getNumOutgoingLinks();
117 for (DSNode::iterator I = DN->begin(), E = DN->end(); I != E; ++I) {
118 DSNode *Linked = *I;
119 if (Linked != DN && Linked->getNumOutgoingLinks() == NumOutgoing &&
120 DN->getType() == Linked->getType() && DN->isEquivalentTo(Linked)) {
121#if 0
122 // Make sure the leftover node contains links to everything we do...
123 for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
124 Linked->getLink(i).add(DN->getLink(i));
125#endif
126
127 IndFrom = Linked;
128 break;
129 }
130 }
131 }
132
133
134 // If DN is indistinguishable from some other node, merge them now...
135 if (IndFrom == 0)
136 return false; // Otherwise, nothing found, perhaps next time....
137
Chris Lattner0b7c85c2002-03-31 19:57:44 +0000138 DestroyFirstNodeOfPair(DN, IndFrom);
Chris Lattner44cf3902002-03-31 07:14:52 +0000139 return true;
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000140}
141
Chris Lattner1120c8b2002-03-28 17:56:03 +0000142template<typename NodeTy>
Chris Lattner44cf3902002-03-31 07:14:52 +0000143static bool removeIndistinguishableNodes(std::vector<NodeTy*> &Nodes) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000144 bool Changed = false;
145 std::vector<NodeTy*>::iterator I = Nodes.begin();
146 while (I != Nodes.end()) {
147 if (isIndistinguishableNode(*I)) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000148 I = Nodes.erase(I);
149 Changed = true;
150 } else {
151 ++I;
152 }
153 }
154 return Changed;
155}
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000156
Chris Lattner44cf3902002-03-31 07:14:52 +0000157template<typename NodeTy>
158static bool removeIndistinguishableNodePairs(std::vector<NodeTy*> &Nodes) {
159 bool Changed = false;
160 std::vector<NodeTy*>::iterator I = Nodes.begin();
161 while (I != Nodes.end()) {
162 NodeTy *N1 = *I++;
163 for (std::vector<NodeTy*>::iterator I2 = I, I2E = Nodes.end();
164 I2 != I2E; ++I2) {
165 NodeTy *N2 = *I2;
166 if (N1->isEquivalentTo(N2)) {
Chris Lattner0b7c85c2002-03-31 19:57:44 +0000167 DestroyFirstNodeOfPair(N1, N2);
Chris Lattner44cf3902002-03-31 07:14:52 +0000168 --I;
169 I = Nodes.erase(I);
170 Changed = true;
171 break;
172 }
173 }
174 }
175 return Changed;
176}
177
178
179
Chris Lattner7d093d42002-03-28 19:16:48 +0000180// UnlinkUndistinguishableNodes - Eliminate shadow nodes that are not
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000181// distinguishable from some other node in the graph...
182//
Chris Lattner7d093d42002-03-28 19:16:48 +0000183bool FunctionDSGraph::UnlinkUndistinguishableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000184 // Loop over all of the shadow nodes, checking to see if they are
185 // indistinguishable from some other node. If so, eliminate the node!
186 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000187 return
Chris Lattner44cf3902002-03-31 07:14:52 +0000188 removeIndistinguishableNodes(AllocNodes) |
189 removeIndistinguishableNodes(ShadowNodes) |
Chris Lattnerf30185f2002-04-01 00:13:56 +0000190 removeIndistinguishableNodePairs(CallNodes) |
Chris Lattner44cf3902002-03-31 07:14:52 +0000191 removeIndistinguishableNodePairs(GlobalNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000192}
193
Chris Lattner1120c8b2002-03-28 17:56:03 +0000194static void MarkReferredNodesReachable(DSNode *N,
195 vector<ShadowDSNode*> &ShadowNodes,
196 vector<bool> &ReachableShadowNodes,
197 vector<AllocDSNode*> &AllocNodes,
198 vector<bool> &ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000199
200static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
Chris Lattner1120c8b2002-03-28 17:56:03 +0000201 vector<ShadowDSNode*> &ShadowNodes,
202 vector<bool> &ReachableShadowNodes,
203 vector<AllocDSNode*> &AllocNodes,
204 vector<bool> &ReachableAllocNodes) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000205 for (unsigned i = 0, e = PVS.size(); i != e; ++i)
Chris Lattnercdae0b22002-03-28 18:38:38 +0000206 if (isa<ShadowDSNode>(PVS[i].Node) || isa<AllocDSNode>(PVS[i].Node))
Chris Lattner1120c8b2002-03-28 17:56:03 +0000207 MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes,
208 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000209}
210
Chris Lattner1120c8b2002-03-28 17:56:03 +0000211static void MarkReferredNodesReachable(DSNode *N,
212 vector<ShadowDSNode*> &ShadowNodes,
213 vector<bool> &ReachableShadowNodes,
214 vector<AllocDSNode*> &AllocNodes,
215 vector<bool> &ReachableAllocNodes) {
216 assert(ShadowNodes.size() == ReachableShadowNodes.size());
217 assert(AllocNodes.size() == ReachableAllocNodes.size());
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000218
Chris Lattner1120c8b2002-03-28 17:56:03 +0000219 if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N)) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000220 vector<ShadowDSNode*>::iterator I =
Chris Lattner1120c8b2002-03-28 17:56:03 +0000221 std::find(ShadowNodes.begin(), ShadowNodes.end(), Shad);
222 unsigned i = I-ShadowNodes.begin();
223 if (ReachableShadowNodes[i]) return; // Recursion detected, abort...
224 ReachableShadowNodes[i] = true;
225 } else if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(N)) {
226 vector<AllocDSNode*>::iterator I =
227 std::find(AllocNodes.begin(), AllocNodes.end(), Alloc);
228 unsigned i = I-AllocNodes.begin();
229 if (ReachableAllocNodes[i]) return; // Recursion detected, abort...
230 ReachableAllocNodes[i] = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000231 }
232
233 for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000234 MarkReferredNodeSetReachable(N->getLink(i),
235 ShadowNodes, ReachableShadowNodes,
236 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000237
238 const std::vector<PointerValSet> *Links = N->getAuxLinks();
239 if (Links)
240 for (unsigned i = 0, e = Links->size(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000241 MarkReferredNodeSetReachable((*Links)[i],
242 ShadowNodes, ReachableShadowNodes,
243 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000244}
245
Chris Lattner4dc1f822002-03-28 19:33:00 +0000246void FunctionDSGraph::MarkEscapeableNodesReachable(
247 vector<bool> &ReachableShadowNodes,
248 vector<bool> &ReachableAllocNodes) {
249 // Mark all shadow nodes that have edges from other nodes as reachable.
250 // Recursively mark any shadow nodes pointed to by the newly live shadow
251 // nodes as also alive.
252 //
253 for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
254 MarkReferredNodesReachable(ArgNodes[i],
255 ShadowNodes, ReachableShadowNodes,
256 AllocNodes, ReachableAllocNodes);
257
258 for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
259 MarkReferredNodesReachable(GlobalNodes[i],
260 ShadowNodes, ReachableShadowNodes,
261 AllocNodes, ReachableAllocNodes);
262
263 for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
264 MarkReferredNodesReachable(CallNodes[i],
265 ShadowNodes, ReachableShadowNodes,
266 AllocNodes, ReachableAllocNodes);
267
268 // Mark all nodes in the return set as being reachable...
269 MarkReferredNodeSetReachable(RetNode,
270 ShadowNodes, ReachableShadowNodes,
271 AllocNodes, ReachableAllocNodes);
272}
273
Chris Lattner7d093d42002-03-28 19:16:48 +0000274bool FunctionDSGraph::RemoveUnreachableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000275 bool Changed = false;
Chris Lattnercdae0b22002-03-28 18:38:38 +0000276
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000277 while (1) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000278 // Reachable*Nodes - Contains true if there is an edge from a reachable
279 // node to the numbered node...
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000280 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000281 vector<bool> ReachableShadowNodes(ShadowNodes.size());
282 vector<bool> ReachableAllocNodes (AllocNodes.size());
Chris Lattner4dc1f822002-03-28 19:33:00 +0000283
284 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000285
286 // Mark all nodes in the value map as being reachable...
287 for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
288 E = ValueMap.end(); I != E; ++I)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000289 MarkReferredNodeSetReachable(I->second,
290 ShadowNodes, ReachableShadowNodes,
291 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000292
293 // At this point, all reachable shadow nodes have a true value in the
294 // Reachable vector. This means that any shadow nodes without an entry in
295 // the reachable vector are not reachable and should be removed. This is
296 // a two part process, because we must drop all references before we delete
297 // the shadow nodes [in case cycles exist].
298 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000299 bool LocalChange = false;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000300 for (unsigned i = 0; i != ShadowNodes.size(); ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000301 if (!ReachableShadowNodes[i]) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000302 // Track all unreachable nodes...
Chris Lattner2ba3a722002-03-27 19:48:03 +0000303#if DEBUG_NODE_ELIMINATE
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000304 cerr << "Unreachable node eliminated:\n";
305 ShadowNodes[i]->print(cerr);
306#endif
Chris Lattner1120c8b2002-03-28 17:56:03 +0000307 ShadowNodes[i]->removeAllIncomingEdges();
308 delete ShadowNodes[i];
309
310 // Remove from reachable...
311 ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000312 ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry
313 --i; // Don't skip the next node.
Chris Lattner1120c8b2002-03-28 17:56:03 +0000314 LocalChange = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000315 }
316
Chris Lattner1120c8b2002-03-28 17:56:03 +0000317 for (unsigned i = 0; i != AllocNodes.size(); ++i)
318 if (!ReachableAllocNodes[i]) {
319 // Track all unreachable nodes...
320#if DEBUG_NODE_ELIMINATE
321 cerr << "Unreachable node eliminated:\n";
322 AllocNodes[i]->print(cerr);
323#endif
324 AllocNodes[i]->removeAllIncomingEdges();
325 delete AllocNodes[i];
326
327 // Remove from reachable...
328 ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
329 AllocNodes.erase(AllocNodes.begin()+i); // Remove node entry
330 --i; // Don't skip the next node.
331 LocalChange = true;
332 }
333
334 if (!LocalChange) return Changed; // No more dead nodes...
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000335
336 Changed = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000337 }
338}
Chris Lattner4dc1f822002-03-28 19:33:00 +0000339
340
341
342
343// getEscapingAllocations - Add all allocations that escape the current
344// function to the specified vector.
345//
346void FunctionDSGraph::getEscapingAllocations(vector<AllocDSNode*> &Allocs) {
347 vector<bool> ReachableShadowNodes(ShadowNodes.size());
348 vector<bool> ReachableAllocNodes (AllocNodes.size());
349
350 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
351
352 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
353 if (ReachableAllocNodes[i])
354 Allocs.push_back(AllocNodes[i]);
355}
356
357// getNonEscapingAllocations - Add all allocations that do not escape the
358// current function to the specified vector.
359//
360void FunctionDSGraph::getNonEscapingAllocations(vector<AllocDSNode*> &Allocs) {
361 vector<bool> ReachableShadowNodes(ShadowNodes.size());
362 vector<bool> ReachableAllocNodes (AllocNodes.size());
363
364 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
365
366 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
367 if (!ReachableAllocNodes[i])
368 Allocs.push_back(AllocNodes[i]);
369}