blob: 7dd5b3317b0166b897f4e0020855c5ccc59e0a1e [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...
66 if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN))
67 return true; // Node is trivially dead
68 else
69 return false;
70 }
71
Chris Lattner9d42a1d2002-03-27 00:55:13 +000072 // Pick a random referrer... Ptr is the things that the referrer points to.
Chris Lattner1120c8b2002-03-28 17:56:03 +000073 // Since DN is in the Ptr set, look through the set seeing if there are any
74 // other nodes that are exactly equilivant to DN (with the exception of node
75 // type), but are not DN. If anything exists, then DN is indistinguishable.
Chris Lattner9d42a1d2002-03-27 00:55:13 +000076 //
Chris Lattner44cf3902002-03-31 07:14:52 +000077
78 DSNode *IndFrom = 0;
Chris Lattner1120c8b2002-03-28 17:56:03 +000079 const std::vector<PointerValSet*> &Refs = DN->getReferrers();
80 for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
81 const PointerValSet &Ptr = *Refs[R];
Chris Lattner9d42a1d2002-03-27 00:55:13 +000082
Chris Lattner1120c8b2002-03-28 17:56:03 +000083 for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
84 DSNode *N2 = Ptr[i].Node;
85 if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
86 DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {
87
Chris Lattner44cf3902002-03-31 07:14:52 +000088 IndFrom = N2;
89 R = RE-1;
90 break;
Chris Lattner1120c8b2002-03-28 17:56:03 +000091 }
92 }
93 }
Chris Lattner9d42a1d2002-03-27 00:55:13 +000094
Chris Lattner44cf3902002-03-31 07:14:52 +000095 // If we haven't found an equivalent node to merge with, see if one of the
96 // nodes pointed to by this node is equivalent to this one...
97 //
98 if (IndFrom == 0) {
99 unsigned NumOutgoing = DN->getNumOutgoingLinks();
100 for (DSNode::iterator I = DN->begin(), E = DN->end(); I != E; ++I) {
101 DSNode *Linked = *I;
102 if (Linked != DN && Linked->getNumOutgoingLinks() == NumOutgoing &&
103 DN->getType() == Linked->getType() && DN->isEquivalentTo(Linked)) {
104#if 0
105 // Make sure the leftover node contains links to everything we do...
106 for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
107 Linked->getLink(i).add(DN->getLink(i));
108#endif
109
110 IndFrom = Linked;
111 break;
112 }
113 }
114 }
115
116
117 // If DN is indistinguishable from some other node, merge them now...
118 if (IndFrom == 0)
119 return false; // Otherwise, nothing found, perhaps next time....
120
Chris Lattner0b7c85c2002-03-31 19:57:44 +0000121 DestroyFirstNodeOfPair(DN, IndFrom);
Chris Lattner44cf3902002-03-31 07:14:52 +0000122 return true;
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000123}
124
Chris Lattner1120c8b2002-03-28 17:56:03 +0000125template<typename NodeTy>
Chris Lattner44cf3902002-03-31 07:14:52 +0000126static bool removeIndistinguishableNodes(std::vector<NodeTy*> &Nodes) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000127 bool Changed = false;
128 std::vector<NodeTy*>::iterator I = Nodes.begin();
129 while (I != Nodes.end()) {
130 if (isIndistinguishableNode(*I)) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000131 I = Nodes.erase(I);
132 Changed = true;
133 } else {
134 ++I;
135 }
136 }
137 return Changed;
138}
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000139
Chris Lattner44cf3902002-03-31 07:14:52 +0000140template<typename NodeTy>
141static bool removeIndistinguishableNodePairs(std::vector<NodeTy*> &Nodes) {
142 bool Changed = false;
143 std::vector<NodeTy*>::iterator I = Nodes.begin();
144 while (I != Nodes.end()) {
145 NodeTy *N1 = *I++;
146 for (std::vector<NodeTy*>::iterator I2 = I, I2E = Nodes.end();
147 I2 != I2E; ++I2) {
148 NodeTy *N2 = *I2;
149 if (N1->isEquivalentTo(N2)) {
Chris Lattner0b7c85c2002-03-31 19:57:44 +0000150 DestroyFirstNodeOfPair(N1, N2);
Chris Lattner44cf3902002-03-31 07:14:52 +0000151 --I;
152 I = Nodes.erase(I);
153 Changed = true;
154 break;
155 }
156 }
157 }
158 return Changed;
159}
160
161
162
Chris Lattner7d093d42002-03-28 19:16:48 +0000163// UnlinkUndistinguishableNodes - Eliminate shadow nodes that are not
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000164// distinguishable from some other node in the graph...
165//
Chris Lattner7d093d42002-03-28 19:16:48 +0000166bool FunctionDSGraph::UnlinkUndistinguishableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000167 // Loop over all of the shadow nodes, checking to see if they are
168 // indistinguishable from some other node. If so, eliminate the node!
169 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000170 return
Chris Lattner44cf3902002-03-31 07:14:52 +0000171 removeIndistinguishableNodes(AllocNodes) |
172 removeIndistinguishableNodes(ShadowNodes) |
173 //FIXME: We cannot naively remove call nodes here because if there is a
174 // shadow node that is the result of the call, we have to make sure to
175 // merge the shadow node as well!!!
176 // removeIndistinguishableNodePairs(CallNodes) |
177 removeIndistinguishableNodePairs(GlobalNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000178}
179
Chris Lattner1120c8b2002-03-28 17:56:03 +0000180static void MarkReferredNodesReachable(DSNode *N,
181 vector<ShadowDSNode*> &ShadowNodes,
182 vector<bool> &ReachableShadowNodes,
183 vector<AllocDSNode*> &AllocNodes,
184 vector<bool> &ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000185
186static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
Chris Lattner1120c8b2002-03-28 17:56:03 +0000187 vector<ShadowDSNode*> &ShadowNodes,
188 vector<bool> &ReachableShadowNodes,
189 vector<AllocDSNode*> &AllocNodes,
190 vector<bool> &ReachableAllocNodes) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000191 for (unsigned i = 0, e = PVS.size(); i != e; ++i)
Chris Lattnercdae0b22002-03-28 18:38:38 +0000192 if (isa<ShadowDSNode>(PVS[i].Node) || isa<AllocDSNode>(PVS[i].Node))
Chris Lattner1120c8b2002-03-28 17:56:03 +0000193 MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes,
194 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000195}
196
Chris Lattner1120c8b2002-03-28 17:56:03 +0000197static void MarkReferredNodesReachable(DSNode *N,
198 vector<ShadowDSNode*> &ShadowNodes,
199 vector<bool> &ReachableShadowNodes,
200 vector<AllocDSNode*> &AllocNodes,
201 vector<bool> &ReachableAllocNodes) {
202 assert(ShadowNodes.size() == ReachableShadowNodes.size());
203 assert(AllocNodes.size() == ReachableAllocNodes.size());
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000204
Chris Lattner1120c8b2002-03-28 17:56:03 +0000205 if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N)) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000206 vector<ShadowDSNode*>::iterator I =
Chris Lattner1120c8b2002-03-28 17:56:03 +0000207 std::find(ShadowNodes.begin(), ShadowNodes.end(), Shad);
208 unsigned i = I-ShadowNodes.begin();
209 if (ReachableShadowNodes[i]) return; // Recursion detected, abort...
210 ReachableShadowNodes[i] = true;
211 } else if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(N)) {
212 vector<AllocDSNode*>::iterator I =
213 std::find(AllocNodes.begin(), AllocNodes.end(), Alloc);
214 unsigned i = I-AllocNodes.begin();
215 if (ReachableAllocNodes[i]) return; // Recursion detected, abort...
216 ReachableAllocNodes[i] = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000217 }
218
219 for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000220 MarkReferredNodeSetReachable(N->getLink(i),
221 ShadowNodes, ReachableShadowNodes,
222 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000223
224 const std::vector<PointerValSet> *Links = N->getAuxLinks();
225 if (Links)
226 for (unsigned i = 0, e = Links->size(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000227 MarkReferredNodeSetReachable((*Links)[i],
228 ShadowNodes, ReachableShadowNodes,
229 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000230}
231
Chris Lattner4dc1f822002-03-28 19:33:00 +0000232void FunctionDSGraph::MarkEscapeableNodesReachable(
233 vector<bool> &ReachableShadowNodes,
234 vector<bool> &ReachableAllocNodes) {
235 // Mark all shadow nodes that have edges from other nodes as reachable.
236 // Recursively mark any shadow nodes pointed to by the newly live shadow
237 // nodes as also alive.
238 //
239 for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
240 MarkReferredNodesReachable(ArgNodes[i],
241 ShadowNodes, ReachableShadowNodes,
242 AllocNodes, ReachableAllocNodes);
243
244 for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
245 MarkReferredNodesReachable(GlobalNodes[i],
246 ShadowNodes, ReachableShadowNodes,
247 AllocNodes, ReachableAllocNodes);
248
249 for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
250 MarkReferredNodesReachable(CallNodes[i],
251 ShadowNodes, ReachableShadowNodes,
252 AllocNodes, ReachableAllocNodes);
253
254 // Mark all nodes in the return set as being reachable...
255 MarkReferredNodeSetReachable(RetNode,
256 ShadowNodes, ReachableShadowNodes,
257 AllocNodes, ReachableAllocNodes);
258}
259
Chris Lattner7d093d42002-03-28 19:16:48 +0000260bool FunctionDSGraph::RemoveUnreachableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000261 bool Changed = false;
Chris Lattnercdae0b22002-03-28 18:38:38 +0000262
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000263 while (1) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000264 // Reachable*Nodes - Contains true if there is an edge from a reachable
265 // node to the numbered node...
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000266 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000267 vector<bool> ReachableShadowNodes(ShadowNodes.size());
268 vector<bool> ReachableAllocNodes (AllocNodes.size());
Chris Lattner4dc1f822002-03-28 19:33:00 +0000269
270 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000271
272 // Mark all nodes in the value map as being reachable...
273 for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
274 E = ValueMap.end(); I != E; ++I)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000275 MarkReferredNodeSetReachable(I->second,
276 ShadowNodes, ReachableShadowNodes,
277 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000278
279 // At this point, all reachable shadow nodes have a true value in the
280 // Reachable vector. This means that any shadow nodes without an entry in
281 // the reachable vector are not reachable and should be removed. This is
282 // a two part process, because we must drop all references before we delete
283 // the shadow nodes [in case cycles exist].
284 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000285 bool LocalChange = false;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000286 for (unsigned i = 0; i != ShadowNodes.size(); ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000287 if (!ReachableShadowNodes[i]) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000288 // Track all unreachable nodes...
Chris Lattner2ba3a722002-03-27 19:48:03 +0000289#if DEBUG_NODE_ELIMINATE
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000290 cerr << "Unreachable node eliminated:\n";
291 ShadowNodes[i]->print(cerr);
292#endif
Chris Lattner1120c8b2002-03-28 17:56:03 +0000293 ShadowNodes[i]->removeAllIncomingEdges();
294 delete ShadowNodes[i];
295
296 // Remove from reachable...
297 ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000298 ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry
299 --i; // Don't skip the next node.
Chris Lattner1120c8b2002-03-28 17:56:03 +0000300 LocalChange = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000301 }
302
Chris Lattner1120c8b2002-03-28 17:56:03 +0000303 for (unsigned i = 0; i != AllocNodes.size(); ++i)
304 if (!ReachableAllocNodes[i]) {
305 // Track all unreachable nodes...
306#if DEBUG_NODE_ELIMINATE
307 cerr << "Unreachable node eliminated:\n";
308 AllocNodes[i]->print(cerr);
309#endif
310 AllocNodes[i]->removeAllIncomingEdges();
311 delete AllocNodes[i];
312
313 // Remove from reachable...
314 ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
315 AllocNodes.erase(AllocNodes.begin()+i); // Remove node entry
316 --i; // Don't skip the next node.
317 LocalChange = true;
318 }
319
320 if (!LocalChange) return Changed; // No more dead nodes...
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000321
322 Changed = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000323 }
324}
Chris Lattner4dc1f822002-03-28 19:33:00 +0000325
326
327
328
329// getEscapingAllocations - Add all allocations that escape the current
330// function to the specified vector.
331//
332void FunctionDSGraph::getEscapingAllocations(vector<AllocDSNode*> &Allocs) {
333 vector<bool> ReachableShadowNodes(ShadowNodes.size());
334 vector<bool> ReachableAllocNodes (AllocNodes.size());
335
336 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
337
338 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
339 if (ReachableAllocNodes[i])
340 Allocs.push_back(AllocNodes[i]);
341}
342
343// getNonEscapingAllocations - Add all allocations that do not escape the
344// current function to the specified vector.
345//
346void FunctionDSGraph::getNonEscapingAllocations(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}