blob: 3d1319dcf23c4df219ec2db69a675ddd90c9cc0b [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 Lattner9d42a1d2002-03-27 00:55:13 +000024// NodesAreEquivalent - Check to see if the nodes are equivalent in all ways
25// except node type. Since we know N1 is a shadow node, N2 is allowed to be
26// any type.
27//
28static bool NodesAreEquivalent(const ShadowDSNode *N1, const DSNode *N2) {
29 assert(N1 != N2 && "A node is always equivalent to itself!");
30
31 // Perform simple, fast checks first...
Chris Lattner2ba3a722002-03-27 19:48:03 +000032 if (N1->getType() != N2->getType() || // Must have same type...
33 N1->isCriticalNode()) // Must not be a critical node...
34 return false;
35
36#if 0
37 return true;
38#else
Chris Lattner9d42a1d2002-03-27 00:55:13 +000039
40 // The shadow node is considered equivalent if it has a subset of the incoming
41 // edges that N2 does...
42 if (N1->getReferrers().size() > N2->getReferrers().size()) return false;
43
44 // Check to see if the referring (incoming) pointers are all the same...
45 std::vector<PointerValSet*> N1R = N1->getReferrers();
46 std::vector<PointerValSet*> N2R = N2->getReferrers();
47 sort(N1R.begin(), N1R.end());
48 sort(N2R.begin(), N2R.end());
49
50 // The nodes are equivalent if the incoming edges to N1 are a subset of N2.
51 unsigned i1 = 0, e1 = N1R.size();
52 unsigned i2 = 0, e2 = N2R.size();
53 for (; i1 != e1 && i2 < e2; ++i1, ++i2) {
54 while (N1R[i1] > N2R[i2] && i2 < e2)
55 ++i2;
56
57 if (N1R[i1] < N2R[i2]) return false; // Error case...
58 }
59
60 return i1 == e1 && i2 <= e2;
Chris Lattner2ba3a722002-03-27 19:48:03 +000061#endif
Chris Lattner9d42a1d2002-03-27 00:55:13 +000062}
63
64// IndistinguishableShadowNode - A shadow node is indistinguishable if some
65// other node (shadow or otherwise) has exactly the same incoming and outgoing
66// links to it (or if there are no edges coming in, in which it is trivially
67// dead).
68//
69static bool IndistinguishableShadowNode(const ShadowDSNode *SN) {
70 if (SN->getReferrers().empty()) return true; // Node is trivially dead
71
72 // Pick a random referrer... Ptr is the things that the referrer points to.
73 // Since SN is in the Ptr set, look through the set seeing if there are any
74 // other nodes that are exactly equilivant to SN (with the exception of node
75 // type), but are not SN. If anything exists, then SN is indistinguishable.
76 //
77 const PointerValSet &Ptr = *SN->getReferrers()[0];
78
79 for (unsigned i = 0, e = Ptr.size(); i != e; ++i)
80 if (Ptr[i].Index == 0 && Ptr[i].Node != cast<DSNode>(SN) &&
81 NodesAreEquivalent(SN, Ptr[i].Node))
82 return true;
83
84 // Otherwise, nothing found, perhaps next time....
85 return false;
86}
87
Chris Lattnerbb2a28f2002-03-26 22:39:06 +000088
89// UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not
90// distinguishable from some other node in the graph...
91//
Chris Lattner9d42a1d2002-03-27 00:55:13 +000092bool FunctionDSGraph::UnlinkUndistinguishableShadowNodes() {
93 bool Changed = false;
94 // Loop over all of the shadow nodes, checking to see if they are
95 // indistinguishable from some other node. If so, eliminate the node!
96 //
97 for (vector<ShadowDSNode*>::iterator I = ShadowNodes.begin();
98 I != ShadowNodes.end(); )
99 if (IndistinguishableShadowNode(*I)) {
Chris Lattner2ba3a722002-03-27 19:48:03 +0000100#ifdef DEBUG_NODE_ELIMINATE
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000101 cerr << "Found Indistinguishable Shadow Node:\n";
102 (*I)->print(cerr);
Chris Lattner2ba3a722002-03-27 19:48:03 +0000103#endif
104 (*I)->removeAllIncomingEdges();
105 // Don't need to dropAllRefs, because nothing can point to it now
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000106 delete *I;
107
108 I = ShadowNodes.erase(I);
109 Changed = true;
110 } else {
111 ++I;
112 }
113 return Changed;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000114}
115
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000116static void MarkReferredNodesReachable(DSNode *N, vector<ShadowDSNode*> &Nodes,
117 vector<bool> &Reachable);
118
119static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
120 vector<ShadowDSNode*> &Nodes,
121 vector<bool> &Reachable) {
122 for (unsigned i = 0, e = PVS.size(); i != e; ++i)
123 if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(PVS[i].Node))
124 MarkReferredNodesReachable(Shad, Nodes, Reachable);
125}
126
127static void MarkReferredNodesReachable(DSNode *N, vector<ShadowDSNode*> &Nodes,
128 vector<bool> &Reachable) {
129 assert(Nodes.size() == Reachable.size());
130 ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N);
131
132 if (Shad) {
133 vector<ShadowDSNode*>::iterator I =
134 std::find(Nodes.begin(), Nodes.end(), Shad);
135 unsigned i = I-Nodes.begin();
136 if (Reachable[i]) return; // Recursion detected, abort...
137 Reachable[i] = true;
138 }
139
140 for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
141 MarkReferredNodeSetReachable(N->getLink(i), Nodes, Reachable);
142
143 const std::vector<PointerValSet> *Links = N->getAuxLinks();
144 if (Links)
145 for (unsigned i = 0, e = Links->size(); i != e; ++i)
146 MarkReferredNodeSetReachable((*Links)[i], Nodes, Reachable);
147}
148
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000149bool FunctionDSGraph::RemoveUnreachableShadowNodes() {
150 bool Changed = false;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000151 while (1) {
152
153 // Reachable - Contains true if there is an edge from a nonshadow node to
154 // the numbered node...
155 //
156 vector<bool> Reachable(ShadowNodes.size());
157
158 // Mark all shadow nodes that have edges from other nodes as reachable.
159 // Recursively mark any shadow nodes pointed to by the newly live shadow
160 // nodes as also alive.
161 //
162 for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
163 // Loop over all of the nodes referred and mark them live if they are
164 // shadow nodes...
165 MarkReferredNodesReachable(Nodes[i], ShadowNodes, Reachable);
166
167 // Mark all nodes in the return set as being reachable...
168 MarkReferredNodeSetReachable(RetNode, ShadowNodes, Reachable);
169
170 // Mark all nodes in the value map as being reachable...
171 for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
172 E = ValueMap.end(); I != E; ++I)
173 MarkReferredNodeSetReachable(I->second, ShadowNodes, Reachable);
174
175
176 // At this point, all reachable shadow nodes have a true value in the
177 // Reachable vector. This means that any shadow nodes without an entry in
178 // the reachable vector are not reachable and should be removed. This is
179 // a two part process, because we must drop all references before we delete
180 // the shadow nodes [in case cycles exist].
181 //
182 vector<ShadowDSNode*> DeadNodes;
183 for (unsigned i = 0; i != ShadowNodes.size(); ++i)
184 if (!Reachable[i]) {
185 // Track all unreachable nodes...
Chris Lattner2ba3a722002-03-27 19:48:03 +0000186#if DEBUG_NODE_ELIMINATE
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000187 cerr << "Unreachable node eliminated:\n";
188 ShadowNodes[i]->print(cerr);
189#endif
190 DeadNodes.push_back(ShadowNodes[i]);
191 ShadowNodes[i]->dropAllReferences(); // Drop references to other nodes
192 Reachable.erase(Reachable.begin()+i); // Remove from reachable...
193 ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry
194 --i; // Don't skip the next node.
195 }
196
Chris Lattner9d42a1d2002-03-27 00:55:13 +0000197 if (DeadNodes.empty()) return Changed; // No more dead nodes...
198
199 Changed = true;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000200
201 // All dead nodes are in the DeadNodes vector... delete them now.
202 for_each(DeadNodes.begin(), DeadNodes.end(), deleter<DSNode>);
203 }
204}