blob: 39fdd2c5b290a0d10422420b791f88e9a5161d8d [file] [log] [blame]
Chris Lattnerbb2a28f2002-03-26 22:39:06 +00001//===- ShadowNodeEliminate.cpp - Optimize away shadow nodes ---------------===//
2//
3// This file contains two shadow node optimizations:
4// 1. UnlinkUndistinguishableShadowNodes - Often, after unification, shadow
5// 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//
10// 2. RemoveUnreachableShadowNodes - Remove shadow nodes that are not
11// reachable from some other node in the graph. Unreachable shadow nodes
12// are left lying around because other transforms don't go to the trouble
13// or removing them, since this pass exists.
14//
15//===----------------------------------------------------------------------===//
16
17#include "llvm/Analysis/DataStructure.h"
18#include "llvm/Value.h"
19#include "Support/STLExtras.h"
20#include <algorithm>
21
Chris Lattner2ba3a722002-03-27 19:48:03 +000022//#define DEBUG_NODE_ELIMINATE 1
23
Chris Lattner1120c8b2002-03-28 17:56:03 +000024bool AllocDSNode::isEquivalentTo(DSNode *Node) const {
25 if (AllocDSNode *N = dyn_cast<AllocDSNode>(Node))
26 return N->Allocation == Allocation;
27 return false;
28}
29
30bool GlobalDSNode::isEquivalentTo(DSNode *Node) const {
31 if (GlobalDSNode *G = dyn_cast<GlobalDSNode>(Node))
32 return G->Val == Val;
33 return false;
34}
35
36bool CallDSNode::isEquivalentTo(DSNode *Node) const {
37 if (CallDSNode *C = dyn_cast<CallDSNode>(Node))
38 return C->CI == CI && C->ArgLinks == ArgLinks;
39 return false;
40}
41
42bool ArgDSNode::isEquivalentTo(DSNode *Node) const {
43 return false;
44}
45
Chris Lattner9d42a1d2002-03-27 00:55:13 +000046// NodesAreEquivalent - Check to see if the nodes are equivalent in all ways
47// except node type. Since we know N1 is a shadow node, N2 is allowed to be
48// any type.
49//
Chris Lattner1120c8b2002-03-28 17:56:03 +000050bool ShadowDSNode::isEquivalentTo(DSNode *Node) const {
51 return !isCriticalNode(); // Must not be a critical node...
Chris Lattner9d42a1d2002-03-27 00:55:13 +000052}
53
Chris Lattner1120c8b2002-03-28 17:56:03 +000054
55
56// isIndistinguishableNode - A node is indistinguishable if some other node
57// has exactly the same incoming links to it and if the node considers itself
58// to be the same as the other node...
Chris Lattner9d42a1d2002-03-27 00:55:13 +000059//
Chris Lattner1120c8b2002-03-28 17:56:03 +000060bool isIndistinguishableNode(DSNode *DN) {
61 if (DN->getReferrers().empty()) { // No referrers...
62 if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN))
63 return true; // Node is trivially dead
64 else
65 return false;
66 }
67
Chris Lattner9d42a1d2002-03-27 00:55:13 +000068 // Pick a random referrer... Ptr is the things that the referrer points to.
Chris Lattner1120c8b2002-03-28 17:56:03 +000069 // Since DN is in the Ptr set, look through the set seeing if there are any
70 // other nodes that are exactly equilivant to DN (with the exception of node
71 // type), but are not DN. If anything exists, then DN is indistinguishable.
Chris Lattner9d42a1d2002-03-27 00:55:13 +000072 //
Chris Lattner1120c8b2002-03-28 17:56:03 +000073 const std::vector<PointerValSet*> &Refs = DN->getReferrers();
74 for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
75 const PointerValSet &Ptr = *Refs[R];
Chris Lattner9d42a1d2002-03-27 00:55:13 +000076
Chris Lattner1120c8b2002-03-28 17:56:03 +000077 for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
78 DSNode *N2 = Ptr[i].Node;
79 if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
80 DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {
81
82 // Otherwise, the nodes can be merged. Make sure that N2 contains all
83 // of the outgoing edges (fields) that DN does...
84 //
85 assert(DN->getNumLinks() == N2->getNumLinks() &&
86 "Same type, diff # fields?");
87 for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
88 N2->getLink(i).add(DN->getLink(i));
89
90 // Now make sure that all of the nodes that point to the shadow node
91 // also point to the node that we are merging it with...
92 //
93 const std::vector<PointerValSet*> &Refs = DN->getReferrers();
94 for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
95 PointerValSet &PVS = *Refs[i];
96 // FIXME: this is incorrect if the referring pointer has index != 0
97 //
98 PVS.add(N2);
99 }
100 return true;
101 }
102 }
103 }
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000104
105 // Otherwise, nothing found, perhaps next time....
106 return false;
107}
108
Chris Lattner1120c8b2002-03-28 17:56:03 +0000109template<typename NodeTy>
110bool removeIndistinguishableNode(std::vector<NodeTy*> &Nodes) {
111 bool Changed = false;
112 std::vector<NodeTy*>::iterator I = Nodes.begin();
113 while (I != Nodes.end()) {
114 if (isIndistinguishableNode(*I)) {
115#ifdef DEBUG_NODE_ELIMINATE
116 cerr << "Found Indistinguishable Node:\n";
117 (*I)->print(cerr);
118#endif
119 (*I)->removeAllIncomingEdges();
120 delete *I;
121 I = Nodes.erase(I);
122 Changed = true;
123 } else {
124 ++I;
125 }
126 }
127 return Changed;
128}
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000129
130// UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not
131// distinguishable from some other node in the graph...
132//
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000133bool FunctionDSGraph::UnlinkUndistinguishableShadowNodes() {
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000134 // Loop over all of the shadow nodes, checking to see if they are
135 // indistinguishable from some other node. If so, eliminate the node!
136 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000137 return
138 removeIndistinguishableNode(AllocNodes) |
139 removeIndistinguishableNode(ShadowNodes) |
140 removeIndistinguishableNode(GlobalNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000141}
142
Chris Lattner1120c8b2002-03-28 17:56:03 +0000143static void MarkReferredNodesReachable(DSNode *N,
144 vector<ShadowDSNode*> &ShadowNodes,
145 vector<bool> &ReachableShadowNodes,
146 vector<AllocDSNode*> &AllocNodes,
147 vector<bool> &ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000148
149static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
Chris Lattner1120c8b2002-03-28 17:56:03 +0000150 vector<ShadowDSNode*> &ShadowNodes,
151 vector<bool> &ReachableShadowNodes,
152 vector<AllocDSNode*> &AllocNodes,
153 vector<bool> &ReachableAllocNodes) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000154 for (unsigned i = 0, e = PVS.size(); i != e; ++i)
Chris Lattnercdae0b22002-03-28 18:38:38 +0000155 if (isa<ShadowDSNode>(PVS[i].Node) || isa<AllocDSNode>(PVS[i].Node))
Chris Lattner1120c8b2002-03-28 17:56:03 +0000156 MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes,
157 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000158}
159
Chris Lattner1120c8b2002-03-28 17:56:03 +0000160static void MarkReferredNodesReachable(DSNode *N,
161 vector<ShadowDSNode*> &ShadowNodes,
162 vector<bool> &ReachableShadowNodes,
163 vector<AllocDSNode*> &AllocNodes,
164 vector<bool> &ReachableAllocNodes) {
165 assert(ShadowNodes.size() == ReachableShadowNodes.size());
166 assert(AllocNodes.size() == ReachableAllocNodes.size());
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000167
Chris Lattner1120c8b2002-03-28 17:56:03 +0000168 if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N)) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000169 vector<ShadowDSNode*>::iterator I =
Chris Lattner1120c8b2002-03-28 17:56:03 +0000170 std::find(ShadowNodes.begin(), ShadowNodes.end(), Shad);
171 unsigned i = I-ShadowNodes.begin();
172 if (ReachableShadowNodes[i]) return; // Recursion detected, abort...
173 ReachableShadowNodes[i] = true;
174 } else if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(N)) {
175 vector<AllocDSNode*>::iterator I =
176 std::find(AllocNodes.begin(), AllocNodes.end(), Alloc);
177 unsigned i = I-AllocNodes.begin();
178 if (ReachableAllocNodes[i]) return; // Recursion detected, abort...
179 ReachableAllocNodes[i] = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000180 }
181
182 for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000183 MarkReferredNodeSetReachable(N->getLink(i),
184 ShadowNodes, ReachableShadowNodes,
185 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000186
187 const std::vector<PointerValSet> *Links = N->getAuxLinks();
188 if (Links)
189 for (unsigned i = 0, e = Links->size(); i != e; ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000190 MarkReferredNodeSetReachable((*Links)[i],
191 ShadowNodes, ReachableShadowNodes,
192 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000193}
194
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000195bool FunctionDSGraph::RemoveUnreachableShadowNodes() {
196 bool Changed = false;
Chris Lattnercdae0b22002-03-28 18:38:38 +0000197
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000198 while (1) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000199 // Reachable*Nodes - Contains true if there is an edge from a reachable
200 // node to the numbered node...
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000201 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000202 vector<bool> ReachableShadowNodes(ShadowNodes.size());
203 vector<bool> ReachableAllocNodes (AllocNodes.size());
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000204
205 // Mark all shadow nodes that have edges from other nodes as reachable.
206 // Recursively mark any shadow nodes pointed to by the newly live shadow
207 // nodes as also alive.
208 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000209 for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
210 MarkReferredNodesReachable(ArgNodes[i],
211 ShadowNodes, ReachableShadowNodes,
212 AllocNodes, ReachableAllocNodes);
213
214 for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
215 MarkReferredNodesReachable(GlobalNodes[i],
216 ShadowNodes, ReachableShadowNodes,
217 AllocNodes, ReachableAllocNodes);
218
219 for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
220 MarkReferredNodesReachable(CallNodes[i],
221 ShadowNodes, ReachableShadowNodes,
222 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000223
224 // Mark all nodes in the return set as being reachable...
Chris Lattner1120c8b2002-03-28 17:56:03 +0000225 MarkReferredNodeSetReachable(RetNode,
226 ShadowNodes, ReachableShadowNodes,
227 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000228
229 // Mark all nodes in the value map as being reachable...
230 for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
231 E = ValueMap.end(); I != E; ++I)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000232 MarkReferredNodeSetReachable(I->second,
233 ShadowNodes, ReachableShadowNodes,
234 AllocNodes, ReachableAllocNodes);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000235
236 // At this point, all reachable shadow nodes have a true value in the
237 // Reachable vector. This means that any shadow nodes without an entry in
238 // the reachable vector are not reachable and should be removed. This is
239 // a two part process, because we must drop all references before we delete
240 // the shadow nodes [in case cycles exist].
241 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000242 bool LocalChange = false;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000243 for (unsigned i = 0; i != ShadowNodes.size(); ++i)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000244 if (!ReachableShadowNodes[i]) {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000245 // Track all unreachable nodes...
Chris Lattner2ba3a722002-03-27 19:48:03 +0000246#if DEBUG_NODE_ELIMINATE
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000247 cerr << "Unreachable node eliminated:\n";
248 ShadowNodes[i]->print(cerr);
249#endif
Chris Lattner1120c8b2002-03-28 17:56:03 +0000250 ShadowNodes[i]->removeAllIncomingEdges();
251 delete ShadowNodes[i];
252
253 // Remove from reachable...
254 ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000255 ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry
256 --i; // Don't skip the next node.
Chris Lattner1120c8b2002-03-28 17:56:03 +0000257 LocalChange = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000258 }
259
Chris Lattner1120c8b2002-03-28 17:56:03 +0000260 for (unsigned i = 0; i != AllocNodes.size(); ++i)
261 if (!ReachableAllocNodes[i]) {
262 // Track all unreachable nodes...
263#if DEBUG_NODE_ELIMINATE
264 cerr << "Unreachable node eliminated:\n";
265 AllocNodes[i]->print(cerr);
266#endif
267 AllocNodes[i]->removeAllIncomingEdges();
268 delete AllocNodes[i];
269
270 // Remove from reachable...
271 ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
272 AllocNodes.erase(AllocNodes.begin()+i); // Remove node entry
273 --i; // Don't skip the next node.
274 LocalChange = true;
275 }
276
277 if (!LocalChange) return Changed; // No more dead nodes...
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000278
279 Changed = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000280 }
281}