blob: 06385d4b12c8548b186f1547f1c2a2f8f433e134 [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>
Anand Shuklaa9284032002-06-25 20:35:19 +000022#include <iostream>
Chris Lattnerbb2a28f2002-03-26 22:39:06 +000023
Chris Lattner2ba3a722002-03-27 19:48:03 +000024//#define DEBUG_NODE_ELIMINATE 1
25
Chris Lattner0b7c85c2002-03-31 19:57:44 +000026static void DestroyFirstNodeOfPair(DSNode *N1, DSNode *N2) {
27#ifdef DEBUG_NODE_ELIMINATE
Anand Shuklaa9284032002-06-25 20:35:19 +000028 std::cerr << "Found Indistinguishable Node:\n";
29 N1->print(std::cerr);
Chris Lattner0b7c85c2002-03-31 19:57:44 +000030#endif
31
32 // The nodes can be merged. Make sure that N2 contains all of the
33 // outgoing edges (fields) that N1 does...
34 //
35 assert(N1->getNumLinks() == N2->getNumLinks() &&
36 "Same type, diff # fields?");
37 for (unsigned i = 0, e = N1->getNumLinks(); i != e; ++i)
38 N2->getLink(i).add(N1->getLink(i));
39
40 // Now make sure that all of the nodes that point to N1 also point to the node
41 // that we are merging it with...
42 //
43 const std::vector<PointerValSet*> &Refs = N1->getReferrers();
44 for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
45 PointerValSet &PVS = *Refs[i];
46
47 bool RanOnce = false;
48 for (unsigned j = 0, je = PVS.size(); j != je; ++j)
49 if (PVS[j].Node == N1) {
50 RanOnce = true;
51 PVS.add(PointerVal(N2, PVS[j].Index));
52 }
53
54 assert(RanOnce && "Node on user set but cannot find the use!");
55 }
56
Chris Lattneree7eafa2002-04-27 02:28:41 +000057 N1->mergeInto(N2);
Chris Lattner0b7c85c2002-03-31 19:57:44 +000058 N1->removeAllIncomingEdges();
59 delete N1;
60}
Chris Lattner1120c8b2002-03-28 17:56:03 +000061
62// isIndistinguishableNode - A node is indistinguishable if some other node
63// has exactly the same incoming links to it and if the node considers itself
64// to be the same as the other node...
Chris Lattner9d42a1d2002-03-27 00:55:13 +000065//
Chris Lattner7d093d42002-03-28 19:16:48 +000066static bool isIndistinguishableNode(DSNode *DN) {
Chris Lattner1120c8b2002-03-28 17:56:03 +000067 if (DN->getReferrers().empty()) { // No referrers...
Chris Lattner7650b942002-04-16 20:39:59 +000068 if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN)) {
69 delete DN;
Chris Lattner1120c8b2002-03-28 17:56:03 +000070 return true; // Node is trivially dead
Chris Lattner7650b942002-04-16 20:39:59 +000071 } else
Chris Lattner1120c8b2002-03-28 17:56:03 +000072 return false;
73 }
74
Chris Lattner9d42a1d2002-03-27 00:55:13 +000075 // Pick a random referrer... Ptr is the things that the referrer points to.
Chris Lattner1120c8b2002-03-28 17:56:03 +000076 // Since DN is in the Ptr set, look through the set seeing if there are any
77 // other nodes that are exactly equilivant to DN (with the exception of node
78 // type), but are not DN. If anything exists, then DN is indistinguishable.
Chris Lattner9d42a1d2002-03-27 00:55:13 +000079 //
Chris Lattner44cf3902002-03-31 07:14:52 +000080
81 DSNode *IndFrom = 0;
Chris Lattner1120c8b2002-03-28 17:56:03 +000082 const std::vector<PointerValSet*> &Refs = DN->getReferrers();
83 for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
84 const PointerValSet &Ptr = *Refs[R];
Chris Lattner9d42a1d2002-03-27 00:55:13 +000085
Chris Lattner1120c8b2002-03-28 17:56:03 +000086 for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
87 DSNode *N2 = Ptr[i].Node;
88 if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
89 DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {
90
Chris Lattner44cf3902002-03-31 07:14:52 +000091 IndFrom = N2;
92 R = RE-1;
93 break;
Chris Lattner1120c8b2002-03-28 17:56:03 +000094 }
95 }
96 }
Chris Lattner9d42a1d2002-03-27 00:55:13 +000097
Chris Lattner44cf3902002-03-31 07:14:52 +000098 // If we haven't found an equivalent node to merge with, see if one of the
99 // nodes pointed to by this node is equivalent to this one...
100 //
101 if (IndFrom == 0) {
102 unsigned NumOutgoing = DN->getNumOutgoingLinks();
103 for (DSNode::iterator I = DN->begin(), E = DN->end(); I != E; ++I) {
104 DSNode *Linked = *I;
105 if (Linked != DN && Linked->getNumOutgoingLinks() == NumOutgoing &&
106 DN->getType() == Linked->getType() && DN->isEquivalentTo(Linked)) {
107#if 0
108 // Make sure the leftover node contains links to everything we do...
109 for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
110 Linked->getLink(i).add(DN->getLink(i));
111#endif
112
113 IndFrom = Linked;
114 break;
115 }
116 }
117 }
118
119
120 // If DN is indistinguishable from some other node, merge them now...
121 if (IndFrom == 0)
122 return false; // Otherwise, nothing found, perhaps next time....
123
Chris Lattner0b7c85c2002-03-31 19:57:44 +0000124 DestroyFirstNodeOfPair(DN, IndFrom);
Chris Lattner44cf3902002-03-31 07:14:52 +0000125 return true;
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000126}
127
Chris Lattner1120c8b2002-03-28 17:56:03 +0000128template<typename NodeTy>
Chris Lattner44cf3902002-03-31 07:14:52 +0000129static bool removeIndistinguishableNodes(std::vector<NodeTy*> &Nodes) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000130 bool Changed = false;
131 std::vector<NodeTy*>::iterator I = Nodes.begin();
132 while (I != Nodes.end()) {
133 if (isIndistinguishableNode(*I)) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000134 I = Nodes.erase(I);
135 Changed = true;
136 } else {
137 ++I;
138 }
139 }
140 return Changed;
141}
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000142
Chris Lattner44cf3902002-03-31 07:14:52 +0000143template<typename NodeTy>
144static bool removeIndistinguishableNodePairs(std::vector<NodeTy*> &Nodes) {
145 bool Changed = false;
146 std::vector<NodeTy*>::iterator I = Nodes.begin();
147 while (I != Nodes.end()) {
148 NodeTy *N1 = *I++;
149 for (std::vector<NodeTy*>::iterator I2 = I, I2E = Nodes.end();
150 I2 != I2E; ++I2) {
151 NodeTy *N2 = *I2;
152 if (N1->isEquivalentTo(N2)) {
Chris Lattner0b7c85c2002-03-31 19:57:44 +0000153 DestroyFirstNodeOfPair(N1, N2);
Chris Lattner44cf3902002-03-31 07:14:52 +0000154 --I;
155 I = Nodes.erase(I);
156 Changed = true;
157 break;
158 }
159 }
160 }
161 return Changed;
162}
163
164
165
Chris Lattner7d093d42002-03-28 19:16:48 +0000166// UnlinkUndistinguishableNodes - Eliminate shadow nodes that are not
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000167// distinguishable from some other node in the graph...
168//
Chris Lattner7d093d42002-03-28 19:16:48 +0000169bool FunctionDSGraph::UnlinkUndistinguishableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000170 // Loop over all of the shadow nodes, checking to see if they are
171 // indistinguishable from some other node. If so, eliminate the node!
172 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000173 return
Chris Lattner44cf3902002-03-31 07:14:52 +0000174 removeIndistinguishableNodes(AllocNodes) |
175 removeIndistinguishableNodes(ShadowNodes) |
Chris Lattnerf30185f2002-04-01 00:13:56 +0000176 removeIndistinguishableNodePairs(CallNodes) |
Chris Lattner44cf3902002-03-31 07:14:52 +0000177 removeIndistinguishableNodePairs(GlobalNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000178}
179
Chris Lattner1120c8b2002-03-28 17:56:03 +0000180static void MarkReferredNodesReachable(DSNode *N,
Anand Shuklaa9284032002-06-25 20:35:19 +0000181 std::vector<ShadowDSNode*> &ShadowNodes,
182 std::vector<bool> &ReachableShadowNodes,
183 std::vector<AllocDSNode*> &AllocNodes,
184 std::vector<bool> &ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000185
186static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
Anand Shuklaa9284032002-06-25 20:35:19 +0000187 std::vector<ShadowDSNode*> &ShadowNodes,
188 std::vector<bool> &ReachableShadowNodes,
189 std::vector<AllocDSNode*> &AllocNodes,
190 std::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,
Anand Shuklaa9284032002-06-25 20:35:19 +0000198 std::vector<ShadowDSNode*> &ShadowNodes,
199 std::vector<bool> &ReachableShadowNodes,
200 std::vector<AllocDSNode*> &AllocNodes,
201 std::vector<bool> &ReachableAllocNodes) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000202 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)) {
Anand Shuklaa9284032002-06-25 20:35:19 +0000206 std::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)) {
Anand Shuklaa9284032002-06-25 20:35:19 +0000212 std::vector<AllocDSNode*>::iterator I =
Chris Lattner1120c8b2002-03-28 17:56:03 +0000213 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(
Anand Shuklaa9284032002-06-25 20:35:19 +0000233 std::vector<bool> &ReachableShadowNodes,
234 std::vector<bool> &ReachableAllocNodes) {
Chris Lattner4dc1f822002-03-28 19:33:00 +0000235 // 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 //
Chris Lattner4dc1f822002-03-28 19:33:00 +0000239 for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
240 MarkReferredNodesReachable(GlobalNodes[i],
241 ShadowNodes, ReachableShadowNodes,
242 AllocNodes, ReachableAllocNodes);
243
244 for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
245 MarkReferredNodesReachable(CallNodes[i],
246 ShadowNodes, ReachableShadowNodes,
247 AllocNodes, ReachableAllocNodes);
248
249 // Mark all nodes in the return set as being reachable...
250 MarkReferredNodeSetReachable(RetNode,
251 ShadowNodes, ReachableShadowNodes,
252 AllocNodes, ReachableAllocNodes);
253}
254
Chris Lattner7d093d42002-03-28 19:16:48 +0000255bool FunctionDSGraph::RemoveUnreachableNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000256 bool Changed = false;
Chris Lattner212be2e2002-04-16 03:44:03 +0000257 bool LocalChange = true;
258
259 while (LocalChange) {
260 LocalChange = false;
Chris Lattner1120c8b2002-03-28 17:56:03 +0000261 // Reachable*Nodes - Contains true if there is an edge from a reachable
262 // node to the numbered node...
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000263 //
Anand Shuklaa9284032002-06-25 20:35:19 +0000264 std::vector<bool> ReachableShadowNodes(ShadowNodes.size());
265 std::vector<bool> ReachableAllocNodes (AllocNodes.size());
Chris Lattner4dc1f822002-03-28 19:33:00 +0000266
267 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000268
269 // Mark all nodes in the value map as being reachable...
270 for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
271 E = ValueMap.end(); I != E; ++I)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000272 MarkReferredNodeSetReachable(I->second,
273 ShadowNodes, ReachableShadowNodes,
274 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000275
276 // At this point, all reachable shadow nodes have a true value in the
277 // Reachable vector. This means that any shadow nodes without an entry in
278 // the reachable vector are not reachable and should be removed. This is
279 // a two part process, because we must drop all references before we delete
280 // the shadow nodes [in case cycles exist].
281 //
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000282 for (unsigned i = 0; i != ShadowNodes.size(); ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000283 if (!ReachableShadowNodes[i]) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000284 // Track all unreachable nodes...
Chris Lattner2ba3a722002-03-27 19:48:03 +0000285#if DEBUG_NODE_ELIMINATE
Anand Shuklaa9284032002-06-25 20:35:19 +0000286 std::cerr << "Unreachable node eliminated:\n";
287 ShadowNodes[i]->print(std::cerr);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000288#endif
Chris Lattner1120c8b2002-03-28 17:56:03 +0000289 ShadowNodes[i]->removeAllIncomingEdges();
290 delete ShadowNodes[i];
291
292 // Remove from reachable...
293 ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000294 ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry
295 --i; // Don't skip the next node.
Chris Lattner212be2e2002-04-16 03:44:03 +0000296 LocalChange = Changed = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000297 }
298
Chris Lattner1120c8b2002-03-28 17:56:03 +0000299 for (unsigned i = 0; i != AllocNodes.size(); ++i)
300 if (!ReachableAllocNodes[i]) {
301 // Track all unreachable nodes...
302#if DEBUG_NODE_ELIMINATE
Anand Shuklaa9284032002-06-25 20:35:19 +0000303 std::cerr << "Unreachable node eliminated:\n";
304 AllocNodes[i]->print(std::cerr);
Chris Lattner1120c8b2002-03-28 17:56:03 +0000305#endif
306 AllocNodes[i]->removeAllIncomingEdges();
307 delete AllocNodes[i];
308
309 // Remove from reachable...
310 ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
311 AllocNodes.erase(AllocNodes.begin()+i); // Remove node entry
312 --i; // Don't skip the next node.
Chris Lattner212be2e2002-04-16 03:44:03 +0000313 LocalChange = Changed = true;
Chris Lattner1120c8b2002-03-28 17:56:03 +0000314 }
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000315 }
Chris Lattner212be2e2002-04-16 03:44:03 +0000316
Chris Lattner7650b942002-04-16 20:39:59 +0000317 // Loop over the global nodes, removing nodes that have no edges into them or
318 // out of them.
319 //
Chris Lattner212be2e2002-04-16 03:44:03 +0000320 for (std::vector<GlobalDSNode*>::iterator I = GlobalNodes.begin();
321 I != GlobalNodes.end(); )
Chris Lattner7650b942002-04-16 20:39:59 +0000322 if ((*I)->getReferrers().empty()) {
323 GlobalDSNode *GDN = *I;
324 bool NoLinks = true; // Make sure there are no outgoing links...
325 for (unsigned i = 0, e = GDN->getNumLinks(); i != e; ++i)
326 if (!GDN->getLink(i).empty()) {
327 NoLinks = false;
328 break;
329 }
330 if (NoLinks) {
331 delete GDN;
332 I = GlobalNodes.erase(I); // Remove the node...
333 Changed = true;
334 } else {
335 ++I;
336 }
Chris Lattner212be2e2002-04-16 03:44:03 +0000337 } else {
338 ++I;
339 }
Chris Lattner7650b942002-04-16 20:39:59 +0000340
Chris Lattner212be2e2002-04-16 03:44:03 +0000341 return Changed;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000342}
Chris Lattner4dc1f822002-03-28 19:33:00 +0000343
344
345
346
347// getEscapingAllocations - Add all allocations that escape the current
348// function to the specified vector.
349//
Anand Shuklaa9284032002-06-25 20:35:19 +0000350void FunctionDSGraph::getEscapingAllocations(std::vector<AllocDSNode*> &Allocs) {
351 std::vector<bool> ReachableShadowNodes(ShadowNodes.size());
352 std::vector<bool> ReachableAllocNodes (AllocNodes.size());
Chris Lattner4dc1f822002-03-28 19:33:00 +0000353
354 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
355
356 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
357 if (ReachableAllocNodes[i])
358 Allocs.push_back(AllocNodes[i]);
359}
360
361// getNonEscapingAllocations - Add all allocations that do not escape the
362// current function to the specified vector.
363//
Anand Shuklaa9284032002-06-25 20:35:19 +0000364void FunctionDSGraph::getNonEscapingAllocations(std::vector<AllocDSNode*> &Allocs) {
365 std::vector<bool> ReachableShadowNodes(ShadowNodes.size());
366 std::vector<bool> ReachableAllocNodes (AllocNodes.size());
Chris Lattner4dc1f822002-03-28 19:33:00 +0000367
368 MarkEscapeableNodesReachable(ReachableShadowNodes, ReachableAllocNodes);
369
370 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
371 if (!ReachableAllocNodes[i])
372 Allocs.push_back(AllocNodes[i]);
373}