DataStructure *DS;
// Prototypes that we add to support pool allocation...
- Function *PoolInit, *PoolDestroy, *PoolAlloc, *PoolFree;
+ Function *PoolInit, *PoolDestroy, *PoolAlloc, *PoolAllocArray, *PoolFree;
// The map of already transformed functions... note that the keys of this
// map do not have meaningful values for 'Call' or the 'PoolHandle' elements
//
static bool isNotPoolableAlloc(const AllocDSNode *DS) {
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 true; // Do not allow variable size allocations...
-
return false;
}
if (isa<Constant>(Ref.OldVal) && // Refering to a null ptr?
cast<Constant>(Ref.OldVal)->isNullValue()) {
// Transform the null pointer into a null index... caching in XFormMap
- XFormMap[Ref.OldVal] = NewVal =Constant::getNullConstant(POINTERTYPE);
+ XFormMap[Ref.OldVal] = NewVal = Constant::getNullValue(POINTERTYPE);
//} else if (isa<Argument>(Ref.OldVal)) {
} else {
cerr << "Unknown reference to: " << Ref.OldVal << "\n";
Instruction *PoolBase = createPoolBaseInstruction(I->getOperand(0));
// Cast our index to be a UIntTy so we can use it to index into the pool...
- CastInst *Index = new CastInst(Constant::getNullConstant(POINTERTYPE),
+ CastInst *Index = new CastInst(Constant::getNullValue(POINTERTYPE),
Type::UIntTy, I->getOperand(0)->getName());
ReferencesToUpdate.push_back(RefToUpdate(Index, 0, I->getOperand(0)));
vector<Value*> Indices(I->idx_begin(), I->idx_end());
- assert(Indices[0] == ConstantUInt::get(Type::UIntTy, 0) &&
- "Cannot handle array indexing yet!");
- Indices[0] = Index;
+ Instruction *IdxInst =
+ BinaryOperator::create(Instruction::Add, Indices[0], Index,
+ I->getName()+".idx");
+ Indices[0] = IdxInst;
Instruction *NewLoad = new LoadInst(PoolBase, Indices, I->getName());
// Replace the load instruction with the new load instruction...
// Add the pool base calculator instruction before the load...
II = NewLoad->getParent()->getInstList().insert(II, PoolBase) + 1;
+ // Add the idx calculator instruction before the load...
+ II = NewLoad->getParent()->getInstList().insert(II, Index) + 1;
+
// Add the cast before the load instruction...
- NewLoad->getParent()->getInstList().insert(II, Index);
+ NewLoad->getParent()->getInstList().insert(II, IdxInst);
// If not yielding a pool allocated pointer, use the new load value as the
// value in the program instead of the old load value...
Value *Val = I->getOperand(0); // The value to store...
// Check to see if the value we are storing is a data structure pointer...
- if (const ScalarInfo *ValScalar = getScalar(I->getOperand(0)))
- Val = Constant::getNullConstant(POINTERTYPE); // Yes, store a dummy
+ //if (const ScalarInfo *ValScalar = getScalar(I->getOperand(0)))
+ if (isa<PointerType>(I->getOperand(0)->getType()))
+ Val = Constant::getNullValue(POINTERTYPE); // Yes, store a dummy
Instruction *PoolBase = createPoolBaseInstruction(I->getOperand(1));
// Cast our index to be a UIntTy so we can use it to index into the pool...
- CastInst *Index = new CastInst(Constant::getNullConstant(POINTERTYPE),
+ CastInst *Index = new CastInst(Constant::getNullValue(POINTERTYPE),
Type::UIntTy, I->getOperand(1)->getName());
ReferencesToUpdate.push_back(RefToUpdate(Index, 0, I->getOperand(1)));
vector<Value*> Indices(I->idx_begin(), I->idx_end());
- assert(Indices[0] == ConstantUInt::get(Type::UIntTy, 0) &&
- "Cannot handle array indexing yet!");
- Indices[0] = Index;
+ Instruction *IdxInst =
+ BinaryOperator::create(Instruction::Add, Indices[0], Index, "idx");
+ Indices[0] = IdxInst;
+
Instruction *NewStore = new StoreInst(Val, PoolBase, Indices);
if (Val != I->getOperand(0)) // Value stored was a pointer?
// Add the pool base calculator instruction before the index...
II = Index->getParent()->getInstList().insert(II, PoolBase) + 2;
+ // Add the indexing instruction...
+ II = Index->getParent()->getInstList().insert(II, IdxInst) + 1;
+
// Add the store after the cast instruction...
Index->getParent()->getInstList().insert(II, NewStore);
}
// Create call to poolalloc for every malloc instruction
void visitMallocInst(MallocInst *I) {
+ const ScalarInfo &SCI = getScalarRef(I);
vector<Value*> Args;
- Args.push_back(getScalarRef(I).Pool.Handle);
- CallInst *Call = new CallInst(PoolAllocator.PoolAlloc, Args, I->getName());
+
+ CallInst *Call;
+ if (!I->isArrayAllocation()) {
+ Args.push_back(SCI.Pool.Handle);
+ Call = new CallInst(PoolAllocator.PoolAlloc, Args, I->getName());
+ } else {
+ Args.push_back(I->getArraySize());
+ Args.push_back(SCI.Pool.Handle);
+ Call = new CallInst(PoolAllocator.PoolAllocArray, Args, I->getName());
+ }
+
ReplaceInstWith(I, Call);
}
void visitFreeInst(FreeInst *I) {
// Create a new call to poolfree before the free instruction
vector<Value*> Args;
- Args.push_back(Constant::getNullConstant(POINTERTYPE));
+ Args.push_back(Constant::getNullValue(POINTERTYPE));
Args.push_back(getScalarRef(I->getOperand(0)).Pool.Handle);
Instruction *NewCall = new CallInst(PoolAllocator.PoolFree, Args);
ReplaceInstWith(I, NewCall);
for (unsigned i = 0, e = TI.ArgInfo.size(); i != e; ++i) {
// Replace all of the pointer arguments with our new pointer typed values.
if (TI.ArgInfo[i].ArgNo != -1)
- Args[TI.ArgInfo[i].ArgNo] = Constant::getNullConstant(POINTERTYPE);
+ Args[TI.ArgInfo[i].ArgNo] = Constant::getNullValue(POINTERTYPE);
// Add all of the pool arguments...
Args.push_back(TI.ArgInfo[i].PoolHandle);
// nodes...
//
void visitPHINode(PHINode *PN) {
- Value *DummyVal = Constant::getNullConstant(POINTERTYPE);
+ Value *DummyVal = Constant::getNullValue(POINTERTYPE);
PHINode *NewPhi = new PHINode(POINTERTYPE, PN->getName());
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
NewPhi->addIncoming(DummyVal, PN->getIncomingBlock(i));
// visitReturnInst - Replace ret instruction with a new return...
void visitReturnInst(ReturnInst *I) {
- Instruction *Ret = new ReturnInst(Constant::getNullConstant(POINTERTYPE));
+ Instruction *Ret = new ReturnInst(Constant::getNullValue(POINTERTYPE));
ReplaceInstWith(I, Ret);
ReferencesToUpdate.push_back(RefToUpdate(Ret, 0, I->getOperand(0)));
}
// visitSetCondInst - Replace a conditional test instruction with a new one
void visitSetCondInst(SetCondInst *SCI) {
BinaryOperator *I = (BinaryOperator*)SCI;
- Value *DummyVal = Constant::getNullConstant(POINTERTYPE);
+ Value *DummyVal = Constant::getNullValue(POINTERTYPE);
BinaryOperator *New = BinaryOperator::create(I->getOpcode(), DummyVal,
DummyVal, I->getName());
ReplaceInstWith(I, New);
PoolDescValues.end()) {
assert("Make sure it's a load of the pool base, not a chaining field" &&
- LI->getOperand(1) == Constant::getNullConstant(Type::UIntTy) &&
- LI->getOperand(2) == Constant::getNullConstant(Type::UByteTy) &&
- LI->getOperand(3) == Constant::getNullConstant(Type::UByteTy));
+ LI->getOperand(1) == Constant::getNullValue(Type::UIntTy) &&
+ LI->getOperand(2) == Constant::getNullValue(Type::UByteTy) &&
+ LI->getOperand(3) == Constant::getNullValue(Type::UByteTy));
// If it is a load of a pool base, keep track of it for future reference
PoolDescMap.insert(make_pair(LoadAddr, LI));
vector<ScalarInfo> Scalars;
#ifdef DEBUG_TRANSFORM_PROGRESS
- cerr << "Building scalar map:\n";
+ cerr << "Building scalar map for fn '" << F->getName() << "' body:\n";
#endif
for (map<Value*, PointerValSet>::iterator I = ValMap.begin(),
// Check to see if the scalar points to a data structure node...
for (unsigned i = 0, e = PVS.size(); i != e; ++i) {
+ if (PVS[i].Index) { cerr << "Problem in " << F->getName() << " for " << I->first << "\n"; }
assert(PVS[i].Index == 0 && "Nonzero not handled yet!");
// If the allocation is in the nonescaping set...
// Add a symbol table entry for the new type if there was one for the old
// type...
string OldName = CurModule->getTypeName(Allocs[i]->getType());
- if (!OldName.empty())
- CurModule->addTypeName(OldName+".p", PI->second.NewType);
+ if (OldName.empty()) OldName = "node";
+ CurModule->addTypeName(OldName+".p", PI->second.NewType);
// Create the abstract pool types that will need to be resolved in a second
// pass once an abstract type is created for each pool.
//
// Can only handle limited shapes for now...
- StructType *OldNodeTy = cast<StructType>(Allocs[i]->getType());
+ const Type *OldNodeTy = Allocs[i]->getType();
vector<const Type*> PoolTypes;
// Pool type is the first element of the pool descriptor type...
StructType *PoolType = StructType::get(PoolTypes);
// Add a symbol table entry for the pooltype if possible...
- if (!OldName.empty()) CurModule->addTypeName(OldName+".pool", PoolType);
+ CurModule->addTypeName(OldName+".pool", PoolType);
// Create the pool type, with opaque values for pointers...
AbsPoolTyMap.insert(make_pair(Allocs[i], PoolType));
FunctionType *PoolFreeTy = FunctionType::get(Type::VoidTy, Args, true);
PoolFree = M->getOrInsertFunction("poolfree", PoolFreeTy);
- // Add the %PoolTy type to the symbol table of the module...
- //M->addTypeName("PoolTy", PoolTy->getElementType());
+ Args[0] = Type::UIntTy; // Number of slots to allocate
+ FunctionType *PoolAllocArrayTy = FunctionType::get(POINTERTYPE, Args, true);
+ PoolAllocArray = M->getOrInsertFunction("poolallocarray", PoolAllocArrayTy);
}