mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-28 08:59:28 +00:00
Implement the first step of pool allocation - Creating, initialization, and
destruction of the pools. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2039 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b04bb3f158
commit
54ce13f983
@ -12,8 +12,16 @@
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/iMemory.h"
|
||||
#include "llvm/iTerminators.h"
|
||||
#include "llvm/iOther.h"
|
||||
#include "llvm/ConstantVals.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "Support/STLExtras.h"
|
||||
#include <algorithm>
|
||||
|
||||
// FIXME: This is dependant on the sparc backend layout conventions!!
|
||||
static TargetData TargetData("test");
|
||||
|
||||
// Define the pass class that we implement...
|
||||
namespace {
|
||||
class PoolAllocate : public Pass {
|
||||
@ -71,13 +79,13 @@ namespace {
|
||||
// allocation node in a data structure graph is eligable for pool allocation.
|
||||
//
|
||||
static bool isNotPoolableAlloc(const AllocDSNode *DS) {
|
||||
if (DS->isAllocaNode()) return false; // Do not pool allocate alloca's.
|
||||
if (DS->isAllocaNode()) return true; // Do not pool allocate alloca's.
|
||||
|
||||
MallocInst *MI = cast<MallocInst>(DS->getAllocation());
|
||||
if (MI->isArrayAllocation() && !isa<Constant>(MI->getArraySize()))
|
||||
return false; // Do not allow variable size allocations...
|
||||
return true; // Do not allow variable size allocations...
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -134,19 +142,85 @@ bool PoolAllocate::processFunction(Function *F) {
|
||||
|
||||
for (unsigned i = 0, e = Scalars.size(); i != e; ++i)
|
||||
Scalars[i].first->dump();
|
||||
|
||||
// FIXME: This should use an IP version of the UnifyAllExits pass!
|
||||
vector<BasicBlock*> ReturnNodes;
|
||||
for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I)
|
||||
if (isa<ReturnInst>((*I)->getTerminator()))
|
||||
ReturnNodes.push_back(*I);
|
||||
|
||||
|
||||
// Create the code that goes in the entry and exit nodes for the method...
|
||||
vector<Instruction*> EntryNodeInsts;
|
||||
for (unsigned i = 0, e = Allocs.size(); i != e; ++i) {
|
||||
// Add an allocation and a free for each pool...
|
||||
AllocaInst *PoolAlloc = new AllocaInst(PoolTy, 0, "pool");
|
||||
EntryNodeInsts.push_back(PoolAlloc);
|
||||
|
||||
AllocationInst *AI = Allocs[i]->getAllocation();
|
||||
|
||||
// Initialize the pool. We need to know how big each allocation is. For
|
||||
// our purposes here, we assume we are allocating a scalar, or array of
|
||||
// constant size.
|
||||
//
|
||||
unsigned ElSize = TargetData.getTypeSize(AI->getAllocatedType());
|
||||
ElSize *= cast<ConstantUInt>(AI->getArraySize())->getValue();
|
||||
|
||||
vector<Value*> Args;
|
||||
Args.push_back(PoolAlloc); // Pool to initialize
|
||||
Args.push_back(ConstantUInt::get(Type::UIntTy, ElSize));
|
||||
EntryNodeInsts.push_back(new CallInst(PoolInit, Args));
|
||||
|
||||
// Destroy the pool...
|
||||
Args.pop_back();
|
||||
|
||||
for (unsigned EN = 0, ENE = ReturnNodes.size(); EN != ENE; ++EN) {
|
||||
Instruction *Destroy = new CallInst(PoolDestroy, Args);
|
||||
|
||||
// Insert it before the return instruction...
|
||||
BasicBlock *RetNode = ReturnNodes[EN];
|
||||
RetNode->getInstList().insert(RetNode->end()-1, Destroy);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the entry node code into the entry block...
|
||||
F->getEntryNode()->getInstList().insert(F->getEntryNode()->begin()+1,
|
||||
EntryNodeInsts.begin(),
|
||||
EntryNodeInsts.end());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Prototypes that we add to support pool allocation...
|
||||
Function *PoolInit, *PoolDestroy, *PoolAlloc, *PoolFree;
|
||||
|
||||
// addPoolPrototypes - Add prototypes for the pool methods to the specified
|
||||
// module and update the Pool* instance variables to point to them.
|
||||
//
|
||||
void PoolAllocate::addPoolPrototypes(Module *M) {
|
||||
//M->getOrCreate...
|
||||
// Get PoolInit function...
|
||||
vector<const Type*> Args;
|
||||
Args.push_back(PoolTy); // Pool to initialize
|
||||
Args.push_back(Type::UIntTy); // Num bytes per element
|
||||
FunctionType *PoolInitTy = FunctionType::get(Type::VoidTy, Args, false);
|
||||
PoolInit = M->getOrInsertFunction("poolinit", PoolInitTy);
|
||||
|
||||
// Get pooldestroy function...
|
||||
Args.pop_back(); // Only takes a pool...
|
||||
FunctionType *PoolDestroyTy = FunctionType::get(Type::VoidTy, Args, false);
|
||||
PoolDestroy = M->getOrInsertFunction("pooldestroy", PoolDestroyTy);
|
||||
|
||||
const Type *PtrVoid = PointerType::get(Type::SByteTy);
|
||||
|
||||
// Get the poolalloc function...
|
||||
FunctionType *PoolAllocTy = FunctionType::get(PtrVoid, Args, false);
|
||||
PoolAlloc = M->getOrInsertFunction("poolalloc", PoolAllocTy);
|
||||
|
||||
// Get the poolfree function...
|
||||
Args.push_back(PtrVoid);
|
||||
FunctionType *PoolFreeTy = FunctionType::get(Type::VoidTy, Args, false);
|
||||
PoolFree = M->getOrInsertFunction("poolfree", PoolFreeTy);
|
||||
|
||||
// Add the %PoolTy type to the symbol table of the module...
|
||||
M->addTypeName("PoolTy", PoolTy->getElementType());
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user