1 //===- TopDownClosure.cpp - Compute the top-down interprocedure closure ---===//
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.
8 //===----------------------------------------------------------------------===//
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"
17 RegisterAnalysis<TDDataStructures> // Register the pass
18 Y("tddatastructure", "Top-down Data Structure Analysis Closure");
21 // run - Calculate the top down data structure graphs for each function in the
24 bool TDDataStructures::run(Module &M) {
25 BUDataStructures &BU = getAnalysis<BUDataStructures>();
26 GlobalsGraph = new DSGraph();
28 // Calculate top-down from main...
29 if (Function *F = M.getMainFunction())
32 // Next calculate the graphs for each function unreachable function...
33 for (Module::reverse_iterator I = M.rbegin(), E = M.rend(); I != E; ++I)
37 GraphDone.clear(); // Free temporary memory...
41 // releaseMemory - If the pass pipeline is done with this pass, we can release
42 // our memory... here...
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.
47 void TDDataStructures::releaseMyMemory() {
48 for (hash_map<const Function*, DSGraph*>::iterator I = DSInfo.begin(),
49 E = DSInfo.end(); I != E; ++I)
52 // Empty map so next time memory is released, data structures are not
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.
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();
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;
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));
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());
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);
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.
100 if (GraphDone.count(&F)) return;
101 GraphDone.insert(&F);
103 // Get the current functions graph...
104 DSGraph &Graph = getOrCreateDSGraph(F);
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
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.
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 const std::vector<GlobalValue*> Callees =
120 CS.getCallee().getNode()->getGlobals();
122 // Loop over all of the functions that this call may invoke...
123 for (unsigned c = 0, e = Callees.size(); c != e; ++c)
124 if (Function *F = dyn_cast<Function>(Callees[c])) // If this is a fn...
125 if (!F->isExternal()) // If it's not external
126 CalleeSites.insert(std::make_pair(F, &CS)); // Keep track of it!
129 // Now that we have information about all of the callees, propogate the
130 // current graph into the callees.
132 DEBUG(std::cerr << " [TD] Inlining '" << F.getName() << "' into "
133 << CalleeSites.size() << " callees.\n");
135 // Loop over all the callees...
136 for (std::multimap<Function*, const DSCallSite*>::iterator
137 I = CalleeSites.begin(), E = CalleeSites.end(); I != E; )
138 if (I->first == &F) { // Bottom-up pass takes care of self loops!
141 // For each callee...
142 Function *Callee = I->first;
143 DSGraph &CG = getOrCreateDSGraph(*Callee); // Get the callee's graph...
145 DEBUG(std::cerr << "\t [TD] Inlining into callee '" << Callee->getName()
148 // Clone our current graph into the callee...
149 hash_map<Value*, DSNodeHandle> OldValMap;
150 hash_map<const DSNode*, DSNodeHandle> OldNodeMap;
151 CG.cloneInto(Graph, OldValMap, OldNodeMap,
152 DSGraph::StripModRefBits |
153 DSGraph::KeepAllocaBit | DSGraph::DontCloneCallNodes);
154 OldValMap.clear(); // We don't care about the ValMap
156 // Loop over all of the invocation sites of the callee, resolving
157 // arguments to our graph. This loop may iterate multiple times if the
158 // current function calls this callee multiple times with different
161 for (; I != E && I->first == Callee; ++I) {
162 // Map call site into callee graph
163 DSCallSite NewCS(*I->second, OldNodeMap);
165 // Resolve the return values...
166 NewCS.getRetVal().mergeWith(CG.getRetNode());
168 // Resolve all of the arguments...
169 Function::aiterator AI = Callee->abegin();
170 for (unsigned i = 0, e = NewCS.getNumPtrArgs();
171 i != e && AI != Callee->aend(); ++i, ++AI) {
172 // Advance the argument iterator to the first pointer argument...
173 while (!DS::isPointerType(AI->getType())) {
176 if (AI == Callee->aend())
177 std::cerr << "Bad call to Function: " << Callee->getName()<< "\n";
179 assert(AI != Callee->aend() &&
180 "# Args provided is not # Args required!");
183 // Add the link from the argument scalar to the provided value
184 DSNodeHandle &NH = CG.getNodeForValue(AI);
185 assert(NH.getNode() && "Pointer argument without scalarmap entry?");
186 NH.mergeWith(NewCS.getPtrArg(i));
190 // Done with the nodemap...
193 // Recompute the Incomplete markers and eliminate unreachable nodes.
194 CG.maskIncompleteMarkers();
195 CG.markIncompleteNodes(F.hasInternalLinkage() ? DSGraph::IgnoreFormalArgs:
196 DSGraph::MarkFormalArgs
197 /*&& FIXME: NEED TO CHECK IF ALL CALLERS FOUND!*/);
198 CG.removeDeadNodes(DSGraph::RemoveUnreachableGlobals);
201 DEBUG(std::cerr << " [TD] Done inlining into callees for: " << F.getName()
202 << " [" << Graph.getGraphSize() << "+"
203 << Graph.getFunctionCalls().size() << "]\n");
206 // Loop over all the callees... making sure they are all resolved now...
207 Function *LastFunc = 0;
208 for (std::multimap<Function*, const DSCallSite*>::iterator
209 I = CalleeSites.begin(), E = CalleeSites.end(); I != E; ++I)
210 if (I->first != LastFunc) { // Only visit each callee once...
212 calculateGraph(*I->first);