blob: 49b3a5482e85fefea8293e946edc26fa3f49cf2b [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"
Chris Lattner0e744122002-10-17 04:26:54 +000011#include "llvm/Analysis/DSGraph.h"
Vikram S. Adveaaeee752002-07-30 22:06:40 +000012#include "llvm/Module.h"
13#include "llvm/DerivedTypes.h"
Chris Lattnerfccd06f2002-10-01 22:33:50 +000014#include "Support/Statistic.h"
Vikram S. Adveaaeee752002-07-30 22:06:40 +000015
Chris Lattner4923d1b2003-02-03 22:51:28 +000016namespace {
17 RegisterAnalysis<TDDataStructures> // Register the pass
18 Y("tddatastructure", "Top-down Data Structure Analysis Closure");
19}
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>();
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
Vikram S. Adveaaeee752002-07-30 22:06:40 +000041// releaseMemory - If the pass pipeline is done with this pass, we can release
42// our memory... here...
43//
Chris Lattner4923d1b2003-02-03 22:51:28 +000044// 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//
47void TDDataStructures::releaseMyMemory() {
Chris Lattner41c04f72003-02-01 04:52:08 +000048 for (hash_map<const Function*, DSGraph*>::iterator I = DSInfo.begin(),
Vikram S. Adveaaeee752002-07-30 22:06:40 +000049 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();
Chris Lattneraa0b4682002-11-09 21:12:07 +000055 delete GlobalsGraph;
56 GlobalsGraph = 0;
Vikram S. Adveaaeee752002-07-30 22:06:40 +000057}
58
Chris Lattner0e744122002-10-17 04:26:54 +000059/// 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///
64void TDDataStructures::ResolveCallSite(DSGraph &Graph,
Vikram S. Adve42fd1692002-10-20 18:07:37 +000065 const DSCallSite &CallSite) {
Chris Lattner0e744122002-10-17 04:26:54 +000066 // Resolve all of the function formal arguments...
67 Function &F = Graph.getFunction();
68 Function::aiterator AI = F.abegin();
Vikram S. Adveaaeee752002-07-30 22:06:40 +000069
Vikram S. Adve26b98262002-10-20 21:41:02 +000070 for (unsigned i = 0, e = CallSite.getNumPtrArgs(); i != e; ++i, ++AI) {
Chris Lattner0e744122002-10-17 04:26:54 +000071 // Advance the argument iterator to the first pointer argument...
Chris Lattnerb1060432002-11-07 05:20:53 +000072 while (!DS::isPointerType(AI->getType())) ++AI;
Vikram S. Adveaaeee752002-07-30 22:06:40 +000073
Chris Lattner0e744122002-10-17 04:26:54 +000074 // TD ...Merge the formal arg scalar with the actual arg node
75 DSNodeHandle &NodeForFormal = Graph.getNodeForValue(AI);
Chris Lattner99a22842002-10-21 15:04:18 +000076 assert(NodeForFormal.getNode() && "Pointer argument has no dest node!");
77 NodeForFormal.mergeWith(CallSite.getPtrArg(i));
Chris Lattner0e744122002-10-17 04:26:54 +000078 }
79
80 // Merge returned node in the caller with the "return" node in callee
Chris Lattner0969c502002-10-21 02:08:03 +000081 if (CallSite.getRetVal().getNode() && Graph.getRetNode().getNode())
82 Graph.getRetNode().mergeWith(CallSite.getRetVal());
Vikram S. Adveaaeee752002-07-30 22:06:40 +000083}
84
Chris Lattner7a211632002-11-08 21:28:37 +000085DSGraph &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();
Chris Lattneraa0b4682002-11-09 21:12:07 +000090 G->setGlobalsGraph(GlobalsGraph);
Chris Lattner7a211632002-11-08 21:28:37 +000091 }
92 return *G;
93}
Vikram S. Adve26b98262002-10-20 21:41:02 +000094
Chris Lattner7a211632002-11-08 21:28:37 +000095void TDDataStructures::calculateGraph(Function &F) {
96 // Make sure this graph has not already been calculated, and that we don't get
Vikram S. Adveaaeee752002-07-30 22:06:40 +000097 // into an infinite loop with mutually recursive functions.
98 //
Chris Lattner7a211632002-11-08 21:28:37 +000099 if (GraphDone.count(&F)) return;
100 GraphDone.insert(&F);
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000101
Chris Lattner7a211632002-11-08 21:28:37 +0000102 // Get the current functions graph...
103 DSGraph &Graph = getOrCreateDSGraph(F);
Chris Lattner198be222002-10-21 19:47:18 +0000104
Chris Lattner7a211632002-11-08 21:28:37 +0000105 const std::vector<DSCallSite> &CallSites = Graph.getFunctionCalls();
Chris Lattner7a211632002-11-08 21:28:37 +0000106 if (CallSites.empty()) {
107 DEBUG(std::cerr << " [TD] No callees for: " << F.getName() << "\n");
Vikram S. Adve61ff0292002-11-27 17:41:13 +0000108 return; // If no call sites, there is nothing more to do here
Chris Lattner4bdb9b72002-10-22 16:01:03 +0000109 }
Chris Lattnerce2d1322002-11-08 22:26:43 +0000110
Chris Lattner7a211632002-11-08 21:28:37 +0000111 // Loop over all of the call sites, building a multi-map from Callees to
112 // DSCallSite*'s. With this map we can then loop over each callee, cloning
113 // this graph once into it, then resolving arguments.
Chris Lattner0e744122002-10-17 04:26:54 +0000114 //
Chris Lattner7a211632002-11-08 21:28:37 +0000115 std::multimap<Function*, const DSCallSite*> CalleeSites;
116 for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
117 const DSCallSite &CS = CallSites[i];
118 const std::vector<GlobalValue*> Callees =
119 CS.getCallee().getNode()->getGlobals();
Chris Lattner198be222002-10-21 19:47:18 +0000120
Chris Lattner7a211632002-11-08 21:28:37 +0000121 // Loop over all of the functions that this call may invoke...
122 for (unsigned c = 0, e = Callees.size(); c != e; ++c)
123 if (Function *F = dyn_cast<Function>(Callees[c])) // If this is a fn...
124 if (!F->isExternal()) // If it's not external
125 CalleeSites.insert(std::make_pair(F, &CS)); // Keep track of it!
Chris Lattner0e744122002-10-17 04:26:54 +0000126 }
Chris Lattner0e744122002-10-17 04:26:54 +0000127
Chris Lattner7a211632002-11-08 21:28:37 +0000128 // Now that we have information about all of the callees, propogate the
129 // current graph into the callees.
130 //
131 DEBUG(std::cerr << " [TD] Inlining '" << F.getName() << "' into "
132 << CalleeSites.size() << " callees.\n");
133
134 // Loop over all the callees...
135 for (std::multimap<Function*, const DSCallSite*>::iterator
136 I = CalleeSites.begin(), E = CalleeSites.end(); I != E; )
137 if (I->first == &F) { // Bottom-up pass takes care of self loops!
138 ++I;
139 } else {
140 // For each callee...
141 Function *Callee = I->first;
142 DSGraph &CG = getOrCreateDSGraph(*Callee); // Get the callee's graph...
143
144 DEBUG(std::cerr << "\t [TD] Inlining into callee '" << Callee->getName()
145 << "'\n");
146
147 // Clone our current graph into the callee...
Chris Lattner41c04f72003-02-01 04:52:08 +0000148 hash_map<Value*, DSNodeHandle> OldValMap;
149 hash_map<const DSNode*, DSNodeHandle> OldNodeMap;
Chris Lattner7a211632002-11-08 21:28:37 +0000150 CG.cloneInto(Graph, OldValMap, OldNodeMap,
Vikram S. Adve61ff0292002-11-27 17:41:13 +0000151 DSGraph::StripModRefBits |
Chris Lattner7a211632002-11-08 21:28:37 +0000152 DSGraph::KeepAllocaBit | DSGraph::DontCloneCallNodes);
153 OldValMap.clear(); // We don't care about the ValMap
Vikram S. Adve61ff0292002-11-27 17:41:13 +0000154
Chris Lattner7a211632002-11-08 21:28:37 +0000155 // Loop over all of the invocation sites of the callee, resolving
156 // arguments to our graph. This loop may iterate multiple times if the
157 // current function calls this callee multiple times with different
158 // signatures.
159 //
160 for (; I != E && I->first == Callee; ++I) {
161 // Map call site into callee graph
162 DSCallSite NewCS(*I->second, OldNodeMap);
163
164 // Resolve the return values...
165 NewCS.getRetVal().mergeWith(CG.getRetNode());
166
167 // Resolve all of the arguments...
168 Function::aiterator AI = Callee->abegin();
Chris Lattner0ecc4262002-11-11 21:36:05 +0000169 for (unsigned i = 0, e = NewCS.getNumPtrArgs();
170 i != e && AI != Callee->aend(); ++i, ++AI) {
Chris Lattner7a211632002-11-08 21:28:37 +0000171 // Advance the argument iterator to the first pointer argument...
172 while (!DS::isPointerType(AI->getType())) {
173 ++AI;
174#ifndef NDEBUG
175 if (AI == Callee->aend())
176 std::cerr << "Bad call to Function: " << Callee->getName()<< "\n";
177#endif
178 assert(AI != Callee->aend() &&
179 "# Args provided is not # Args required!");
180 }
181
182 // Add the link from the argument scalar to the provided value
183 DSNodeHandle &NH = CG.getNodeForValue(AI);
184 assert(NH.getNode() && "Pointer argument without scalarmap entry?");
185 NH.mergeWith(NewCS.getPtrArg(i));
186 }
187 }
188
189 // Done with the nodemap...
190 OldNodeMap.clear();
191
192 // Recompute the Incomplete markers and eliminate unreachable nodes.
193 CG.maskIncompleteMarkers();
Chris Lattner394471f2003-01-23 22:05:33 +0000194 CG.markIncompleteNodes(F.hasInternalLinkage() ? DSGraph::IgnoreFormalArgs:
195 DSGraph::MarkFormalArgs
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000196 /*&& FIXME: NEED TO CHECK IF ALL CALLERS FOUND!*/);
Chris Lattner394471f2003-01-23 22:05:33 +0000197 CG.removeDeadNodes(DSGraph::RemoveUnreachableGlobals);
Chris Lattner7a211632002-11-08 21:28:37 +0000198 }
Chris Lattner4bdb9b72002-10-22 16:01:03 +0000199
Chris Lattner7a211632002-11-08 21:28:37 +0000200 DEBUG(std::cerr << " [TD] Done inlining into callees for: " << F.getName()
201 << " [" << Graph.getGraphSize() << "+"
202 << Graph.getFunctionCalls().size() << "]\n");
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000203
Chris Lattner7a211632002-11-08 21:28:37 +0000204
205 // Loop over all the callees... making sure they are all resolved now...
206 Function *LastFunc = 0;
207 for (std::multimap<Function*, const DSCallSite*>::iterator
208 I = CalleeSites.begin(), E = CalleeSites.end(); I != E; ++I)
209 if (I->first != LastFunc) { // Only visit each callee once...
210 LastFunc = I->first;
211 calculateGraph(*I->first);
212 }
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000213}
Chris Lattner4923d1b2003-02-03 22:51:28 +0000214