blob: 5a12bb61c70fee9577b1c3c97543e713af57fc99 [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 Lattner1120c8b2002-03-28 17:56:03 +000025
26// isIndistinguishableNode - A node is indistinguishable if some other node
27// has exactly the same incoming links to it and if the node considers itself
28// to be the same as the other node...
Chris Lattner9d42a1d2002-03-27 00:55:13 +000029//
Chris Lattner7d093d42002-03-28 19:16:48 +000030static bool isIndistinguishableNode(DSNode *DN) {
Chris Lattner1120c8b2002-03-28 17:56:03 +000031 if (DN->getReferrers().empty()) { // No referrers...
32 if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN))
33 return true; // Node is trivially dead
34 else
35 return false;
36 }
37
Chris Lattner9d42a1d2002-03-27 00:55:13 +000038 // Pick a random referrer... Ptr is the things that the referrer points to.
Chris Lattner1120c8b2002-03-28 17:56:03 +000039 // Since DN is in the Ptr set, look through the set seeing if there are any
40 // other nodes that are exactly equilivant to DN (with the exception of node
41 // type), but are not DN. If anything exists, then DN is indistinguishable.
Chris Lattner9d42a1d2002-03-27 00:55:13 +000042 //
Chris Lattner44cf3902002-03-31 07:14:52 +000043
44 DSNode *IndFrom = 0;
Chris Lattner1120c8b2002-03-28 17:56:03 +000045 const std::vector<PointerValSet*> &Refs = DN->getReferrers();
46 for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
47 const PointerValSet &Ptr = *Refs[R];
Chris Lattner9d42a1d2002-03-27 00:55:13 +000048
Chris Lattner1120c8b2002-03-28 17:56:03 +000049 for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
50 DSNode *N2 = Ptr[i].Node;
51 if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
52 DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {
53
Chris Lattner44cf3902002-03-31 07:14:52 +000054 IndFrom = N2;
55 R = RE-1;
56 break;
Chris Lattner1120c8b2002-03-28 17:56:03 +000057 }
58 }
59 }
Chris Lattner9d42a1d2002-03-27 00:55:13 +000060
Chris Lattner44cf3902002-03-31 07:14:52 +000061 // If we haven't found an equivalent node to merge with, see if one of the
62 // nodes pointed to by this node is equivalent to this one...
63 //
64 if (IndFrom == 0) {
65 unsigned NumOutgoing = DN->getNumOutgoingLinks();
66 for (DSNode::iterator I = DN->begin(), E = DN->end(); I != E; ++I) {
67 DSNode *Linked = *I;
68 if (Linked != DN && Linked->getNumOutgoingLinks() == NumOutgoing &&
69 DN->getType() == Linked->getType() && DN->isEquivalentTo(Linked)) {
70#if 0
71 // Make sure the leftover node contains links to everything we do...
72 for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
73 Linked->getLink(i).add(DN->getLink(i));
74#endif
75
76 IndFrom = Linked;
77 break;
78 }
79 }
80 }
81
82
83 // If DN is indistinguishable from some other node, merge them now...
84 if (IndFrom == 0)
85 return false; // Otherwise, nothing found, perhaps next time....
86
87 // The nodes can be merged. Make sure that IndFrom contains all of the
88 // outgoing edges (fields) that DN does...
89 //
90 assert(DN->getNumLinks() == IndFrom->getNumLinks() &&
91 "Same type, diff # fields?");
92 for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
93 IndFrom->getLink(i).add(DN->getLink(i));
94
95 // Now make sure that all of the nodes that point to the shadow node also
96 // point to the node that we are merging it with...
97 //
98 for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
99 PointerValSet &PVS = *Refs[i];
100
101 bool RanOnce = false;
102 for (unsigned j = 0, je = PVS.size(); j != je; ++j)
103 if (PVS[j].Node == DN) {
104 RanOnce = true;
105 PVS.add(PointerVal(IndFrom, PVS[j].Index));
106 }
107
108 assert(RanOnce && "Node on user set but cannot find the use!");
109 }
110 return true;
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000111}
112
Chris Lattner1120c8b2002-03-28 17:56:03 +0000113template<typename NodeTy>
Chris Lattner44cf3902002-03-31 07:14:52 +0000114static bool removeIndistinguishableNodes(std::vector<NodeTy*> &Nodes) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000115 bool Changed = false;
116 std::vector<NodeTy*>::iterator I = Nodes.begin();
117 while (I != Nodes.end()) {
118 if (isIndistinguishableNode(*I)) {
119#ifdef DEBUG_NODE_ELIMINATE
120 cerr << "Found Indistinguishable Node:\n";
121 (*I)->print(cerr);
122#endif
123 (*I)->removeAllIncomingEdges();
124 delete *I;
125 I = Nodes.erase(I);
126 Changed = true;
127 } else {
128 ++I;
129 }
130 }
131 return Changed;
132}
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000133
Chris Lattner44cf3902002-03-31 07:14:52 +0000134template<typename NodeTy>
135static bool removeIndistinguishableNodePairs(std::vector<NodeTy*> &Nodes) {
136 bool Changed = false;
137 std::vector<NodeTy*>::iterator I = Nodes.begin();
138 while (I != Nodes.end()) {
139 NodeTy *N1 = *I++;
140 for (std::vector<NodeTy*>::iterator I2 = I, I2E = Nodes.end();
141 I2 != I2E; ++I2) {
142 NodeTy *N2 = *I2;
143 if (N1->isEquivalentTo(N2)) {
144#ifdef DEBUG_NODE_ELIMINATE
145 cerr << "Found Indistinguishable Node:\n";
146 N1->print(cerr);
147#endif
148 N1->removeAllIncomingEdges();
149 delete N1;
150 --I;
151 I = Nodes.erase(I);
152 Changed = true;
153 break;
154 }
155 }
156 }
157 return Changed;
158}
159
160
161
Chris Lattner7d093d42002-03-28 19:16:48 +0000162// UnlinkUndistinguishableNodes - Eliminate shadow nodes that are not
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000163// distinguishable from some other node in the graph...
164//
Chris Lattner7d093d42002-03-28 19:16:48 +0000165bool FunctionDSGraph::UnlinkUndistinguishableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000166 // Loop over all of the shadow nodes, checking to see if they are
167 // indistinguishable from some other node. If so, eliminate the node!
168 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000169 return
Chris Lattner44cf3902002-03-31 07:14:52 +0000170 removeIndistinguishableNodes(AllocNodes) |
171 removeIndistinguishableNodes(ShadowNodes) |
172 //FIXME: We cannot naively remove call nodes here because if there is a
173 // shadow node that is the result of the call, we have to make sure to
174 // merge the shadow node as well!!!
175 // removeIndistinguishableNodePairs(CallNodes) |
176 removeIndistinguishableNodePairs(GlobalNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000177}
178
Chris Lattner1120c8b2002-03-28 17:56:03 +0000179static void MarkReferredNodesReachable(DSNode *N,
180 vector<ShadowDSNode*> &ShadowNodes,
181 vector<bool> &ReachableShadowNodes,
182 vector<AllocDSNode*> &AllocNodes,
183 vector<bool> &ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000184
185static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
Chris Lattner1120c8b2002-03-28 17:56:03 +0000186 vector<ShadowDSNode*> &ShadowNodes,
187 vector<bool> &ReachableShadowNodes,
188 vector<AllocDSNode*> &AllocNodes,
189 vector<bool> &ReachableAllocNodes) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000190 for (unsigned i = 0, e = PVS.size(); i != e; ++i)
Chris Lattnercdae0b22002-03-28 18:38:38 +0000191 if (isa<ShadowDSNode>(PVS[i].Node) || isa<AllocDSNode>(PVS[i].Node))
Chris Lattner1120c8b2002-03-28 17:56:03 +0000192 MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes,
193 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000194}
195
Chris Lattner1120c8b2002-03-28 17:56:03 +0000196static void MarkReferredNodesReachable(DSNode *N,
197 vector<ShadowDSNode*> &ShadowNodes,
198 vector<bool> &ReachableShadowNodes,
199 vector<AllocDSNode*> &AllocNodes,
200 vector<bool> &ReachableAllocNodes) {
201 assert(ShadowNodes.size() == ReachableShadowNodes.size());
202 assert(AllocNodes.size() == ReachableAllocNodes.size());
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000203
Chris Lattner1120c8b2002-03-28 17:56:03 +0000204 if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N)) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000205 vector<ShadowDSNode*>::iterator I =
Chris Lattner1120c8b2002-03-28 17:56:03 +0000206 std::find(ShadowNodes.begin(), ShadowNodes.end(), Shad);
207 unsigned i = I-ShadowNodes.begin();
208 if (ReachableShadowNodes[i]) return; // Recursion detected, abort...
209 ReachableShadowNodes[i] = true;
210 } else if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(N)) {
211 vector<AllocDSNode*>::iterator I =
212 std::find(AllocNodes.begin(), AllocNodes.end(), Alloc);
213 unsigned i = I-AllocNodes.begin();
214 if (ReachableAllocNodes[i]) return; // Recursion detected, abort...
215 ReachableAllocNodes[i] = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000216 }
217
218 for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000219 MarkReferredNodeSetReachable(N->getLink(i),
220 ShadowNodes, ReachableShadowNodes,
221 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000222
223 const std::vector<PointerValSet> *Links = N->getAuxLinks();
224 if (Links)
225 for (unsigned i = 0, e = Links->size(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000226 MarkReferredNodeSetReachable((*Links)[i],
227 ShadowNodes, ReachableShadowNodes,
228 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000229}
230
Chris Lattner4dc1f822002-03-28 19:33:00 +0000231void FunctionDSGraph::MarkEscapeableNodesReachable(
232 vector<bool> &ReachableShadowNodes,
233 vector<bool> &ReachableAllocNodes) {
234 // Mark all shadow nodes that have edges from other nodes as reachable.
235 // Recursively mark any shadow nodes pointed to by the newly live shadow
236 // nodes as also alive.
237 //
238 for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
239 MarkReferredNodesReachable(ArgNodes[i],
240 ShadowNodes, ReachableShadowNodes,
241 AllocNodes, ReachableAllocNodes);
242
243 for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
244 MarkReferredNodesReachable(GlobalNodes[i],
245 ShadowNodes, ReachableShadowNodes,
246 AllocNodes, ReachableAllocNodes);
247
248 for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
249 MarkReferredNodesReachable(CallNodes[i],
250 ShadowNodes, ReachableShadowNodes,
251 AllocNodes, ReachableAllocNodes);
252
253 // Mark all nodes in the return set as being reachable...
254 MarkReferredNodeSetReachable(RetNode,
255 ShadowNodes, ReachableShadowNodes,
256 AllocNodes, ReachableAllocNodes);
257}
258
Chris Lattner7d093d42002-03-28 19:16:48 +0000259bool FunctionDSGraph::RemoveUnreachableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000260 bool Changed = false;
Chris Lattnercdae0b22002-03-28 18:38:38 +0000261
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000262 while (1) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000263 // Reachable*Nodes - Contains true if there is an edge from a reachable
264 // node to the numbered node...
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000265 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000266 vector<bool> ReachableShadowNodes(ShadowNodes.size());
267 vector<bool> ReachableAllocNodes (AllocNodes.size());
Chris Lattner4dc1f822002-03-28 19:33:00 +0000268
269 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000270
271 // Mark all nodes in the value map as being reachable...
272 for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
273 E = ValueMap.end(); I != E; ++I)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000274 MarkReferredNodeSetReachable(I->second,
275 ShadowNodes, ReachableShadowNodes,
276 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000277
278 // At this point, all reachable shadow nodes have a true value in the
279 // Reachable vector. This means that any shadow nodes without an entry in
280 // the reachable vector are not reachable and should be removed. This is
281 // a two part process, because we must drop all references before we delete
282 // the shadow nodes [in case cycles exist].
283 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000284 bool LocalChange = false;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000285 for (unsigned i = 0; i != ShadowNodes.size(); ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000286 if (!ReachableShadowNodes[i]) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000287 // Track all unreachable nodes...
Chris Lattner2ba3a722002-03-27 19:48:03 +0000288#if DEBUG_NODE_ELIMINATE
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000289 cerr << "Unreachable node eliminated:\n";
290 ShadowNodes[i]->print(cerr);
291#endif
Chris Lattner1120c8b2002-03-28 17:56:03 +0000292 ShadowNodes[i]->removeAllIncomingEdges();
293 delete ShadowNodes[i];
294
295 // Remove from reachable...
296 ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000297 ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry
298 --i; // Don't skip the next node.
Chris Lattner1120c8b2002-03-28 17:56:03 +0000299 LocalChange = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000300 }
301
Chris Lattner1120c8b2002-03-28 17:56:03 +0000302 for (unsigned i = 0; i != AllocNodes.size(); ++i)
303 if (!ReachableAllocNodes[i]) {
304 // Track all unreachable nodes...
305#if DEBUG_NODE_ELIMINATE
306 cerr << "Unreachable node eliminated:\n";
307 AllocNodes[i]->print(cerr);
308#endif
309 AllocNodes[i]->removeAllIncomingEdges();
310 delete AllocNodes[i];
311
312 // Remove from reachable...
313 ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
314 AllocNodes.erase(AllocNodes.begin()+i); // Remove node entry
315 --i; // Don't skip the next node.
316 LocalChange = true;
317 }
318
319 if (!LocalChange) return Changed; // No more dead nodes...
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000320
321 Changed = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000322 }
323}
Chris Lattner4dc1f822002-03-28 19:33:00 +0000324
325
326
327
328// getEscapingAllocations - Add all allocations that escape the current
329// function to the specified vector.
330//
331void FunctionDSGraph::getEscapingAllocations(vector<AllocDSNode*> &Allocs) {
332 vector<bool> ReachableShadowNodes(ShadowNodes.size());
333 vector<bool> ReachableAllocNodes (AllocNodes.size());
334
335 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
336
337 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
338 if (ReachableAllocNodes[i])
339 Allocs.push_back(AllocNodes[i]);
340}
341
342// getNonEscapingAllocations - Add all allocations that do not escape the
343// current function to the specified vector.
344//
345void FunctionDSGraph::getNonEscapingAllocations(vector<AllocDSNode*> &Allocs) {
346 vector<bool> ReachableShadowNodes(ShadowNodes.size());
347 vector<bool> ReachableAllocNodes (AllocNodes.size());
348
349 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
350
351 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
352 if (!ReachableAllocNodes[i])
353 Allocs.push_back(AllocNodes[i]);
354}