blob: 904ec2af5649b08d924dc5178bfedd233fc307d7 [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
22// removeEdgesTo - Erase all edges in the graph that point to the specified node
23static void removeEdgesTo(DSNode *Node) {
24 while (!Node->getReferrers().empty()) {
25 PointerValSet *PVS = Node->getReferrers().back();
26 PVS->removePointerTo(Node);
27 }
28}
29
30// UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not
31// distinguishable from some other node in the graph...
32//
33void FunctionDSGraph::UnlinkUndistinguishableShadowNodes() {
34 // TODO:
35}
36
37
38
39
40
41
42static void MarkReferredNodesReachable(DSNode *N, vector<ShadowDSNode*> &Nodes,
43 vector<bool> &Reachable);
44
45static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
46 vector<ShadowDSNode*> &Nodes,
47 vector<bool> &Reachable) {
48 for (unsigned i = 0, e = PVS.size(); i != e; ++i)
49 if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(PVS[i].Node))
50 MarkReferredNodesReachable(Shad, Nodes, Reachable);
51}
52
53static void MarkReferredNodesReachable(DSNode *N, vector<ShadowDSNode*> &Nodes,
54 vector<bool> &Reachable) {
55 assert(Nodes.size() == Reachable.size());
56 ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N);
57
58 if (Shad) {
59 vector<ShadowDSNode*>::iterator I =
60 std::find(Nodes.begin(), Nodes.end(), Shad);
61 unsigned i = I-Nodes.begin();
62 if (Reachable[i]) return; // Recursion detected, abort...
63 Reachable[i] = true;
64 }
65
66 for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
67 MarkReferredNodeSetReachable(N->getLink(i), Nodes, Reachable);
68
69 const std::vector<PointerValSet> *Links = N->getAuxLinks();
70 if (Links)
71 for (unsigned i = 0, e = Links->size(); i != e; ++i)
72 MarkReferredNodeSetReachable((*Links)[i], Nodes, Reachable);
73}
74
75void FunctionDSGraph::RemoveUnreachableShadowNodes() {
76 while (1) {
77
78 // Reachable - Contains true if there is an edge from a nonshadow node to
79 // the numbered node...
80 //
81 vector<bool> Reachable(ShadowNodes.size());
82
83 // Mark all shadow nodes that have edges from other nodes as reachable.
84 // Recursively mark any shadow nodes pointed to by the newly live shadow
85 // nodes as also alive.
86 //
87 for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
88 // Loop over all of the nodes referred and mark them live if they are
89 // shadow nodes...
90 MarkReferredNodesReachable(Nodes[i], ShadowNodes, Reachable);
91
92 // Mark all nodes in the return set as being reachable...
93 MarkReferredNodeSetReachable(RetNode, ShadowNodes, Reachable);
94
95 // Mark all nodes in the value map as being reachable...
96 for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
97 E = ValueMap.end(); I != E; ++I)
98 MarkReferredNodeSetReachable(I->second, ShadowNodes, Reachable);
99
100
101 // At this point, all reachable shadow nodes have a true value in the
102 // Reachable vector. This means that any shadow nodes without an entry in
103 // the reachable vector are not reachable and should be removed. This is
104 // a two part process, because we must drop all references before we delete
105 // the shadow nodes [in case cycles exist].
106 //
107 vector<ShadowDSNode*> DeadNodes;
108 for (unsigned i = 0; i != ShadowNodes.size(); ++i)
109 if (!Reachable[i]) {
110 // Track all unreachable nodes...
111#if 0
112 cerr << "Unreachable node eliminated:\n";
113 ShadowNodes[i]->print(cerr);
114#endif
115 DeadNodes.push_back(ShadowNodes[i]);
116 ShadowNodes[i]->dropAllReferences(); // Drop references to other nodes
117 Reachable.erase(Reachable.begin()+i); // Remove from reachable...
118 ShadowNodes.erase(ShadowNodes.begin()+i); // Remove node entry
119 --i; // Don't skip the next node.
120 }
121
122 if (DeadNodes.empty()) return; // No more dead nodes...
123
124 // All dead nodes are in the DeadNodes vector... delete them now.
125 for_each(DeadNodes.begin(), DeadNodes.end(), deleter<DSNode>);
126 }
127}