Fix a bug where we would mark the callees arguments incomplete if the caller was...
[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/Analysis/DSGraph.h"
12 #include "llvm/Module.h"
13 #include "llvm/DerivedTypes.h"
14 #include "Support/Statistic.h"
15
16 namespace {
17   RegisterAnalysis<TDDataStructures>   // Register the pass
18   Y("tddatastructure", "Top-down Data Structure Analysis Closure");
19 }
20
21 // run - Calculate the top down data structure graphs for each function in the
22 // program.
23 //
24 bool TDDataStructures::run(Module &M) {
25   BUDataStructures &BU = getAnalysis<BUDataStructures>();
26   GlobalsGraph = new DSGraph();
27
28   // Calculate top-down from main...
29   if (Function *F = M.getMainFunction())
30     calculateGraph(*F);
31
32   // Next calculate the graphs for each function unreachable function...
33   for (Module::reverse_iterator I = M.rbegin(), E = M.rend(); I != E; ++I)
34     if (!I->isExternal())
35       calculateGraph(*I);
36
37   GraphDone.clear();    // Free temporary memory...
38   return false;
39 }
40
41 // releaseMemory - If the pass pipeline is done with this pass, we can release
42 // our memory... here...
43 //
44 // FIXME: This should be releaseMemory and will work fine, except that LoadVN
45 // has no way to extend the lifetime of the pass, which screws up ds-aa.
46 //
47 void TDDataStructures::releaseMyMemory() {
48   for (hash_map<const Function*, DSGraph*>::iterator I = DSInfo.begin(),
49          E = DSInfo.end(); I != E; ++I)
50     delete I->second;
51
52   // Empty map so next time memory is released, data structures are not
53   // re-deleted.
54   DSInfo.clear();
55   delete GlobalsGraph;
56   GlobalsGraph = 0;
57 }
58
59 /// ResolveCallSite - This method is used to link the actual arguments together
60 /// with the formal arguments for a function call in the top-down closure.  This
61 /// method assumes that the call site arguments have been mapped into nodes
62 /// local to the specified graph.
63 ///
64 void TDDataStructures::ResolveCallSite(DSGraph &Graph,
65                                        const DSCallSite &CallSite) {
66   // Resolve all of the function formal arguments...
67   Function &F = Graph.getFunction();
68   Function::aiterator AI = F.abegin();
69
70   for (unsigned i = 0, e = CallSite.getNumPtrArgs(); i != e; ++i, ++AI) {
71     // Advance the argument iterator to the first pointer argument...
72     while (!DS::isPointerType(AI->getType())) ++AI;
73     
74     // TD ...Merge the formal arg scalar with the actual arg node
75     DSNodeHandle &NodeForFormal = Graph.getNodeForValue(AI);
76     assert(NodeForFormal.getNode() && "Pointer argument has no dest node!");
77     NodeForFormal.mergeWith(CallSite.getPtrArg(i));
78   }
79   
80   // Merge returned node in the caller with the "return" node in callee
81   if (CallSite.getRetVal().getNode() && Graph.getRetNode().getNode())
82     Graph.getRetNode().mergeWith(CallSite.getRetVal());
83 }
84
85 DSGraph &TDDataStructures::getOrCreateDSGraph(Function &F) {
86   DSGraph *&G = DSInfo[&F];
87   if (G == 0) { // Not created yet?  Clone BU graph...
88     G = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F));
89     G->getAuxFunctionCalls().clear();
90     G->setPrintAuxCalls();
91     G->setGlobalsGraph(GlobalsGraph);
92   }
93   return *G;
94 }
95
96 void TDDataStructures::calculateGraph(Function &F) {
97   // Make sure this graph has not already been calculated, and that we don't get
98   // into an infinite loop with mutually recursive functions.
99   //
100   if (GraphDone.count(&F)) return;
101   GraphDone.insert(&F);
102
103   // Get the current functions graph...
104   DSGraph &Graph = getOrCreateDSGraph(F);
105
106   const std::vector<DSCallSite> &CallSites = Graph.getFunctionCalls();
107   if (CallSites.empty()) {
108     DEBUG(std::cerr << "  [TD] No callees for: " << F.getName() << "\n");
109     return;  // If no call sites, there is nothing more to do here
110   }
111
112   // Loop over all of the call sites, building a multi-map from Callees to
113   // DSCallSite*'s.  With this map we can then loop over each callee, cloning
114   // this graph once into it, then resolving arguments.
115   //
116   std::multimap<Function*, const DSCallSite*> CalleeSites;
117   for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
118     const DSCallSite &CS = CallSites[i];
119     if (CS.isDirectCall()) {
120       if (!CS.getCalleeFunc()->isExternal())           // If it's not external
121         CalleeSites.insert(std::make_pair(CS.getCalleeFunc(), &CS)); // Keep it
122     } else {
123       const std::vector<GlobalValue*> &Callees =
124         CS.getCalleeNode()->getGlobals();
125
126       // Loop over all of the functions that this call may invoke...
127       for (unsigned c = 0, e = Callees.size(); c != e; ++c)
128         if (Function *F = dyn_cast<Function>(Callees[c]))  // If this is a fn...
129           if (!F->isExternal())                            // If it's not extern
130             CalleeSites.insert(std::make_pair(F, &CS));    // Keep track of it!
131     }
132   }
133
134   // Now that we have information about all of the callees, propagate the
135   // current graph into the callees.
136   //
137   DEBUG(std::cerr << "  [TD] Inlining '" << F.getName() << "' into "
138                   << CalleeSites.size() << " callees.\n");
139
140   // Loop over all the callees...
141   for (std::multimap<Function*, const DSCallSite*>::iterator
142          I = CalleeSites.begin(), E = CalleeSites.end(); I != E; )
143     if (I->first == &F) {  // Bottom-up pass takes care of self loops!
144       ++I;
145     } else {
146       // For each callee...
147       Function *Callee = I->first;
148       DSGraph &CG = getOrCreateDSGraph(*Callee);  // Get the callee's graph...
149       
150       DEBUG(std::cerr << "\t [TD] Inlining into callee '" << Callee->getName()
151             << "'\n");
152       
153       // Clone our current graph into the callee...
154       hash_map<Value*, DSNodeHandle> OldValMap;
155       hash_map<const DSNode*, DSNodeHandle> OldNodeMap;
156       CG.cloneInto(Graph, OldValMap, OldNodeMap,
157                    DSGraph::StripModRefBits |
158                    DSGraph::KeepAllocaBit | DSGraph::DontCloneCallNodes);
159       OldValMap.clear();  // We don't care about the ValMap
160
161       // Loop over all of the invocation sites of the callee, resolving
162       // arguments to our graph.  This loop may iterate multiple times if the
163       // current function calls this callee multiple times with different
164       // signatures.
165       //
166       for (; I != E && I->first == Callee; ++I) {
167         // Map call site into callee graph
168         DSCallSite NewCS(*I->second, OldNodeMap);
169         
170         // Resolve the return values...
171         NewCS.getRetVal().mergeWith(CG.getRetNode());
172         
173         // Resolve all of the arguments...
174         Function::aiterator AI = Callee->abegin();
175         for (unsigned i = 0, e = NewCS.getNumPtrArgs();
176              i != e && AI != Callee->aend(); ++i, ++AI) {
177           // Advance the argument iterator to the first pointer argument...
178           while (!DS::isPointerType(AI->getType())) {
179             ++AI;
180 #ifndef NDEBUG
181             if (AI == Callee->aend())
182               std::cerr << "Bad call to Function: " << Callee->getName()<< "\n";
183 #endif
184             assert(AI != Callee->aend() &&
185                    "# Args provided is not # Args required!");
186           }
187           
188           // Add the link from the argument scalar to the provided value
189           DSNodeHandle &NH = CG.getNodeForValue(AI);
190           assert(NH.getNode() && "Pointer argument without scalarmap entry?");
191           NH.mergeWith(NewCS.getPtrArg(i));
192         }
193       }
194
195       // Done with the nodemap...
196       OldNodeMap.clear();
197
198       // Recompute the Incomplete markers and eliminate unreachable nodes.
199       CG.maskIncompleteMarkers();
200       CG.markIncompleteNodes(Callee->hasInternalLinkage() ?
201                              DSGraph::IgnoreFormalArgs : DSGraph::MarkFormalArgs
202                              /*&& FIXME: NEED TO CHECK IF ALL CALLERS FOUND!*/);
203       CG.removeDeadNodes(DSGraph::RemoveUnreachableGlobals);
204     }
205
206   DEBUG(std::cerr << "  [TD] Done inlining into callees for: " << F.getName()
207         << " [" << Graph.getGraphSize() << "+"
208         << Graph.getFunctionCalls().size() << "]\n");
209
210   
211   // Loop over all the callees... making sure they are all resolved now...
212   Function *LastFunc = 0;
213   for (std::multimap<Function*, const DSCallSite*>::iterator
214          I = CalleeSites.begin(), E = CalleeSites.end(); I != E; ++I)
215     if (I->first != LastFunc) {  // Only visit each callee once...
216       LastFunc = I->first;
217       calculateGraph(*I->first);
218     }
219 }
220