Functions reachable from the arguments of unresolvable call nodes should
[oota-llvm.git] / lib / Analysis / DataStructure / TopDownClosure.cpp
1 //===- 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"
13 #include "Support/Debug.h"
14 #include "Support/Statistic.h"
15 #include "DSCallSiteIterator.h"
16
17 namespace {
18   RegisterAnalysis<TDDataStructures>   // Register the pass
19   Y("tddatastructure", "Top-down Data Structure Analysis");
20
21   Statistic<> NumTDInlines("tddatastructures", "Number of graphs inlined");
22 }
23
24 void TDDataStructures::markReachableFunctionsExternallyAccessible(DSNode *N,
25                                                    hash_set<DSNode*> &Visited) {
26   if (!N || Visited.count(N)) return;
27   Visited.insert(N);
28
29   for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i) {
30     DSNodeHandle &NH = N->getLink(i*N->getPointerSize());
31     if (DSNode *NN = NH.getNode()) {
32       const std::vector<GlobalValue*> &Globals = NN->getGlobals();
33       for (unsigned G = 0, e = Globals.size(); G != e; ++G)
34         if (Function *F = dyn_cast<Function>(Globals[G]))
35           ArgsRemainIncomplete.insert(F);
36
37       markReachableFunctionsExternallyAccessible(NN, Visited);
38     }
39   }
40 }
41
42
43 // run - Calculate the top down data structure graphs for each function in the
44 // program.
45 //
46 bool TDDataStructures::run(Module &M) {
47   BUDataStructures &BU = getAnalysis<BUDataStructures>();
48   GlobalsGraph = new DSGraph(BU.getGlobalsGraph());
49   GlobalsGraph->setPrintAuxCalls();
50
51   // Figure out which functions must not mark their arguments complete because
52   // they are accessible outside this compilation unit.  Currently, these
53   // arguments are functions which are reachable by global variables in the
54   // globals graph.
55   const DSGraph::ScalarMapTy &GGSM = GlobalsGraph->getScalarMap();
56   hash_set<DSNode*> Visited;
57   for (DSGraph::ScalarMapTy::const_iterator I = GGSM.begin(), E = GGSM.end();
58        I != E; ++I)
59     if (isa<GlobalValue>(I->first))
60       markReachableFunctionsExternallyAccessible(I->second.getNode(), Visited);
61
62   // Loop over unresolved call nodes.  Any functions passed into (but not
63   // returned!?) from unresolvable call nodes may be invoked outside of the
64   // current module.
65   const std::vector<DSCallSite> &Calls = GlobalsGraph->getAuxFunctionCalls();
66   for (unsigned i = 0, e = Calls.size(); i != e; ++i) {
67     const DSCallSite &CS = Calls[i];
68     for (unsigned arg = 0, e = CS.getNumPtrArgs(); arg != e; ++arg)
69       markReachableFunctionsExternallyAccessible(CS.getPtrArg(arg).getNode(),
70                                                  Visited);
71   }
72   Visited.clear();
73
74   // Functions without internal linkage also have unknown incoming arguments!
75   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
76     if (!I->isExternal() && !I->hasInternalLinkage())
77       ArgsRemainIncomplete.insert(I);
78
79   // We want to traverse the call graph in reverse post-order.  To do this, we
80   // calculate a post-order traversal, then reverse it.
81   hash_set<DSGraph*> VisitedGraph;
82   std::vector<DSGraph*> PostOrder;
83   const BUDataStructures::ActualCalleesTy &ActualCallees = 
84     getAnalysis<BUDataStructures>().getActualCallees();
85
86   // Calculate top-down from main...
87   if (Function *F = M.getMainFunction())
88     ComputePostOrder(*F, VisitedGraph, PostOrder, ActualCallees);
89
90   // Next calculate the graphs for each unreachable function...
91   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
92     ComputePostOrder(*I, VisitedGraph, PostOrder, ActualCallees);
93
94   VisitedGraph.clear();   // Release memory!
95
96   // Visit each of the graphs in reverse post-order now!
97   while (!PostOrder.empty()) {
98     inlineGraphIntoCallees(*PostOrder.back());
99     PostOrder.pop_back();
100   }
101
102   ArgsRemainIncomplete.clear();
103   return false;
104 }
105
106
107 DSGraph &TDDataStructures::getOrCreateDSGraph(Function &F) {
108   DSGraph *&G = DSInfo[&F];
109   if (G == 0) { // Not created yet?  Clone BU graph...
110     G = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F));
111     G->getAuxFunctionCalls().clear();
112     G->setPrintAuxCalls();
113     G->setGlobalsGraph(GlobalsGraph);
114   }
115   return *G;
116 }
117
118
119 void TDDataStructures::ComputePostOrder(Function &F,hash_set<DSGraph*> &Visited,
120                                         std::vector<DSGraph*> &PostOrder,
121                       const BUDataStructures::ActualCalleesTy &ActualCallees) {
122   if (F.isExternal()) return;
123   DSGraph &G = getOrCreateDSGraph(F);
124   if (Visited.count(&G)) return;
125   Visited.insert(&G);
126   
127   // Recursively traverse all of the callee graphs.
128   const std::vector<DSCallSite> &FunctionCalls = G.getFunctionCalls();
129
130   for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
131     Instruction *CallI = FunctionCalls[i].getCallSite().getInstruction();
132     std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
133       BUDataStructures::ActualCalleesTy::const_iterator>
134          IP = ActualCallees.equal_range(CallI);
135
136     for (BUDataStructures::ActualCalleesTy::const_iterator I = IP.first;
137          I != IP.second; ++I)
138       ComputePostOrder(*I->second, Visited, PostOrder, ActualCallees);
139   }
140
141   PostOrder.push_back(&G);
142 }
143
144
145
146
147
148 // releaseMemory - If the pass pipeline is done with this pass, we can release
149 // our memory... here...
150 //
151 // FIXME: This should be releaseMemory and will work fine, except that LoadVN
152 // has no way to extend the lifetime of the pass, which screws up ds-aa.
153 //
154 void TDDataStructures::releaseMyMemory() {
155   for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
156          E = DSInfo.end(); I != E; ++I) {
157     I->second->getReturnNodes().erase(I->first);
158     if (I->second->getReturnNodes().empty())
159       delete I->second;
160   }
161
162   // Empty map so next time memory is released, data structures are not
163   // re-deleted.
164   DSInfo.clear();
165   delete GlobalsGraph;
166   GlobalsGraph = 0;
167 }
168
169 void TDDataStructures::inlineGraphIntoCallees(DSGraph &Graph) {
170   // Recompute the Incomplete markers and eliminate unreachable nodes.
171   Graph.removeTriviallyDeadNodes();
172   Graph.maskIncompleteMarkers();
173
174   // If any of the functions has incomplete incoming arguments, don't mark any
175   // of them as complete.
176   bool HasIncompleteArgs = false;
177   const DSGraph::ReturnNodesTy &GraphReturnNodes = Graph.getReturnNodes();
178   for (DSGraph::ReturnNodesTy::const_iterator I = GraphReturnNodes.begin(),
179          E = GraphReturnNodes.end(); I != E; ++I)
180     if (ArgsRemainIncomplete.count(I->first)) {
181       HasIncompleteArgs = true;
182       break;
183     }
184
185   // Now fold in the necessary globals from the GlobalsGraph.  A global G
186   // must be folded in if it exists in the current graph (i.e., is not dead)
187   // and it was not inlined from any of my callers.  If it was inlined from
188   // a caller, it would have been fully consistent with the GlobalsGraph
189   // in the caller so folding in is not necessary.  Otherwise, this node came
190   // solely from this function's BU graph and so has to be made consistent.
191   // 
192   Graph.updateFromGlobalGraph();
193
194   // Recompute the Incomplete markers.  Depends on whether args are complete
195   unsigned Flags
196     = HasIncompleteArgs ? DSGraph::MarkFormalArgs : DSGraph::IgnoreFormalArgs;
197   Graph.markIncompleteNodes(Flags | DSGraph::IgnoreGlobals);
198
199   // Delete dead nodes.  Treat globals that are unreachable as dead also.
200   Graph.removeDeadNodes(DSGraph::RemoveUnreachableGlobals);
201
202   // We are done with computing the current TD Graph! Now move on to
203   // inlining the current graph into the graphs for its callees, if any.
204   // 
205   const std::vector<DSCallSite> &FunctionCalls = Graph.getFunctionCalls();
206   if (FunctionCalls.empty()) {
207     DEBUG(std::cerr << "  [TD] No callees for: " << Graph.getFunctionNames()
208                     << "\n");
209     return;
210   }
211
212   // Now that we have information about all of the callees, propagate the
213   // current graph into the callees.  Clone only the reachable subgraph at
214   // each call-site, not the entire graph (even though the entire graph
215   // would be cloned only once, this should still be better on average).
216   //
217   DEBUG(std::cerr << "  [TD] Inlining '" << Graph.getFunctionNames() <<"' into "
218                   << FunctionCalls.size() << " call nodes.\n");
219
220   const BUDataStructures::ActualCalleesTy &ActualCallees =
221     getAnalysis<BUDataStructures>().getActualCallees();
222
223   // Loop over all the call sites and all the callees at each call site.
224   // Clone and merge the reachable subgraph from the call into callee's graph.
225   // 
226   for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
227     Instruction *CallI = FunctionCalls[i].getCallSite().getInstruction();
228     // For each function in the invoked function list at this call site...
229     std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
230       BUDataStructures::ActualCalleesTy::const_iterator>
231           IP = ActualCallees.equal_range(CallI);
232
233     // Multiple callees may have the same graph, so try to inline and merge
234     // only once for each <callSite,calleeGraph> pair, not once for each
235     // <callSite,calleeFunction> pair; the latter will be correct but slower.
236     hash_set<DSGraph*> GraphsSeen;
237
238     // Loop over each actual callee at this call site
239     for (BUDataStructures::ActualCalleesTy::const_iterator I = IP.first;
240          I != IP.second; ++I) {
241       DSGraph& CalleeGraph = getDSGraph(*I->second);
242       assert(&CalleeGraph != &Graph && "TD need not inline graph into self!");
243
244       // if this callee graph is already done at this site, skip this callee
245       if (GraphsSeen.find(&CalleeGraph) != GraphsSeen.end())
246         continue;
247       GraphsSeen.insert(&CalleeGraph);
248
249       // Get the root nodes for cloning the reachable subgraph into each callee:
250       // -- all global nodes that appear in both the caller and the callee
251       // -- return value at this call site, if any
252       // -- actual arguments passed at this call site
253       // -- callee node at this call site, if this is an indirect call (this may
254       //    not be needed for merging, but allows us to create CS and therefore
255       //    simplify the merging below).
256       hash_set<const DSNode*> RootNodeSet;
257       for (DSGraph::ScalarMapTy::const_iterator
258              SI = CalleeGraph.getScalarMap().begin(),
259              SE = CalleeGraph.getScalarMap().end(); SI != SE; ++SI)
260         if (GlobalValue* GV = dyn_cast<GlobalValue>(SI->first)) {
261           DSGraph::ScalarMapTy::const_iterator GI=Graph.getScalarMap().find(GV);
262           if (GI != Graph.getScalarMap().end())
263             RootNodeSet.insert(GI->second.getNode());
264         }
265
266       if (const DSNode* RetNode = FunctionCalls[i].getRetVal().getNode())
267         RootNodeSet.insert(RetNode);
268
269       for (unsigned j=0, N=FunctionCalls[i].getNumPtrArgs(); j < N; ++j)
270         if (const DSNode* ArgTarget = FunctionCalls[i].getPtrArg(j).getNode())
271           RootNodeSet.insert(ArgTarget);
272
273       if (FunctionCalls[i].isIndirectCall())
274         RootNodeSet.insert(FunctionCalls[i].getCalleeNode());
275
276       DEBUG(std::cerr << "     [TD] Resolving arguments for callee graph '"
277             << CalleeGraph.getFunctionNames()
278             << "': " << I->second->getFunctionType()->getNumParams()
279             << " args\n          at call site (DSCallSite*) 0x"
280             << &FunctionCalls[i] << "\n");
281       
282       DSGraph::NodeMapTy NodeMapInCallee; // map from nodes to clones in callee
283       DSGraph::NodeMapTy CompletedMap;    // unused map for nodes not to do
284       CalleeGraph.cloneReachableSubgraph(Graph, RootNodeSet,
285                                          NodeMapInCallee, CompletedMap,
286                                          DSGraph::StripModRefBits |
287                                          DSGraph::KeepAllocaBit);
288
289       // Transform our call site info into the cloned version for CalleeGraph
290       DSCallSite CS(FunctionCalls[i], NodeMapInCallee);
291
292       // Get the formal argument and return nodes for the called function
293       // and merge them with the cloned subgraph.  Global nodes were merged  
294       // already by cloneReachableSubgraph() above.
295       CalleeGraph.getCallSiteForArguments(*I->second).mergeWith(CS);
296
297       ++NumTDInlines;
298     }
299   }
300
301   DEBUG(std::cerr << "  [TD] Done inlining into callees for: "
302         << Graph.getFunctionNames() << " [" << Graph.getGraphSize() << "+"
303         << Graph.getFunctionCalls().size() << "]\n");
304 }
305