blob: 69422caa8f0ba965822218479e2032e66b7876de [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"
Chris Lattner4bdb9b72002-10-22 16:01:03 +000015#include <set>
Vikram S. Adveaaeee752002-07-30 22:06:40 +000016
17static RegisterAnalysis<TDDataStructures>
18Y("tddatastructure", "Top-down Data Structure Analysis Closure");
Vikram S. Adveaaeee752002-07-30 22:06:40 +000019
20// releaseMemory - If the pass pipeline is done with this pass, we can release
21// our memory... here...
22//
23void TDDataStructures::releaseMemory() {
Chris Lattner198be222002-10-21 19:47:18 +000024 BUMaps.clear();
Chris Lattner13ec72a2002-10-21 13:31:48 +000025 for (std::map<const Function*, DSGraph*>::iterator I = DSInfo.begin(),
Vikram S. Adveaaeee752002-07-30 22:06:40 +000026 E = DSInfo.end(); I != E; ++I)
27 delete I->second;
28
29 // Empty map so next time memory is released, data structures are not
30 // re-deleted.
31 DSInfo.clear();
32}
33
34// run - Calculate the top down data structure graphs for each function in the
35// program.
36//
37bool TDDataStructures::run(Module &M) {
Chris Lattner4bdb9b72002-10-22 16:01:03 +000038 BUDataStructures &BU = getAnalysis<BUDataStructures>();
39
40 // Calculate the CallSitesForFunction mapping from the BU info...
41 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
42 if (!I->isExternal())
43 if (const std::vector<DSCallSite> *CS = BU.getCallSites(*I))
44 for (unsigned i = 0, e = CS->size(); i != e; ++i)
45 if (Function *F = (*CS)[i].getResolvingCaller())
46 CallSitesForFunction[F].push_back(&(*CS)[i]);
47
48 // Next calculate the graphs for each function...
Vikram S. Adveaaeee752002-07-30 22:06:40 +000049 for (Module::reverse_iterator I = M.rbegin(), E = M.rend(); I != E; ++I)
50 if (!I->isExternal())
51 calculateGraph(*I);
Chris Lattner4bdb9b72002-10-22 16:01:03 +000052
53 // Destroy the temporary mapping...
54 CallSitesForFunction.clear();
Vikram S. Adveaaeee752002-07-30 22:06:40 +000055 return false;
56}
57
Chris Lattner0e744122002-10-17 04:26:54 +000058/// ResolveCallSite - This method is used to link the actual arguments together
59/// with the formal arguments for a function call in the top-down closure. This
60/// method assumes that the call site arguments have been mapped into nodes
61/// local to the specified graph.
62///
63void TDDataStructures::ResolveCallSite(DSGraph &Graph,
Vikram S. Adve42fd1692002-10-20 18:07:37 +000064 const DSCallSite &CallSite) {
Chris Lattner0e744122002-10-17 04:26:54 +000065 // Resolve all of the function formal arguments...
66 Function &F = Graph.getFunction();
67 Function::aiterator AI = F.abegin();
Vikram S. Adveaaeee752002-07-30 22:06:40 +000068
Vikram S. Adve26b98262002-10-20 21:41:02 +000069 for (unsigned i = 0, e = CallSite.getNumPtrArgs(); i != e; ++i, ++AI) {
Chris Lattner0e744122002-10-17 04:26:54 +000070 // Advance the argument iterator to the first pointer argument...
Chris Lattnerb1060432002-11-07 05:20:53 +000071 while (!DS::isPointerType(AI->getType())) ++AI;
Vikram S. Adveaaeee752002-07-30 22:06:40 +000072
Chris Lattner0e744122002-10-17 04:26:54 +000073 // TD ...Merge the formal arg scalar with the actual arg node
74 DSNodeHandle &NodeForFormal = Graph.getNodeForValue(AI);
Chris Lattner99a22842002-10-21 15:04:18 +000075 assert(NodeForFormal.getNode() && "Pointer argument has no dest node!");
76 NodeForFormal.mergeWith(CallSite.getPtrArg(i));
Chris Lattner0e744122002-10-17 04:26:54 +000077 }
78
79 // Merge returned node in the caller with the "return" node in callee
Chris Lattner0969c502002-10-21 02:08:03 +000080 if (CallSite.getRetVal().getNode() && Graph.getRetNode().getNode())
81 Graph.getRetNode().mergeWith(CallSite.getRetVal());
Vikram S. Adveaaeee752002-07-30 22:06:40 +000082}
83
Vikram S. Adve26b98262002-10-20 21:41:02 +000084
Vikram S. Adveaaeee752002-07-30 22:06:40 +000085DSGraph &TDDataStructures::calculateGraph(Function &F) {
86 // Make sure this graph has not already been calculated, or that we don't get
87 // into an infinite loop with mutually recursive functions.
88 //
89 DSGraph *&Graph = DSInfo[&F];
90 if (Graph) return *Graph;
91
Chris Lattner0e744122002-10-17 04:26:54 +000092 BUDataStructures &BU = getAnalysis<BUDataStructures>();
93 DSGraph &BUGraph = BU.getDSGraph(F);
Chris Lattner198be222002-10-21 19:47:18 +000094
95 // Copy the BU graph, keeping a mapping from the BUGraph to the current Graph
96 std::map<const DSNode*, DSNode*> BUNodeMap;
97 Graph = new DSGraph(BUGraph, BUNodeMap);
98
Chris Lattner4bdb9b72002-10-22 16:01:03 +000099 // We only need the BUMap entries for the nodes that are used in call sites.
100 // Calculate which nodes are needed.
101 std::set<const DSNode*> NeededNodes;
102 std::map<const Function*, std::vector<const DSCallSite*> >::iterator CSFFI
103 = CallSitesForFunction.find(&F);
104 if (CSFFI == CallSitesForFunction.end()) {
105 BUNodeMap.clear(); // No nodes are neccesary
106 } else {
107 std::vector<const DSCallSite*> &CSV = CSFFI->second;
108 for (unsigned i = 0, e = CSV.size(); i != e; ++i) {
109 NeededNodes.insert(CSV[i]->getRetVal().getNode());
110 for (unsigned j = 0, je = CSV[i]->getNumPtrArgs(); j != je; ++j)
111 NeededNodes.insert(CSV[i]->getPtrArg(j).getNode());
112 }
113 }
114
115 // Loop through te BUNodeMap, keeping only the nodes that are "Needed"
116 for (std::map<const DSNode*, DSNode*>::iterator I = BUNodeMap.begin();
117 I != BUNodeMap.end(); )
118 if (NeededNodes.count(I->first) && I->first) // Keep needed nodes...
119 ++I;
120 else {
121 std::map<const DSNode*, DSNode*>::iterator J = I++;
122 BUNodeMap.erase(J);
123 }
124
125 NeededNodes.clear(); // We are done with this temporary data structure
126
Chris Lattner198be222002-10-21 19:47:18 +0000127 // Convert the mapping from a node-to-node map into a node-to-nodehandle map
Chris Lattner4bdb9b72002-10-22 16:01:03 +0000128 BUNodeMapTy &BUMap = BUMaps[&F];
129 BUMap.insert(BUNodeMap.begin(), BUNodeMap.end());
Chris Lattner198be222002-10-21 19:47:18 +0000130 BUNodeMap.clear(); // We are done with the temporary map.
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000131
Chris Lattner13ec72a2002-10-21 13:31:48 +0000132 const std::vector<DSCallSite> *CallSitesP = BU.getCallSites(F);
Chris Lattner0e744122002-10-17 04:26:54 +0000133 if (CallSitesP == 0) {
134 DEBUG(std::cerr << " [TD] No callers for: " << F.getName() << "\n");
135 return *Graph; // If no call sites, the graph is the same as the BU graph!
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000136 }
137
Chris Lattner0e744122002-10-17 04:26:54 +0000138 // Loop over all call sites of this function, merging each one into this
139 // graph.
140 //
141 DEBUG(std::cerr << " [TD] Inlining callers for: " << F.getName() << "\n");
Chris Lattner13ec72a2002-10-21 13:31:48 +0000142 const std::vector<DSCallSite> &CallSites = *CallSitesP;
Chris Lattner0e744122002-10-17 04:26:54 +0000143 for (unsigned c = 0, ce = CallSites.size(); c != ce; ++c) {
Chris Lattner198be222002-10-21 19:47:18 +0000144 const DSCallSite &CallSite = CallSites[c];
145 Function &Caller = *CallSite.getResolvingCaller();
146 assert(&Caller && !Caller.isExternal() &&
147 "Externals function cannot 'call'!");
Chris Lattner0e744122002-10-17 04:26:54 +0000148
149 DEBUG(std::cerr << "\t [TD] Inlining caller #" << c << " '"
150 << Caller.getName() << "' into callee: " << F.getName() << "\n");
151
Chris Lattner198be222002-10-21 19:47:18 +0000152 if (&Caller == &F) {
153 // Self-recursive call: this can happen after a cycle of calls is inlined.
154 ResolveCallSite(*Graph, CallSite);
155 } else {
156
Chris Lattner99a22842002-10-21 15:04:18 +0000157 // Recursively compute the graph for the Caller. It should be fully
158 // resolved except if there is mutual recursion...
Chris Lattner0e744122002-10-17 04:26:54 +0000159 //
160 DSGraph &CG = calculateGraph(Caller); // Graph to inline
161
162 DEBUG(std::cerr << "\t\t[TD] Got graph for " << Caller.getName()
163 << " in: " << F.getName() << "\n");
164
165 // These two maps keep track of where scalars in the old graph _used_
166 // to point to, and of new nodes matching nodes of the old graph.
167 std::map<Value*, DSNodeHandle> OldValMap;
168 std::map<const DSNode*, DSNode*> OldNodeMap;
169
Chris Lattner198be222002-10-21 19:47:18 +0000170 // Translate call site from having links into the BU graph
171 DSCallSite CallSiteInCG(CallSite, BUMaps[&Caller]);
172
Chris Lattner0e744122002-10-17 04:26:54 +0000173 // Clone the Caller's graph into the current graph, keeping
174 // track of where scalars in the old graph _used_ to point...
175 // Do this here because it only needs to happens once for each Caller!
176 // Strip scalars but not allocas since they are alive in callee.
177 //
178 DSNodeHandle RetVal = Graph->cloneInto(CG, OldValMap, OldNodeMap,
Chris Lattnere4ae3042002-10-21 19:50:29 +0000179 /*StripAllocas*/ false);
Chris Lattner198be222002-10-21 19:47:18 +0000180 ResolveCallSite(*Graph, DSCallSite(CallSiteInCG, OldNodeMap));
Chris Lattner0e744122002-10-17 04:26:54 +0000181 }
182 }
Chris Lattner0e744122002-10-17 04:26:54 +0000183
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000184 // Recompute the Incomplete markers and eliminate unreachable nodes.
185 Graph->maskIncompleteMarkers();
Chris Lattner19db0492002-10-17 04:57:28 +0000186 Graph->markIncompleteNodes(/*markFormals*/ !F.hasInternalLinkage()
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000187 /*&& FIXME: NEED TO CHECK IF ALL CALLERS FOUND!*/);
188 Graph->removeDeadNodes(/*KeepAllGlobals*/ false, /*KeepCalls*/ false);
Chris Lattner4bdb9b72002-10-22 16:01:03 +0000189
Chris Lattner221c9792002-08-07 21:41:11 +0000190 DEBUG(std::cerr << " [TD] Done inlining callers for: " << F.getName() << " ["
191 << Graph->getGraphSize() << "+" << Graph->getFunctionCalls().size()
192 << "]\n");
Vikram S. Adveaaeee752002-07-30 22:06:40 +0000193
194 return *Graph;
195}