blob: 13ed8fd9514af50d13a2e18345357cf97a31cc90 [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
16static RegisterAnalysis<TDDataStructures>
17Y("tddatastructure", "Top-down Data Structure Analysis Closure");
Vikram S. Adveaaeee752002-07-30 22:06:40 +000018
19// releaseMemory - If the pass pipeline is done with this pass, we can release
20// our memory... here...
21//
22void TDDataStructures::releaseMemory() {
Chris Lattner13ec72a2002-10-21 13:31:48 +000023 for (std::map<const Function*, DSGraph*>::iterator I = DSInfo.begin(),
Vikram S. Adveaaeee752002-07-30 22:06:40 +000024 E = DSInfo.end(); I != E; ++I)
25 delete I->second;
26
27 // Empty map so next time memory is released, data structures are not
28 // re-deleted.
29 DSInfo.clear();
30}
31
32// run - Calculate the top down data structure graphs for each function in the
33// program.
34//
35bool TDDataStructures::run(Module &M) {
Chris Lattner4bdb9b72002-10-22 16:01:03 +000036 BUDataStructures &BU = getAnalysis<BUDataStructures>();
37
Chris Lattner7a211632002-11-08 21:28:37 +000038 // Calculate top-down from main...
39 if (Function *F = M.getMainFunction())
40 calculateGraph(*F);
Chris Lattner4bdb9b72002-10-22 16:01:03 +000041
Chris Lattner7a211632002-11-08 21:28:37 +000042 // Next calculate the graphs for each function unreachable function...
Vikram S. Adveaaeee752002-07-30 22:06:40 +000043 for (Module::reverse_iterator I = M.rbegin(), E = M.rend(); I != E; ++I)
44 if (!I->isExternal())
45 calculateGraph(*I);
46 return false;
47}
48
Chris Lattner0e744122002-10-17 04:26:54 +000049/// ResolveCallSite - This method is used to link the actual arguments together
50/// with the formal arguments for a function call in the top-down closure. This
51/// method assumes that the call site arguments have been mapped into nodes
52/// local to the specified graph.
53///
54void TDDataStructures::ResolveCallSite(DSGraph &Graph,
Vikram S. Adve42fd1692002-10-20 18:07:37 +000055 const DSCallSite &CallSite) {
Chris Lattner0e744122002-10-17 04:26:54 +000056 // Resolve all of the function formal arguments...
57 Function &F = Graph.getFunction();
58 Function::aiterator AI = F.abegin();
Vikram S. Adveaaeee752002-07-30 22:06:40 +000059
Vikram S. Adve26b98262002-10-20 21:41:02 +000060 for (unsigned i = 0, e = CallSite.getNumPtrArgs(); i != e; ++i, ++AI) {
Chris Lattner0e744122002-10-17 04:26:54 +000061 // Advance the argument iterator to the first pointer argument...
Chris Lattnerb1060432002-11-07 05:20:53 +000062 while (!DS::isPointerType(AI->getType())) ++AI;
Vikram S. Adveaaeee752002-07-30 22:06:40 +000063
Chris Lattner0e744122002-10-17 04:26:54 +000064 // TD ...Merge the formal arg scalar with the actual arg node
65 DSNodeHandle &NodeForFormal = Graph.getNodeForValue(AI);
Chris Lattner99a22842002-10-21 15:04:18 +000066 assert(NodeForFormal.getNode() && "Pointer argument has no dest node!");
67 NodeForFormal.mergeWith(CallSite.getPtrArg(i));
Chris Lattner0e744122002-10-17 04:26:54 +000068 }
69
70 // Merge returned node in the caller with the "return" node in callee
Chris Lattner0969c502002-10-21 02:08:03 +000071 if (CallSite.getRetVal().getNode() && Graph.getRetNode().getNode())
72 Graph.getRetNode().mergeWith(CallSite.getRetVal());
Vikram S. Adveaaeee752002-07-30 22:06:40 +000073}
74
Chris Lattner7a211632002-11-08 21:28:37 +000075DSGraph &TDDataStructures::getOrCreateDSGraph(Function &F) {
76 DSGraph *&G = DSInfo[&F];
77 if (G == 0) { // Not created yet? Clone BU graph...
78 G = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F));
79 G->getAuxFunctionCalls().clear();
80 }
81 return *G;
82}
Vikram S. Adve26b98262002-10-20 21:41:02 +000083
Chris Lattner7a211632002-11-08 21:28:37 +000084void TDDataStructures::calculateGraph(Function &F) {
85 // Make sure this graph has not already been calculated, and that we don't get
Vikram S. Adveaaeee752002-07-30 22:06:40 +000086 // into an infinite loop with mutually recursive functions.
87 //
Chris Lattner7a211632002-11-08 21:28:37 +000088 if (GraphDone.count(&F)) return;
89 GraphDone.insert(&F);
Vikram S. Adveaaeee752002-07-30 22:06:40 +000090
Chris Lattner7a211632002-11-08 21:28:37 +000091 // Get the current functions graph...
92 DSGraph &Graph = getOrCreateDSGraph(F);
Chris Lattner198be222002-10-21 19:47:18 +000093
Chris Lattner7a211632002-11-08 21:28:37 +000094 const std::vector<DSCallSite> &CallSites = Graph.getFunctionCalls();
95#if 0
96 if (CallSites.empty()) {
97 DEBUG(std::cerr << " [TD] No callees for: " << F.getName() << "\n");
98 return; // If no call sites, the graph is the same as the BU graph!
Chris Lattner4bdb9b72002-10-22 16:01:03 +000099 }
Chris Lattner7a211632002-11-08 21:28:37 +0000100#endif
101 // Loop over all of the call sites, building a multi-map from Callees to
102 // DSCallSite*'s. With this map we can then loop over each callee, cloning
103 // this graph once into it, then resolving arguments.
Chris Lattner0e744122002-10-17 04:26:54 +0000104 //
Chris Lattner7a211632002-11-08 21:28:37 +0000105 std::multimap<Function*, const DSCallSite*> CalleeSites;
106 for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
107 const DSCallSite &CS = CallSites[i];
108 const std::vector<GlobalValue*> Callees =
109 CS.getCallee().getNode()->getGlobals();
Chris Lattner198be222002-10-21 19:47:18 +0000110
Chris Lattner7a211632002-11-08 21:28:37 +0000111 // Loop over all of the functions that this call may invoke...
112 for (unsigned c = 0, e = Callees.size(); c != e; ++c)
113 if (Function *F = dyn_cast<Function>(Callees[c])) // If this is a fn...
114 if (!F->isExternal()) // If it's not external
115 CalleeSites.insert(std::make_pair(F, &CS)); // Keep track of it!
Chris Lattner0e744122002-10-17 04:26:54 +0000116 }
Chris Lattner0e744122002-10-17 04:26:54 +0000117
Chris Lattner7a211632002-11-08 21:28:37 +0000118 // Now that we have information about all of the callees, propogate the
119 // current graph into the callees.
120 //
121 DEBUG(std::cerr << " [TD] Inlining '" << F.getName() << "' into "
122 << CalleeSites.size() << " callees.\n");
123
124 // Loop over all the callees...
125 for (std::multimap<Function*, const DSCallSite*>::iterator
126 I = CalleeSites.begin(), E = CalleeSites.end(); I != E; )
127 if (I->first == &F) { // Bottom-up pass takes care of self loops!
128 ++I;
129 } else {
130 // For each callee...
131 Function *Callee = I->first;
132 DSGraph &CG = getOrCreateDSGraph(*Callee); // Get the callee's graph...
133
134 DEBUG(std::cerr << "\t [TD] Inlining into callee '" << Callee->getName()
135 << "'\n");
136
137 // Clone our current graph into the callee...
138 std::map<Value*, DSNodeHandle> OldValMap;
139 std::map<const DSNode*, DSNodeHandle> OldNodeMap;
140 CG.cloneInto(Graph, OldValMap, OldNodeMap,
141 DSGraph::KeepAllocaBit | DSGraph::DontCloneCallNodes);
142 OldValMap.clear(); // We don't care about the ValMap
143
144 // Loop over all of the invocation sites of the callee, resolving
145 // arguments to our graph. This loop may iterate multiple times if the
146 // current function calls this callee multiple times with different
147 // signatures.
148 //
149 for (; I != E && I->first == Callee; ++I) {
150 // Map call site into callee graph
151 DSCallSite NewCS(*I->second, OldNodeMap);
152
153 // Resolve the return values...
154 NewCS.getRetVal().mergeWith(CG.getRetNode());
155
156 // Resolve all of the arguments...
157 Function::aiterator AI = Callee->abegin();
158 for (unsigned i = 0, e = NewCS.getNumPtrArgs(); i != e; ++i, ++AI) {
159 // Advance the argument iterator to the first pointer argument...
160 while (!DS::isPointerType(AI->getType())) {
161 ++AI;
162#ifndef NDEBUG
163 if (AI == Callee->aend())
164 std::cerr << "Bad call to Function: " << Callee->getName()<< "\n";
165#endif
166 assert(AI != Callee->aend() &&
167 "# Args provided is not # Args required!");
168 }
169
170 // Add the link from the argument scalar to the provided value
171 DSNodeHandle &NH = CG.getNodeForValue(AI);
172 assert(NH.getNode() && "Pointer argument without scalarmap entry?");
173 NH.mergeWith(NewCS.getPtrArg(i));
174 }
175 }
176
177 // Done with the nodemap...
178 OldNodeMap.clear();
179
180 // Recompute the Incomplete markers and eliminate unreachable nodes.
181 CG.maskIncompleteMarkers();
182 CG.markIncompleteNodes(/*markFormals*/ !F.hasInternalLinkage()
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000183 /*&& FIXME: NEED TO CHECK IF ALL CALLERS FOUND!*/);
Chris Lattner7a211632002-11-08 21:28:37 +0000184 CG.removeTriviallyDeadNodes(false);
185 CG.removeDeadNodes(false, true) ;///*KeepAllGlobals*/ false, true);
186 ///*KeepCalls*/ false);
187 }
Chris Lattner4bdb9b72002-10-22 16:01:03 +0000188
Chris Lattner7a211632002-11-08 21:28:37 +0000189 DEBUG(std::cerr << " [TD] Done inlining into callees for: " << F.getName()
190 << " [" << Graph.getGraphSize() << "+"
191 << Graph.getFunctionCalls().size() << "]\n");
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000192
Chris Lattner7a211632002-11-08 21:28:37 +0000193
194 // Loop over all the callees... making sure they are all resolved now...
195 Function *LastFunc = 0;
196 for (std::multimap<Function*, const DSCallSite*>::iterator
197 I = CalleeSites.begin(), E = CalleeSites.end(); I != E; ++I)
198 if (I->first != LastFunc) { // Only visit each callee once...
199 LastFunc = I->first;
200 calculateGraph(*I->first);
201 }
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000202}