blob: b45a2f9e23bc39dbb00e3141c682e4d8ac94e258 [file] [log] [blame]
Vikram S. Adveaaeee752002-07-30 22:06:40 +00001//===- TopDownClosure.cpp - Compute the top-down interprocedure closure ---===//
2//
3// This file implements the TDDataStructures class, which represents the
4// Top-down Interprocedural closure of the data structure graph over the
5// program. This is useful (but not strictly necessary?) for applications
6// like pointer analysis.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Analysis/DataStructure.h"
11#include "llvm/Module.h"
12#include "llvm/DerivedTypes.h"
Chris Lattnerfccd06f2002-10-01 22:33:50 +000013#include "Support/Statistic.h"
Chris Lattner18f07a12003-07-01 16:28:11 +000014#include "DSCallSiteIterator.h"
Vikram S. Adveaaeee752002-07-30 22:06:40 +000015
Chris Lattner4923d1b2003-02-03 22:51:28 +000016namespace {
17 RegisterAnalysis<TDDataStructures> // Register the pass
Chris Lattner312edd32003-06-28 22:14:55 +000018 Y("tddatastructure", "Top-down Data Structure Analysis");
Chris Lattner4923d1b2003-02-03 22:51:28 +000019}
Vikram S. Adveaaeee752002-07-30 22:06:40 +000020
Chris Lattneraa0b4682002-11-09 21:12:07 +000021// run - Calculate the top down data structure graphs for each function in the
22// program.
23//
24bool TDDataStructures::run(Module &M) {
25 BUDataStructures &BU = getAnalysis<BUDataStructures>();
Chris Lattner312edd32003-06-28 22:14:55 +000026 GlobalsGraph = new DSGraph(BU.getGlobalsGraph());
Chris Lattneraa0b4682002-11-09 21:12:07 +000027
28 // Calculate top-down from main...
29 if (Function *F = M.getMainFunction())
Chris Lattner18f07a12003-07-01 16:28:11 +000030 calculateGraphFrom(*F);
Chris Lattneraa0b4682002-11-09 21:12:07 +000031
32 // Next calculate the graphs for each function unreachable function...
33 for (Module::reverse_iterator I = M.rbegin(), E = M.rend(); I != E; ++I)
Chris Lattner18f07a12003-07-01 16:28:11 +000034 if (!I->isExternal() && !DSInfo.count(&*I))
35 calculateGraphFrom(*I);
Chris Lattneraa0b4682002-11-09 21:12:07 +000036
Chris Lattneraa0b4682002-11-09 21:12:07 +000037 return false;
38}
39
Vikram S. Adveaaeee752002-07-30 22:06:40 +000040// releaseMemory - If the pass pipeline is done with this pass, we can release
41// our memory... here...
42//
Chris Lattner4923d1b2003-02-03 22:51:28 +000043// FIXME: This should be releaseMemory and will work fine, except that LoadVN
44// has no way to extend the lifetime of the pass, which screws up ds-aa.
45//
46void TDDataStructures::releaseMyMemory() {
Chris Lattner3d162902003-06-30 04:53:08 +000047 for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
48 E = DSInfo.end(); I != E; ++I) {
49 I->second->getReturnNodes().erase(I->first);
50 if (I->second->getReturnNodes().empty())
51 delete I->second;
52 }
Vikram S. Adveaaeee752002-07-30 22:06:40 +000053
54 // Empty map so next time memory is released, data structures are not
55 // re-deleted.
56 DSInfo.clear();
Chris Lattneraa0b4682002-11-09 21:12:07 +000057 delete GlobalsGraph;
58 GlobalsGraph = 0;
Vikram S. Adveaaeee752002-07-30 22:06:40 +000059}
60
Vikram S. Adveaaeee752002-07-30 22:06:40 +000061
Chris Lattner7a211632002-11-08 21:28:37 +000062DSGraph &TDDataStructures::getOrCreateDSGraph(Function &F) {
63 DSGraph *&G = DSInfo[&F];
64 if (G == 0) { // Not created yet? Clone BU graph...
65 G = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F));
66 G->getAuxFunctionCalls().clear();
Chris Lattner24d80072003-02-04 00:59:32 +000067 G->setPrintAuxCalls();
Chris Lattneraa0b4682002-11-09 21:12:07 +000068 G->setGlobalsGraph(GlobalsGraph);
Chris Lattner7a211632002-11-08 21:28:37 +000069 }
70 return *G;
71}
Vikram S. Adve26b98262002-10-20 21:41:02 +000072
Chris Lattnerdea81462003-06-29 22:37:07 +000073
74/// FunctionHasCompleteArguments - This function returns true if it is safe not
75/// to mark arguments to the function complete.
76///
77/// FIXME: Need to check if all callers have been found, or rather if a
78/// funcpointer escapes!
79///
80static bool FunctionHasCompleteArguments(Function &F) {
81 return F.hasInternalLinkage();
82}
83
Chris Lattner18f07a12003-07-01 16:28:11 +000084void TDDataStructures::ComputePostOrder(Function &F,hash_set<DSGraph*> &Visited,
85 std::vector<DSGraph*> &PostOrder,
86 const BUDataStructures::ActualCalleesTy &ActualCallees) {
87 if (F.isExternal()) return;
88 DSGraph &G = getOrCreateDSGraph(F);
89 if (Visited.count(&G)) return;
90 Visited.insert(&G);
91
92 // Recursively traverse all of the callee graphs.
93 const std::vector<DSCallSite> &FunctionCalls = G.getFunctionCalls();
Chris Lattnerdea81462003-06-29 22:37:07 +000094
Chris Lattner18f07a12003-07-01 16:28:11 +000095 for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
96 std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
97 BUDataStructures::ActualCalleesTy::const_iterator>
98 IP = ActualCallees.equal_range(&FunctionCalls[i].getCallInst());
Vikram S. Adveaaeee752002-07-30 22:06:40 +000099
Chris Lattner18f07a12003-07-01 16:28:11 +0000100 for (BUDataStructures::ActualCalleesTy::const_iterator I = IP.first;
101 I != IP.second; ++I)
102 ComputePostOrder(*I->second, Visited, PostOrder, ActualCallees);
103 }
Chris Lattner198be222002-10-21 19:47:18 +0000104
Chris Lattner18f07a12003-07-01 16:28:11 +0000105 PostOrder.push_back(&G);
106}
107
108
109
110void TDDataStructures::calculateGraphFrom(Function &F) {
111 // We want to traverse the call graph in reverse post-order. To do this, we
112 // calculate a post-order traversal, then reverse it.
113 hash_set<DSGraph*> VisitedGraph;
114 std::vector<DSGraph*> PostOrder;
115 ComputePostOrder(F, VisitedGraph, PostOrder,
116 getAnalysis<BUDataStructures>().getActualCallees());
117 VisitedGraph.clear(); // Release memory!
118
119 // Visit each of the graphs in reverse post-order now!
120 while (!PostOrder.empty()) {
121 inlineGraphIntoCallees(*PostOrder.back());
122 PostOrder.pop_back();
123 }
124}
125
126
127void TDDataStructures::inlineGraphIntoCallees(DSGraph &Graph) {
Chris Lattner4f2cfc02003-02-10 18:16:36 +0000128 // Recompute the Incomplete markers and eliminate unreachable nodes.
129 Graph.maskIncompleteMarkers();
Chris Lattner18f07a12003-07-01 16:28:11 +0000130 unsigned Flags = true /* FIXME!! FunctionHasCompleteArguments(F)*/ ?
Chris Lattnerdea81462003-06-29 22:37:07 +0000131 DSGraph::IgnoreFormalArgs : DSGraph::MarkFormalArgs;
Chris Lattner4f2cfc02003-02-10 18:16:36 +0000132 Graph.markIncompleteNodes(Flags | DSGraph::IgnoreGlobals);
133 Graph.removeDeadNodes(DSGraph::RemoveUnreachableGlobals);
134
Chris Lattner18f07a12003-07-01 16:28:11 +0000135 DSCallSiteIterator CalleeI = DSCallSiteIterator::begin_std(Graph);
136 DSCallSiteIterator CalleeE = DSCallSiteIterator::end_std(Graph);
Chris Lattnerce2d1322002-11-08 22:26:43 +0000137
Chris Lattner18f07a12003-07-01 16:28:11 +0000138 if (CalleeI == CalleeE) {
139 DEBUG(std::cerr << " [TD] No callees for: " << Graph.getFunctionNames()
140 << "\n");
141 return;
142 }
143
144 // Loop over all of the call sites, building a multi-map from Callees to
145 // DSCallSite*'s. With this map we can then loop over each callee, cloning
146 // this graph once into it, then resolving arguments.
147 //
148 std::multimap<std::pair<DSGraph*,Function*>, const DSCallSite*> CalleeSites;
149 for (; CalleeI != CalleeE; ++CalleeI)
150 if (!(*CalleeI)->isExternal()) {
151 // We should have already created the graph here...
152 if (!DSInfo.count(*CalleeI))
153 std::cerr << "WARNING: TD pass, did not know about callee: '"
154 << (*CalleeI)->getName() << "'\n";
155
156 DSGraph &IG = getOrCreateDSGraph(**CalleeI);
157 if (&IG != &Graph)
158 CalleeSites.insert(std::make_pair(std::make_pair(&IG, *CalleeI),
159 &CalleeI.getCallSite()));
160 }
161
162 // Now that we have information about all of the callees, propagate the
163 // current graph into the callees.
164 //
165 DEBUG(std::cerr << " [TD] Inlining '" << Graph.getFunctionNames() <<"' into "
166 << CalleeSites.size() << " callees.\n");
167
168 // Loop over all the callees...
169 for (std::multimap<std::pair<DSGraph*, Function*>,
170 const DSCallSite*>::iterator I = CalleeSites.begin(),
171 E = CalleeSites.end(); I != E; ) {
172 DSGraph &CG = *I->first.first;
173
174 DEBUG(std::cerr << " [TD] Inlining graph into callee graph '"
175 << CG.getFunctionNames() << "'\n");
176
177 // Clone our current graph into the callee...
178 DSGraph::ScalarMapTy OldValMap;
179 DSGraph::NodeMapTy OldNodeMap;
180 DSGraph::ReturnNodesTy ReturnNodes;
181 CG.cloneInto(Graph, OldValMap, ReturnNodes, OldNodeMap,
182 DSGraph::StripModRefBits |
183 DSGraph::KeepAllocaBit | DSGraph::DontCloneCallNodes |
184 DSGraph::DontCloneAuxCallNodes);
185 OldValMap.clear(); // We don't care about the ValMap
186 ReturnNodes.clear(); // We don't care about return values either
187
188 // Loop over all of the invocation sites of the callee, resolving
189 // arguments to our graph. This loop may iterate multiple times if the
190 // current function calls this callee multiple times with different
191 // signatures.
192 //
193 for (; I != E && I->first.first == &CG; ++I) {
194 Function &Callee = *I->first.second;
195 DEBUG(std::cerr << "\t [TD] Merging args for callee '"
196 << Callee.getName() << "'\n");
197
198 // Map call site into callee graph
199 DSCallSite NewCS(*I->second, OldNodeMap);
200
201 // Resolve the return values...
202 NewCS.getRetVal().mergeWith(CG.getReturnNodeFor(Callee));
203
204 // Resolve all of the arguments...
205 Function::aiterator AI = Callee.abegin();
206 for (unsigned i = 0, e = NewCS.getNumPtrArgs();
207 i != e && AI != Callee.aend(); ++i, ++AI) {
208 // Advance the argument iterator to the first pointer argument...
209 while (AI != Callee.aend() && !DS::isPointerType(AI->getType()))
210 ++AI;
211 if (AI == Callee.aend()) break;
212
213 // Add the link from the argument scalar to the provided value
214 DSNodeHandle &NH = CG.getNodeForValue(AI);
215 assert(NH.getNode() && "Pointer argument without scalarmap entry?");
216 NH.mergeWith(NewCS.getPtrArg(i));
Chris Lattnere0fbd482003-02-09 18:42:43 +0000217 }
Chris Lattner923fc052003-02-05 21:59:58 +0000218 }
Chris Lattner0e744122002-10-17 04:26:54 +0000219
Chris Lattner18f07a12003-07-01 16:28:11 +0000220 // Done with the nodemap...
221 OldNodeMap.clear();
Chris Lattner7a211632002-11-08 21:28:37 +0000222
Chris Lattner18f07a12003-07-01 16:28:11 +0000223 // Recompute the Incomplete markers and eliminate unreachable nodes.
224 CG.removeTriviallyDeadNodes();
225 //CG.maskIncompleteMarkers();
226 //CG.markIncompleteNodes(DSGraph::MarkFormalArgs | DSGraph::IgnoreGlobals);
227 //CG.removeDeadNodes(DSGraph::RemoveUnreachableGlobals);
Chris Lattnere0fbd482003-02-09 18:42:43 +0000228 }
Chris Lattner18f07a12003-07-01 16:28:11 +0000229
230 DEBUG(std::cerr << " [TD] Done inlining into callees for: "
231 << Graph.getFunctionNames() << " [" << Graph.getGraphSize() << "+"
232 << Graph.getFunctionCalls().size() << "]\n");
233
234#if 0
235 // Loop over all the callees... making sure they are all resolved now...
236 Function *LastFunc = 0;
237 for (std::multimap<Function*, const DSCallSite*>::iterator
238 I = CalleeSites.begin(), E = CalleeSites.end(); I != E; ++I)
239 if (I->first != LastFunc) { // Only visit each callee once...
240 LastFunc = I->first;
241 calculateGraph(*I->first);
242 }
243#endif
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000244}
Chris Lattner4923d1b2003-02-03 22:51:28 +0000245