blob: 7eea92266122a65564800a5b3e26e2e7314be4f6 [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
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())
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 Lattner3d162902003-06-30 04:53:08 +000048 for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
49 E = DSInfo.end(); I != E; ++I) {
50 I->second->getReturnNodes().erase(I->first);
51 if (I->second->getReturnNodes().empty())
52 delete I->second;
53 }
Vikram S. Adveaaeee752002-07-30 22:06:40 +000054
55 // Empty map so next time memory is released, data structures are not
56 // re-deleted.
57 DSInfo.clear();
Chris Lattneraa0b4682002-11-09 21:12:07 +000058 delete GlobalsGraph;
59 GlobalsGraph = 0;
Vikram S. Adveaaeee752002-07-30 22:06:40 +000060}
61
Chris Lattner5a540632003-06-30 03:15:25 +000062#if 0
Chris Lattner0e744122002-10-17 04:26:54 +000063/// ResolveCallSite - This method is used to link the actual arguments together
64/// with the formal arguments for a function call in the top-down closure. This
65/// method assumes that the call site arguments have been mapped into nodes
66/// local to the specified graph.
67///
68void TDDataStructures::ResolveCallSite(DSGraph &Graph,
Vikram S. Adve42fd1692002-10-20 18:07:37 +000069 const DSCallSite &CallSite) {
Chris Lattner0e744122002-10-17 04:26:54 +000070 // Resolve all of the function formal arguments...
71 Function &F = Graph.getFunction();
72 Function::aiterator AI = F.abegin();
Vikram S. Adveaaeee752002-07-30 22:06:40 +000073
Vikram S. Adve26b98262002-10-20 21:41:02 +000074 for (unsigned i = 0, e = CallSite.getNumPtrArgs(); i != e; ++i, ++AI) {
Chris Lattner0e744122002-10-17 04:26:54 +000075 // Advance the argument iterator to the first pointer argument...
Chris Lattnerb1060432002-11-07 05:20:53 +000076 while (!DS::isPointerType(AI->getType())) ++AI;
Vikram S. Adveaaeee752002-07-30 22:06:40 +000077
Chris Lattner0e744122002-10-17 04:26:54 +000078 // TD ...Merge the formal arg scalar with the actual arg node
79 DSNodeHandle &NodeForFormal = Graph.getNodeForValue(AI);
Chris Lattner99a22842002-10-21 15:04:18 +000080 assert(NodeForFormal.getNode() && "Pointer argument has no dest node!");
81 NodeForFormal.mergeWith(CallSite.getPtrArg(i));
Chris Lattner0e744122002-10-17 04:26:54 +000082 }
83
84 // Merge returned node in the caller with the "return" node in callee
Chris Lattner0969c502002-10-21 02:08:03 +000085 if (CallSite.getRetVal().getNode() && Graph.getRetNode().getNode())
86 Graph.getRetNode().mergeWith(CallSite.getRetVal());
Vikram S. Adveaaeee752002-07-30 22:06:40 +000087}
Chris Lattner5a540632003-06-30 03:15:25 +000088#endif
Vikram S. Adveaaeee752002-07-30 22:06:40 +000089
Chris Lattner7a211632002-11-08 21:28:37 +000090DSGraph &TDDataStructures::getOrCreateDSGraph(Function &F) {
91 DSGraph *&G = DSInfo[&F];
92 if (G == 0) { // Not created yet? Clone BU graph...
93 G = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F));
94 G->getAuxFunctionCalls().clear();
Chris Lattner24d80072003-02-04 00:59:32 +000095 G->setPrintAuxCalls();
Chris Lattneraa0b4682002-11-09 21:12:07 +000096 G->setGlobalsGraph(GlobalsGraph);
Chris Lattner7a211632002-11-08 21:28:37 +000097 }
98 return *G;
99}
Vikram S. Adve26b98262002-10-20 21:41:02 +0000100
Chris Lattnerdea81462003-06-29 22:37:07 +0000101
102/// FunctionHasCompleteArguments - This function returns true if it is safe not
103/// to mark arguments to the function complete.
104///
105/// FIXME: Need to check if all callers have been found, or rather if a
106/// funcpointer escapes!
107///
108static bool FunctionHasCompleteArguments(Function &F) {
109 return F.hasInternalLinkage();
110}
111
112
Chris Lattner7a211632002-11-08 21:28:37 +0000113void TDDataStructures::calculateGraph(Function &F) {
114 // Make sure this graph has not already been calculated, and that we don't get
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000115 // into an infinite loop with mutually recursive functions.
116 //
Chris Lattner7a211632002-11-08 21:28:37 +0000117 if (GraphDone.count(&F)) return;
118 GraphDone.insert(&F);
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000119
Chris Lattner7a211632002-11-08 21:28:37 +0000120 // Get the current functions graph...
121 DSGraph &Graph = getOrCreateDSGraph(F);
Chris Lattner198be222002-10-21 19:47:18 +0000122
Chris Lattner4f2cfc02003-02-10 18:16:36 +0000123 // Recompute the Incomplete markers and eliminate unreachable nodes.
124 Graph.maskIncompleteMarkers();
Chris Lattnerdea81462003-06-29 22:37:07 +0000125 unsigned Flags = FunctionHasCompleteArguments(F) ?
126 DSGraph::IgnoreFormalArgs : DSGraph::MarkFormalArgs;
Chris Lattner4f2cfc02003-02-10 18:16:36 +0000127 Graph.markIncompleteNodes(Flags | DSGraph::IgnoreGlobals);
128 Graph.removeDeadNodes(DSGraph::RemoveUnreachableGlobals);
129
Chris Lattner7a211632002-11-08 21:28:37 +0000130 const std::vector<DSCallSite> &CallSites = Graph.getFunctionCalls();
Chris Lattner7a211632002-11-08 21:28:37 +0000131 if (CallSites.empty()) {
132 DEBUG(std::cerr << " [TD] No callees for: " << F.getName() << "\n");
Chris Lattnere0fbd482003-02-09 18:42:43 +0000133 } else {
134 // Loop over all of the call sites, building a multi-map from Callees to
135 // DSCallSite*'s. With this map we can then loop over each callee, cloning
136 // this graph once into it, then resolving arguments.
137 //
138 std::multimap<Function*, const DSCallSite*> CalleeSites;
139 for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
140 const DSCallSite &CS = CallSites[i];
141 if (CS.isDirectCall()) {
142 if (!CS.getCalleeFunc()->isExternal()) // If it's not external
143 CalleeSites.insert(std::make_pair(CS.getCalleeFunc(), &CS));// Keep it
144 } else {
145 const std::vector<GlobalValue*> &Callees =
146 CS.getCalleeNode()->getGlobals();
Chris Lattnerce2d1322002-11-08 22:26:43 +0000147
Chris Lattnere0fbd482003-02-09 18:42:43 +0000148 // Loop over all of the functions that this call may invoke...
149 for (unsigned c = 0, e = Callees.size(); c != e; ++c)
150 if (Function *F = dyn_cast<Function>(Callees[c]))// If this is a fn...
151 if (!F->isExternal()) // If it's not extern
152 CalleeSites.insert(std::make_pair(F, &CS)); // Keep track of it!
153 }
Chris Lattner923fc052003-02-05 21:59:58 +0000154 }
Chris Lattner0e744122002-10-17 04:26:54 +0000155
Chris Lattnere0fbd482003-02-09 18:42:43 +0000156 // Now that we have information about all of the callees, propagate the
157 // current graph into the callees.
158 //
159 DEBUG(std::cerr << " [TD] Inlining '" << F.getName() << "' into "
160 << CalleeSites.size() << " callees.\n");
Chris Lattner7a211632002-11-08 21:28:37 +0000161
Chris Lattnere0fbd482003-02-09 18:42:43 +0000162 // Loop over all the callees...
163 for (std::multimap<Function*, const DSCallSite*>::iterator
164 I = CalleeSites.begin(), E = CalleeSites.end(); I != E; )
165 if (I->first == &F) { // Bottom-up pass takes care of self loops!
166 ++I;
167 } else {
168 // For each callee...
Chris Lattnerdea81462003-06-29 22:37:07 +0000169 Function &Callee = *I->first;
170 DSGraph &CG = getOrCreateDSGraph(Callee); // Get the callee's graph...
Chris Lattner7a211632002-11-08 21:28:37 +0000171
Chris Lattnerdea81462003-06-29 22:37:07 +0000172 DEBUG(std::cerr << "\t [TD] Inlining into callee '" << Callee.getName()
173 << "'\n");
Chris Lattner7a211632002-11-08 21:28:37 +0000174
Chris Lattnere0fbd482003-02-09 18:42:43 +0000175 // Clone our current graph into the callee...
Chris Lattner5a540632003-06-30 03:15:25 +0000176 DSGraph::ScalarMapTy OldValMap;
177 DSGraph::NodeMapTy OldNodeMap;
178 DSGraph::ReturnNodesTy ReturnNodes;
179 CG.cloneInto(Graph, OldValMap, ReturnNodes, OldNodeMap,
Chris Lattnere0fbd482003-02-09 18:42:43 +0000180 DSGraph::StripModRefBits |
Chris Lattner4f2cfc02003-02-10 18:16:36 +0000181 DSGraph::KeepAllocaBit | DSGraph::DontCloneCallNodes |
182 DSGraph::DontCloneAuxCallNodes);
Chris Lattnere0fbd482003-02-09 18:42:43 +0000183 OldValMap.clear(); // We don't care about the ValMap
Chris Lattner5a540632003-06-30 03:15:25 +0000184 ReturnNodes.clear(); // We don't care about return values either
Vikram S. Adve61ff0292002-11-27 17:41:13 +0000185
Chris Lattnere0fbd482003-02-09 18:42:43 +0000186 // Loop over all of the invocation sites of the callee, resolving
187 // arguments to our graph. This loop may iterate multiple times if the
188 // current function calls this callee multiple times with different
189 // signatures.
190 //
Chris Lattnerdea81462003-06-29 22:37:07 +0000191 for (; I != E && I->first == &Callee; ++I) {
Chris Lattnere0fbd482003-02-09 18:42:43 +0000192 // Map call site into callee graph
193 DSCallSite NewCS(*I->second, OldNodeMap);
Chris Lattner7a211632002-11-08 21:28:37 +0000194
Chris Lattnere0fbd482003-02-09 18:42:43 +0000195 // Resolve the return values...
Chris Lattner5a540632003-06-30 03:15:25 +0000196 NewCS.getRetVal().mergeWith(CG.getReturnNodeFor(Callee));
Chris Lattner7a211632002-11-08 21:28:37 +0000197
Chris Lattnere0fbd482003-02-09 18:42:43 +0000198 // Resolve all of the arguments...
Chris Lattnerdea81462003-06-29 22:37:07 +0000199 Function::aiterator AI = Callee.abegin();
Chris Lattnere0fbd482003-02-09 18:42:43 +0000200 for (unsigned i = 0, e = NewCS.getNumPtrArgs();
Chris Lattnerdea81462003-06-29 22:37:07 +0000201 i != e && AI != Callee.aend(); ++i, ++AI) {
Chris Lattnere0fbd482003-02-09 18:42:43 +0000202 // Advance the argument iterator to the first pointer argument...
Chris Lattnerdea81462003-06-29 22:37:07 +0000203 while (AI != Callee.aend() && !DS::isPointerType(AI->getType()))
Chris Lattnere0fbd482003-02-09 18:42:43 +0000204 ++AI;
Chris Lattnerdea81462003-06-29 22:37:07 +0000205 if (AI == Callee.aend()) break;
Chris Lattner72d29a42003-02-11 23:11:51 +0000206
Chris Lattnere0fbd482003-02-09 18:42:43 +0000207 // Add the link from the argument scalar to the provided value
208 DSNodeHandle &NH = CG.getNodeForValue(AI);
209 assert(NH.getNode() && "Pointer argument without scalarmap entry?");
210 NH.mergeWith(NewCS.getPtrArg(i));
211 }
Chris Lattner7a211632002-11-08 21:28:37 +0000212 }
Chris Lattnere0fbd482003-02-09 18:42:43 +0000213
214 // Done with the nodemap...
215 OldNodeMap.clear();
216
217 // Recompute the Incomplete markers and eliminate unreachable nodes.
Chris Lattner4f2cfc02003-02-10 18:16:36 +0000218 CG.removeTriviallyDeadNodes();
Chris Lattnere0fbd482003-02-09 18:42:43 +0000219 CG.maskIncompleteMarkers();
Chris Lattner4f2cfc02003-02-10 18:16:36 +0000220 CG.markIncompleteNodes(DSGraph::MarkFormalArgs |DSGraph::IgnoreGlobals);
Chris Lattnere0fbd482003-02-09 18:42:43 +0000221 CG.removeDeadNodes(DSGraph::RemoveUnreachableGlobals);
Chris Lattner7a211632002-11-08 21:28:37 +0000222 }
223
Chris Lattnere0fbd482003-02-09 18:42:43 +0000224 DEBUG(std::cerr << " [TD] Done inlining into callees for: " << F.getName()
225 << " [" << Graph.getGraphSize() << "+"
226 << Graph.getFunctionCalls().size() << "]\n");
Chris Lattner7a211632002-11-08 21:28:37 +0000227
Chris Lattnere0fbd482003-02-09 18:42:43 +0000228 // Loop over all the callees... making sure they are all resolved now...
229 Function *LastFunc = 0;
230 for (std::multimap<Function*, const DSCallSite*>::iterator
231 I = CalleeSites.begin(), E = CalleeSites.end(); I != E; ++I)
232 if (I->first != LastFunc) { // Only visit each callee once...
233 LastFunc = I->first;
234 calculateGraph(*I->first);
235 }
236 }
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000237}
Chris Lattner4923d1b2003-02-03 22:51:28 +0000238