blob: edd8285bc81d1d1f5460039280618fccf121c4ea [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
56 N1->removeAllIncomingEdges();
57 delete N1;
58}
Chris Lattner1120c8b2002-03-28 17:56:03 +000059
60// isIndistinguishableNode - A node is indistinguishable if some other node
61// has exactly the same incoming links to it and if the node considers itself
62// to be the same as the other node...
Chris Lattner9d42a1d2002-03-27 00:55:13 +000063//
Chris Lattner7d093d42002-03-28 19:16:48 +000064static bool isIndistinguishableNode(DSNode *DN) {
Chris Lattner1120c8b2002-03-28 17:56:03 +000065 if (DN->getReferrers().empty()) { // No referrers...
Chris Lattner7650b942002-04-16 20:39:59 +000066 if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN)) {
67 delete DN;
Chris Lattner1120c8b2002-03-28 17:56:03 +000068 return true; // Node is trivially dead
Chris Lattner7650b942002-04-16 20:39:59 +000069 } else
Chris Lattner1120c8b2002-03-28 17:56:03 +000070 return false;
71 }
72
Chris Lattner9d42a1d2002-03-27 00:55:13 +000073 // Pick a random referrer... Ptr is the things that the referrer points to.
Chris Lattner1120c8b2002-03-28 17:56:03 +000074 // Since DN is in the Ptr set, look through the set seeing if there are any
75 // other nodes that are exactly equilivant to DN (with the exception of node
76 // type), but are not DN. If anything exists, then DN is indistinguishable.
Chris Lattner9d42a1d2002-03-27 00:55:13 +000077 //
Chris Lattner44cf3902002-03-31 07:14:52 +000078
79 DSNode *IndFrom = 0;
Chris Lattner1120c8b2002-03-28 17:56:03 +000080 const std::vector<PointerValSet*> &Refs = DN->getReferrers();
81 for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
82 const PointerValSet &Ptr = *Refs[R];
Chris Lattner9d42a1d2002-03-27 00:55:13 +000083
Chris Lattner1120c8b2002-03-28 17:56:03 +000084 for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
85 DSNode *N2 = Ptr[i].Node;
86 if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
87 DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {
88
Chris Lattner44cf3902002-03-31 07:14:52 +000089 IndFrom = N2;
90 R = RE-1;
91 break;
Chris Lattner1120c8b2002-03-28 17:56:03 +000092 }
93 }
94 }
Chris Lattner9d42a1d2002-03-27 00:55:13 +000095
Chris Lattner44cf3902002-03-31 07:14:52 +000096 // If we haven't found an equivalent node to merge with, see if one of the
97 // nodes pointed to by this node is equivalent to this one...
98 //
99 if (IndFrom == 0) {
100 unsigned NumOutgoing = DN->getNumOutgoingLinks();
101 for (DSNode::iterator I = DN->begin(), E = DN->end(); I != E; ++I) {
102 DSNode *Linked = *I;
103 if (Linked != DN && Linked->getNumOutgoingLinks() == NumOutgoing &&
104 DN->getType() == Linked->getType() && DN->isEquivalentTo(Linked)) {
105#if 0
106 // Make sure the leftover node contains links to everything we do...
107 for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
108 Linked->getLink(i).add(DN->getLink(i));
109#endif
110
111 IndFrom = Linked;
112 break;
113 }
114 }
115 }
116
117
118 // If DN is indistinguishable from some other node, merge them now...
119 if (IndFrom == 0)
120 return false; // Otherwise, nothing found, perhaps next time....
121
Chris Lattner0b7c85c2002-03-31 19:57:44 +0000122 DestroyFirstNodeOfPair(DN, IndFrom);
Chris Lattner44cf3902002-03-31 07:14:52 +0000123 return true;
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000124}
125
Chris Lattner1120c8b2002-03-28 17:56:03 +0000126template<typename NodeTy>
Chris Lattner44cf3902002-03-31 07:14:52 +0000127static bool removeIndistinguishableNodes(std::vector<NodeTy*> &Nodes) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000128 bool Changed = false;
129 std::vector<NodeTy*>::iterator I = Nodes.begin();
130 while (I != Nodes.end()) {
131 if (isIndistinguishableNode(*I)) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000132 I = Nodes.erase(I);
133 Changed = true;
134 } else {
135 ++I;
136 }
137 }
138 return Changed;
139}
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000140
Chris Lattner44cf3902002-03-31 07:14:52 +0000141template<typename NodeTy>
142static bool removeIndistinguishableNodePairs(std::vector<NodeTy*> &Nodes) {
143 bool Changed = false;
144 std::vector<NodeTy*>::iterator I = Nodes.begin();
145 while (I != Nodes.end()) {
146 NodeTy *N1 = *I++;
147 for (std::vector<NodeTy*>::iterator I2 = I, I2E = Nodes.end();
148 I2 != I2E; ++I2) {
149 NodeTy *N2 = *I2;
150 if (N1->isEquivalentTo(N2)) {
Chris Lattner0b7c85c2002-03-31 19:57:44 +0000151 DestroyFirstNodeOfPair(N1, N2);
Chris Lattner44cf3902002-03-31 07:14:52 +0000152 --I;
153 I = Nodes.erase(I);
154 Changed = true;
155 break;
156 }
157 }
158 }
159 return Changed;
160}
161
162
163
Chris Lattner7d093d42002-03-28 19:16:48 +0000164// UnlinkUndistinguishableNodes - Eliminate shadow nodes that are not
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000165// distinguishable from some other node in the graph...
166//
Chris Lattner7d093d42002-03-28 19:16:48 +0000167bool FunctionDSGraph::UnlinkUndistinguishableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000168 // Loop over all of the shadow nodes, checking to see if they are
169 // indistinguishable from some other node. If so, eliminate the node!
170 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000171 return
Chris Lattner44cf3902002-03-31 07:14:52 +0000172 removeIndistinguishableNodes(AllocNodes) |
173 removeIndistinguishableNodes(ShadowNodes) |
Chris Lattnerf30185f2002-04-01 00:13:56 +0000174 removeIndistinguishableNodePairs(CallNodes) |
Chris Lattner44cf3902002-03-31 07:14:52 +0000175 removeIndistinguishableNodePairs(GlobalNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000176}
177
Chris Lattner1120c8b2002-03-28 17:56:03 +0000178static void MarkReferredNodesReachable(DSNode *N,
179 vector<ShadowDSNode*> &ShadowNodes,
180 vector<bool> &ReachableShadowNodes,
181 vector<AllocDSNode*> &AllocNodes,
182 vector<bool> &ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000183
184static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
Chris Lattner1120c8b2002-03-28 17:56:03 +0000185 vector<ShadowDSNode*> &ShadowNodes,
186 vector<bool> &ReachableShadowNodes,
187 vector<AllocDSNode*> &AllocNodes,
188 vector<bool> &ReachableAllocNodes) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000189 for (unsigned i = 0, e = PVS.size(); i != e; ++i)
Chris Lattnercdae0b22002-03-28 18:38:38 +0000190 if (isa<ShadowDSNode>(PVS[i].Node) || isa<AllocDSNode>(PVS[i].Node))
Chris Lattner1120c8b2002-03-28 17:56:03 +0000191 MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes,
192 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000193}
194
Chris Lattner1120c8b2002-03-28 17:56:03 +0000195static void MarkReferredNodesReachable(DSNode *N,
196 vector<ShadowDSNode*> &ShadowNodes,
197 vector<bool> &ReachableShadowNodes,
198 vector<AllocDSNode*> &AllocNodes,
199 vector<bool> &ReachableAllocNodes) {
200 assert(ShadowNodes.size() == ReachableShadowNodes.size());
201 assert(AllocNodes.size() == ReachableAllocNodes.size());
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000202
Chris Lattner1120c8b2002-03-28 17:56:03 +0000203 if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N)) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000204 vector<ShadowDSNode*>::iterator I =
Chris Lattner1120c8b2002-03-28 17:56:03 +0000205 std::find(ShadowNodes.begin(), ShadowNodes.end(), Shad);
206 unsigned i = I-ShadowNodes.begin();
207 if (ReachableShadowNodes[i]) return; // Recursion detected, abort...
208 ReachableShadowNodes[i] = true;
209 } else if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(N)) {
210 vector<AllocDSNode*>::iterator I =
211 std::find(AllocNodes.begin(), AllocNodes.end(), Alloc);
212 unsigned i = I-AllocNodes.begin();
213 if (ReachableAllocNodes[i]) return; // Recursion detected, abort...
214 ReachableAllocNodes[i] = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000215 }
216
217 for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000218 MarkReferredNodeSetReachable(N->getLink(i),
219 ShadowNodes, ReachableShadowNodes,
220 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000221
222 const std::vector<PointerValSet> *Links = N->getAuxLinks();
223 if (Links)
224 for (unsigned i = 0, e = Links->size(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000225 MarkReferredNodeSetReachable((*Links)[i],
226 ShadowNodes, ReachableShadowNodes,
227 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000228}
229
Chris Lattner4dc1f822002-03-28 19:33:00 +0000230void FunctionDSGraph::MarkEscapeableNodesReachable(
231 vector<bool> &ReachableShadowNodes,
232 vector<bool> &ReachableAllocNodes) {
233 // Mark all shadow nodes that have edges from other nodes as reachable.
234 // Recursively mark any shadow nodes pointed to by the newly live shadow
235 // nodes as also alive.
236 //
Chris Lattner4dc1f822002-03-28 19:33:00 +0000237 for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
238 MarkReferredNodesReachable(GlobalNodes[i],
239 ShadowNodes, ReachableShadowNodes,
240 AllocNodes, ReachableAllocNodes);
241
242 for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
243 MarkReferredNodesReachable(CallNodes[i],
244 ShadowNodes, ReachableShadowNodes,
245 AllocNodes, ReachableAllocNodes);
246
247 // Mark all nodes in the return set as being reachable...
248 MarkReferredNodeSetReachable(RetNode,
249 ShadowNodes, ReachableShadowNodes,
250 AllocNodes, ReachableAllocNodes);
251}
252
Chris Lattner7d093d42002-03-28 19:16:48 +0000253bool FunctionDSGraph::RemoveUnreachableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000254 bool Changed = false;
Chris Lattner212be2e2002-04-16 03:44:03 +0000255 bool LocalChange = true;
256
257 while (LocalChange) {
258 LocalChange = false;
Chris Lattner1120c8b2002-03-28 17:56:03 +0000259 // Reachable*Nodes - Contains true if there is an edge from a reachable
260 // node to the numbered node...
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000261 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000262 vector<bool> ReachableShadowNodes(ShadowNodes.size());
263 vector<bool> ReachableAllocNodes (AllocNodes.size());
Chris Lattner4dc1f822002-03-28 19:33:00 +0000264
265 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000266
267 // Mark all nodes in the value map as being reachable...
268 for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
269 E = ValueMap.end(); I != E; ++I)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000270 MarkReferredNodeSetReachable(I->second,
271 ShadowNodes, ReachableShadowNodes,
272 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000273
274 // At this point, all reachable shadow nodes have a true value in the
275 // Reachable vector. This means that any shadow nodes without an entry in
276 // the reachable vector are not reachable and should be removed. This is
277 // a two part process, because we must drop all references before we delete
278 // the shadow nodes [in case cycles exist].
279 //
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000280 for (unsigned i = 0; i != ShadowNodes.size(); ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000281 if (!ReachableShadowNodes[i]) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000282 // Track all unreachable nodes...
Chris Lattner2ba3a722002-03-27 19:48:03 +0000283#if DEBUG_NODE_ELIMINATE
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000284 cerr << "Unreachable node eliminated:\n";
285 ShadowNodes[i]->print(cerr);
286#endif
Chris Lattner1120c8b2002-03-28 17:56:03 +0000287 ShadowNodes[i]->removeAllIncomingEdges();
288 delete ShadowNodes[i];
289
290 // Remove from reachable...
291 ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000292 ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry
293 --i; // Don't skip the next node.
Chris Lattner212be2e2002-04-16 03:44:03 +0000294 LocalChange = Changed = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000295 }
296
Chris Lattner1120c8b2002-03-28 17:56:03 +0000297 for (unsigned i = 0; i != AllocNodes.size(); ++i)
298 if (!ReachableAllocNodes[i]) {
299 // Track all unreachable nodes...
300#if DEBUG_NODE_ELIMINATE
301 cerr << "Unreachable node eliminated:\n";
302 AllocNodes[i]->print(cerr);
303#endif
304 AllocNodes[i]->removeAllIncomingEdges();
305 delete AllocNodes[i];
306
307 // Remove from reachable...
308 ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
309 AllocNodes.erase(AllocNodes.begin()+i); // Remove node entry
310 --i; // Don't skip the next node.
Chris Lattner212be2e2002-04-16 03:44:03 +0000311 LocalChange = Changed = true;
Chris Lattner1120c8b2002-03-28 17:56:03 +0000312 }
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000313 }
Chris Lattner212be2e2002-04-16 03:44:03 +0000314
Chris Lattner7650b942002-04-16 20:39:59 +0000315 // Loop over the global nodes, removing nodes that have no edges into them or
316 // out of them.
317 //
Chris Lattner212be2e2002-04-16 03:44:03 +0000318 for (std::vector<GlobalDSNode*>::iterator I = GlobalNodes.begin();
319 I != GlobalNodes.end(); )
Chris Lattner7650b942002-04-16 20:39:59 +0000320 if ((*I)->getReferrers().empty()) {
321 GlobalDSNode *GDN = *I;
322 bool NoLinks = true; // Make sure there are no outgoing links...
323 for (unsigned i = 0, e = GDN->getNumLinks(); i != e; ++i)
324 if (!GDN->getLink(i).empty()) {
325 NoLinks = false;
326 break;
327 }
328 if (NoLinks) {
329 delete GDN;
330 I = GlobalNodes.erase(I); // Remove the node...
331 Changed = true;
332 } else {
333 ++I;
334 }
Chris Lattner212be2e2002-04-16 03:44:03 +0000335 } else {
336 ++I;
337 }
Chris Lattner7650b942002-04-16 20:39:59 +0000338
Chris Lattner212be2e2002-04-16 03:44:03 +0000339 return Changed;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000340}
Chris Lattner4dc1f822002-03-28 19:33:00 +0000341
342
343
344
345// getEscapingAllocations - Add all allocations that escape the current
346// function to the specified vector.
347//
348void FunctionDSGraph::getEscapingAllocations(vector<AllocDSNode*> &Allocs) {
349 vector<bool> ReachableShadowNodes(ShadowNodes.size());
350 vector<bool> ReachableAllocNodes (AllocNodes.size());
351
352 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
353
354 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
355 if (ReachableAllocNodes[i])
356 Allocs.push_back(AllocNodes[i]);
357}
358
359// getNonEscapingAllocations - Add all allocations that do not escape the
360// current function to the specified vector.
361//
362void FunctionDSGraph::getNonEscapingAllocations(vector<AllocDSNode*> &Allocs) {
363 vector<bool> ReachableShadowNodes(ShadowNodes.size());
364 vector<bool> ReachableAllocNodes (AllocNodes.size());
365
366 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
367
368 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
369 if (!ReachableAllocNodes[i])
370 Allocs.push_back(AllocNodes[i]);
371}