blob: 9671c8049ddcb2736b03edec303dcd86c63873ed [file] [log] [blame]
Chris Lattner64fd9352002-03-28 18:08:31 +00001//===-- PoolAllocate.cpp - Pool Allocation Pass ---------------------------===//
2//
3// This transform changes programs so that disjoint data structures are
4// allocated out of different pools of memory, increasing locality and shrinking
5// pointer size.
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Transforms/IPO/PoolAllocate.h"
10#include "llvm/Analysis/DataStructure.h"
11#include "llvm/Pass.h"
Chris Lattner175f37c2002-03-29 03:40:59 +000012#include "llvm/Module.h"
13#include "llvm/Function.h"
14#include "llvm/iMemory.h"
Chris Lattnere0618ca2002-03-29 05:50:20 +000015#include "llvm/iTerminators.h"
16#include "llvm/iOther.h"
17#include "llvm/ConstantVals.h"
18#include "llvm/Target/TargetData.h"
19#include "Support/STLExtras.h"
Chris Lattner175f37c2002-03-29 03:40:59 +000020#include <algorithm>
Chris Lattner64fd9352002-03-28 18:08:31 +000021
Chris Lattnere0618ca2002-03-29 05:50:20 +000022// FIXME: This is dependant on the sparc backend layout conventions!!
23static TargetData TargetData("test");
24
Chris Lattner175f37c2002-03-29 03:40:59 +000025// Define the pass class that we implement...
Chris Lattner64fd9352002-03-28 18:08:31 +000026namespace {
Chris Lattner175f37c2002-03-29 03:40:59 +000027 class PoolAllocate : public Pass {
28 // PoolTy - The type of a scalar value that contains a pool pointer.
29 PointerType *PoolTy;
30 public:
31
32 PoolAllocate() {
33 // Initialize the PoolTy instance variable, since the type never changes.
34 vector<const Type*> PoolElements;
35 PoolElements.push_back(PointerType::get(Type::SByteTy));
36 PoolElements.push_back(Type::UIntTy);
37 PoolTy = PointerType::get(StructType::get(PoolElements));
38 // PoolTy = { sbyte*, uint }*
39
40 CurModule = 0; DS = 0;
41 PoolInit = PoolDestroy = PoolAlloc = PoolFree = 0;
Chris Lattner64fd9352002-03-28 18:08:31 +000042 }
43
Chris Lattner175f37c2002-03-29 03:40:59 +000044 bool run(Module *M);
45
46 // getAnalysisUsageInfo - This function requires data structure information
47 // to be able to see what is pool allocatable.
Chris Lattner64fd9352002-03-28 18:08:31 +000048 //
49 virtual void getAnalysisUsageInfo(Pass::AnalysisSet &Required,
Chris Lattner175f37c2002-03-29 03:40:59 +000050 Pass::AnalysisSet &,Pass::AnalysisSet &) {
Chris Lattner64fd9352002-03-28 18:08:31 +000051 Required.push_back(DataStructure::ID);
52 }
Chris Lattner175f37c2002-03-29 03:40:59 +000053
54 private:
55 // CurModule - The module being processed.
56 Module *CurModule;
57
58 // DS - The data structure graph for the module being processed.
59 DataStructure *DS;
60
61 // Prototypes that we add to support pool allocation...
62 Function *PoolInit, *PoolDestroy, *PoolAlloc, *PoolFree;
63
64 // addPoolPrototypes - Add prototypes for the pool methods to the specified
65 // module and update the Pool* instance variables to point to them.
66 //
67 void addPoolPrototypes(Module *M);
68
Chris Lattner66df97d2002-03-29 06:21:38 +000069
70 // CreatePools - Insert instructions into the function we are processing to
71 // create all of the memory pool objects themselves. This also inserts
72 // destruction code. Add an alloca for each pool that is allocated to the
73 // PoolDescriptors vector.
74 //
75 void CreatePools(Function *F, const vector<AllocDSNode*> &Allocs,
76 vector<AllocaInst*> &PoolDescriptors);
77
Chris Lattner175f37c2002-03-29 03:40:59 +000078 // processFunction - Convert a function to use pool allocation where
79 // available.
80 //
81 bool processFunction(Function *F);
Chris Lattner64fd9352002-03-28 18:08:31 +000082 };
83}
84
Chris Lattner175f37c2002-03-29 03:40:59 +000085
86
87// isNotPoolableAlloc - This is a predicate that returns true if the specified
88// allocation node in a data structure graph is eligable for pool allocation.
89//
90static bool isNotPoolableAlloc(const AllocDSNode *DS) {
Chris Lattnere0618ca2002-03-29 05:50:20 +000091 if (DS->isAllocaNode()) return true; // Do not pool allocate alloca's.
Chris Lattner175f37c2002-03-29 03:40:59 +000092
93 MallocInst *MI = cast<MallocInst>(DS->getAllocation());
94 if (MI->isArrayAllocation() && !isa<Constant>(MI->getArraySize()))
Chris Lattnere0618ca2002-03-29 05:50:20 +000095 return true; // Do not allow variable size allocations...
Chris Lattner175f37c2002-03-29 03:40:59 +000096
Chris Lattnere0618ca2002-03-29 05:50:20 +000097 return false;
Chris Lattner175f37c2002-03-29 03:40:59 +000098}
99
100
101// processFunction - Convert a function to use pool allocation where
102// available.
103//
104bool PoolAllocate::processFunction(Function *F) {
105 // Get the closed datastructure graph for the current function... if there are
106 // any allocations in this graph that are not escaping, we need to pool
107 // allocate them here!
108 //
109 FunctionDSGraph &IPGraph = DS->getClosedDSGraph(F);
110
111 // Get all of the allocations that do not escape the current function. Since
112 // they are still live (they exist in the graph at all), this means we must
113 // have scalar references to these nodes, but the scalars are never returned.
114 //
115 std::vector<AllocDSNode*> Allocs;
116 IPGraph.getNonEscapingAllocations(Allocs);
117
118 // Filter out allocations that we cannot handle. Currently, this includes
119 // variable sized array allocations and alloca's (which we do not want to
120 // pool allocate)
121 //
122 Allocs.erase(remove_if(Allocs.begin(), Allocs.end(), isNotPoolableAlloc),
123 Allocs.end());
124
125
126 if (Allocs.empty()) return false; // Nothing to do.
127
128 // Loop through the value map looking for scalars that refer to nonescaping
129 // allocations.
130 //
131 map<Value*, PointerValSet> &ValMap = IPGraph.getValueMap();
132 vector<pair<Value*, AllocDSNode*> > Scalars;
133
134 for (map<Value*, PointerValSet>::iterator I = ValMap.begin(),
135 E = ValMap.end(); I != E; ++I) {
136 const PointerValSet &PVS = I->second; // Set of things pointed to by scalar
137 // Check to see if the scalar points to anything that is an allocation...
138 for (unsigned i = 0, e = PVS.size(); i != e; ++i)
139 if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(PVS[i].Node)) {
140 assert(PVS[i].Index == 0 && "Nonzero not handled yet!");
141
142 // If the allocation is in the nonescaping set...
143 if (find(Allocs.begin(), Allocs.end(), Alloc) != Allocs.end())
144 // Add it to the list of scalars we have
145 Scalars.push_back(make_pair(I->first, Alloc));
146 }
147 }
148
149 cerr << "In '" << F->getName()
150 << "': Found the following values that point to poolable nodes:\n";
151
152 for (unsigned i = 0, e = Scalars.size(); i != e; ++i)
153 Scalars[i].first->dump();
Chris Lattnere0618ca2002-03-29 05:50:20 +0000154
Chris Lattner66df97d2002-03-29 06:21:38 +0000155 // Insert instructions into the function we are processing to create all of
156 // the memory pool objects themselves. This also inserts destruction code.
157 vector<AllocaInst*> PoolDescriptors;
158 CreatePools(F, Allocs, PoolDescriptors);
159
160 return true;
161}
162
163
164// CreatePools - Insert instructions into the function we are processing to
165// create all of the memory pool objects themselves. This also inserts
166// destruction code. Add an alloca for each pool that is allocated to the
167// PoolDescriptors vector.
168//
169void PoolAllocate::CreatePools(Function *F, const vector<AllocDSNode*> &Allocs,
170 vector<AllocaInst*> &PoolDescriptors) {
Chris Lattnere0618ca2002-03-29 05:50:20 +0000171 // FIXME: This should use an IP version of the UnifyAllExits pass!
172 vector<BasicBlock*> ReturnNodes;
173 for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I)
174 if (isa<ReturnInst>((*I)->getTerminator()))
175 ReturnNodes.push_back(*I);
176
177
178 // Create the code that goes in the entry and exit nodes for the method...
179 vector<Instruction*> EntryNodeInsts;
180 for (unsigned i = 0, e = Allocs.size(); i != e; ++i) {
181 // Add an allocation and a free for each pool...
182 AllocaInst *PoolAlloc = new AllocaInst(PoolTy, 0, "pool");
183 EntryNodeInsts.push_back(PoolAlloc);
184
185 AllocationInst *AI = Allocs[i]->getAllocation();
186
187 // Initialize the pool. We need to know how big each allocation is. For
188 // our purposes here, we assume we are allocating a scalar, or array of
189 // constant size.
190 //
191 unsigned ElSize = TargetData.getTypeSize(AI->getAllocatedType());
192 ElSize *= cast<ConstantUInt>(AI->getArraySize())->getValue();
193
194 vector<Value*> Args;
195 Args.push_back(PoolAlloc); // Pool to initialize
196 Args.push_back(ConstantUInt::get(Type::UIntTy, ElSize));
197 EntryNodeInsts.push_back(new CallInst(PoolInit, Args));
198
199 // Destroy the pool...
200 Args.pop_back();
201
202 for (unsigned EN = 0, ENE = ReturnNodes.size(); EN != ENE; ++EN) {
203 Instruction *Destroy = new CallInst(PoolDestroy, Args);
204
205 // Insert it before the return instruction...
206 BasicBlock *RetNode = ReturnNodes[EN];
207 RetNode->getInstList().insert(RetNode->end()-1, Destroy);
208 }
209 }
210
211 // Insert the entry node code into the entry block...
212 F->getEntryNode()->getInstList().insert(F->getEntryNode()->begin()+1,
213 EntryNodeInsts.begin(),
214 EntryNodeInsts.end());
Chris Lattner175f37c2002-03-29 03:40:59 +0000215}
216
217
Chris Lattner175f37c2002-03-29 03:40:59 +0000218// addPoolPrototypes - Add prototypes for the pool methods to the specified
219// module and update the Pool* instance variables to point to them.
220//
221void PoolAllocate::addPoolPrototypes(Module *M) {
Chris Lattnere0618ca2002-03-29 05:50:20 +0000222 // Get PoolInit function...
223 vector<const Type*> Args;
224 Args.push_back(PoolTy); // Pool to initialize
225 Args.push_back(Type::UIntTy); // Num bytes per element
226 FunctionType *PoolInitTy = FunctionType::get(Type::VoidTy, Args, false);
227 PoolInit = M->getOrInsertFunction("poolinit", PoolInitTy);
Chris Lattner175f37c2002-03-29 03:40:59 +0000228
Chris Lattnere0618ca2002-03-29 05:50:20 +0000229 // Get pooldestroy function...
230 Args.pop_back(); // Only takes a pool...
231 FunctionType *PoolDestroyTy = FunctionType::get(Type::VoidTy, Args, false);
232 PoolDestroy = M->getOrInsertFunction("pooldestroy", PoolDestroyTy);
233
234 const Type *PtrVoid = PointerType::get(Type::SByteTy);
235
236 // Get the poolalloc function...
237 FunctionType *PoolAllocTy = FunctionType::get(PtrVoid, Args, false);
238 PoolAlloc = M->getOrInsertFunction("poolalloc", PoolAllocTy);
239
240 // Get the poolfree function...
241 Args.push_back(PtrVoid);
242 FunctionType *PoolFreeTy = FunctionType::get(Type::VoidTy, Args, false);
243 PoolFree = M->getOrInsertFunction("poolfree", PoolFreeTy);
244
245 // Add the %PoolTy type to the symbol table of the module...
246 M->addTypeName("PoolTy", PoolTy->getElementType());
Chris Lattner175f37c2002-03-29 03:40:59 +0000247}
248
249
250bool PoolAllocate::run(Module *M) {
251 addPoolPrototypes(M);
252 CurModule = M;
253
254 DS = &getAnalysis<DataStructure>();
255 bool Changed = false;
256 for (Module::iterator I = M->begin(); I != M->end(); ++I)
257 if (!(*I)->isExternal())
258 Changed |= processFunction(*I);
259
260 CurModule = 0;
261 DS = 0;
262 return false;
263}
264
265
266// createPoolAllocatePass - Global function to access the functionality of this
267// pass...
268//
Chris Lattner64fd9352002-03-28 18:08:31 +0000269Pass *createPoolAllocatePass() { return new PoolAllocate(); }