forked from OSchip/llvm-project
parent
061d15551f
commit
c318ca1a51
|
@ -90,14 +90,14 @@ class PoolAllocate : public Pass {
|
||||||
EquivalenceClasses<Function *> FuncECs;
|
EquivalenceClasses<Function *> FuncECs;
|
||||||
|
|
||||||
// Map from an Indirect CallInst to the set of Functions that it can point to
|
// Map from an Indirect CallInst to the set of Functions that it can point to
|
||||||
map<CallInst *, vector<Function *> > CallInstTargets;
|
std::multimap<CallInst *, Function *> CallInstTargets;
|
||||||
|
|
||||||
// This maps an equivalence class to the last pool argument number for that
|
// This maps an equivalence class to the last pool argument number for that
|
||||||
// class. This is used because the pool arguments for all functions within
|
// class. This is used because the pool arguments for all functions within
|
||||||
// an equivalence class is passed to all the functions in that class.
|
// an equivalence class is passed to all the functions in that class.
|
||||||
// If an equivalence class does not require pool arguments, it is not
|
// If an equivalence class does not require pool arguments, it is not
|
||||||
// on this map.
|
// on this map.
|
||||||
map<Function *, int> EqClass2LastPoolArg;
|
std::map<Function *, int> EqClass2LastPoolArg;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool run(Module &M);
|
bool run(Module &M);
|
||||||
|
|
|
@ -17,14 +17,23 @@
|
||||||
#include "llvm/Support/InstVisitor.h"
|
#include "llvm/Support/InstVisitor.h"
|
||||||
#include "Support/Statistic.h"
|
#include "Support/Statistic.h"
|
||||||
#include "Support/VectorExtras.h"
|
#include "Support/VectorExtras.h"
|
||||||
|
using std::vector;
|
||||||
|
using std::map;
|
||||||
|
using std::multimap;
|
||||||
using namespace PA;
|
using namespace PA;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const Type *VoidPtrTy = PointerType::get(Type::SByteTy);
|
const Type *VoidPtrTy = PointerType::get(Type::SByteTy);
|
||||||
// The type to allocate for a pool descriptor: { sbyte*, uint }
|
|
||||||
|
// The type to allocate for a pool descriptor: { sbyte*, uint, uint }
|
||||||
|
// void *Data (the data)
|
||||||
|
// unsigned NodeSize (size of an allocated node)
|
||||||
|
// unsigned FreeablePool (are slabs in the pool freeable upon calls to
|
||||||
|
// poolfree?)
|
||||||
const Type *PoolDescType =
|
const Type *PoolDescType =
|
||||||
StructType::get(make_vector<const Type*>(VoidPtrTy, Type::UIntTy, 0));
|
StructType::get(make_vector<const Type*>(VoidPtrTy, Type::UIntTy,
|
||||||
|
Type::UIntTy, 0));
|
||||||
|
|
||||||
const PointerType *PoolDescPtr = PointerType::get(PoolDescType);
|
const PointerType *PoolDescPtr = PointerType::get(PoolDescType);
|
||||||
|
|
||||||
RegisterOpt<PoolAllocate>
|
RegisterOpt<PoolAllocate>
|
||||||
|
@ -40,7 +49,7 @@ void PoolAllocate::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
// Prints out the functions mapped to the leader of the equivalence class they
|
// Prints out the functions mapped to the leader of the equivalence class they
|
||||||
// belong to.
|
// belong to.
|
||||||
void PoolAllocate::printFuncECs() {
|
void PoolAllocate::printFuncECs() {
|
||||||
map<Function*, Function*> leaderMap = FuncECs.getLeaderMap();
|
map<Function*, Function*> &leaderMap = FuncECs.getLeaderMap();
|
||||||
std::cerr << "Indirect Function Map \n";
|
std::cerr << "Indirect Function Map \n";
|
||||||
for (map<Function*, Function*>::iterator LI = leaderMap.begin(),
|
for (map<Function*, Function*>::iterator LI = leaderMap.begin(),
|
||||||
LE = leaderMap.end(); LI != LE; ++LI) {
|
LE = leaderMap.end(); LI != LE; ++LI) {
|
||||||
|
@ -73,23 +82,28 @@ void PoolAllocate::buildIndirectFunctionSets(Module &M) {
|
||||||
CSE = callSites.end(); CSI != CSE ; ++CSI) {
|
CSE = callSites.end(); CSI != CSE ; ++CSI) {
|
||||||
if (CSI->isIndirectCall()) {
|
if (CSI->isIndirectCall()) {
|
||||||
DSNode *DSN = CSI->getCalleeNode();
|
DSNode *DSN = CSI->getCalleeNode();
|
||||||
|
if (DSN->NodeType == DSNode::Incomplete)
|
||||||
|
std::cerr << "Incomplete node " << CSI->getCallInst();
|
||||||
// assert(DSN->NodeType == DSNode::GlobalNode);
|
// assert(DSN->NodeType == DSNode::GlobalNode);
|
||||||
std::vector<GlobalValue*> Callees = DSN->getGlobals();
|
std::vector<GlobalValue*> &Callees = DSN->getGlobals();
|
||||||
if (Callees.size() > 0) {
|
if (Callees.size() > 0) {
|
||||||
Function *firstCalledF = dyn_cast<Function>(*Callees.begin());
|
Function *firstCalledF = dyn_cast<Function>(*Callees.begin());
|
||||||
FuncECs.addElement(firstCalledF);
|
FuncECs.addElement(firstCalledF);
|
||||||
CallInstTargets[&CSI->getCallInst()].push_back(firstCalledF);
|
CallInstTargets.insert(std::pair<CallInst*,Function*>
|
||||||
|
(&CSI->getCallInst(),
|
||||||
|
firstCalledF));
|
||||||
if (Callees.size() > 1) {
|
if (Callees.size() > 1) {
|
||||||
for (std::vector<GlobalValue*>::iterator CalleesI =
|
for (std::vector<GlobalValue*>::iterator CalleesI =
|
||||||
++Callees.begin(), CalleesE = Callees.end();
|
++Callees.begin(), CalleesE = Callees.end();
|
||||||
CalleesI != CalleesE; ++CalleesI) {
|
CalleesI != CalleesE; ++CalleesI) {
|
||||||
Function *calledF = dyn_cast<Function>(*CalleesI);
|
Function *calledF = dyn_cast<Function>(*CalleesI);
|
||||||
FuncECs.unionElements(firstCalledF, calledF);
|
FuncECs.unionSetsWith(firstCalledF, calledF);
|
||||||
CallInstTargets[&CSI->getCallInst()].push_back(calledF);
|
CallInstTargets.insert(std::pair<CallInst*,Function*>
|
||||||
|
(&CSI->getCallInst(), calledF));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Callee has no targets\n";
|
std::cerr << "No targets " << CSI->getCallInst();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +111,6 @@ void PoolAllocate::buildIndirectFunctionSets(Module &M) {
|
||||||
|
|
||||||
// Print the equivalence classes
|
// Print the equivalence classes
|
||||||
DEBUG(printFuncECs());
|
DEBUG(printFuncECs());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PoolAllocate::run(Module &M) {
|
bool PoolAllocate::run(Module &M) {
|
||||||
|
@ -523,7 +536,7 @@ namespace {
|
||||||
|
|
||||||
Function* getFuncClass(Value *V);
|
Function* getFuncClass(Value *V);
|
||||||
|
|
||||||
Value* retCloneIfNotFP(Value *V);
|
Value* retCloneIfFunc(Value *V);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,13 +547,8 @@ void PoolAllocate::TransformFunctionBody(Function &F, DSGraph &G, FuncInfo &FI){
|
||||||
|
|
||||||
// Returns true if V is a function pointer
|
// Returns true if V is a function pointer
|
||||||
bool FuncTransform::isFuncPtr(Value *V) {
|
bool FuncTransform::isFuncPtr(Value *V) {
|
||||||
if (V->getType()->getPrimitiveID() == Type::PointerTyID) {
|
if (const PointerType *PTy = dyn_cast<PointerType>(V->getType()))
|
||||||
const PointerType *PTy = dyn_cast<PointerType>(V->getType());
|
return isa<FunctionType>(PTy->getElementType());
|
||||||
|
|
||||||
if (PTy->getElementType()->getPrimitiveID() == Type::FunctionTyID)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,7 +577,7 @@ Function* FuncTransform::getFuncClass(Value *V) {
|
||||||
if (!DSN) {
|
if (!DSN) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
std::vector<GlobalValue*> Callees = DSN->getGlobals();
|
std::vector<GlobalValue*> &Callees = DSN->getGlobals();
|
||||||
if (Callees.size() > 0) {
|
if (Callees.size() > 0) {
|
||||||
Function *calledF = dyn_cast<Function>(*Callees.begin());
|
Function *calledF = dyn_cast<Function>(*Callees.begin());
|
||||||
assert(PAInfo.FuncECs.findClass(calledF) && "should exist in some eq. class");
|
assert(PAInfo.FuncECs.findClass(calledF) && "should exist in some eq. class");
|
||||||
|
@ -580,40 +588,36 @@ Function* FuncTransform::getFuncClass(Value *V) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the clone if V is not a function pointer
|
// Returns the clone if V is a static function (not a pointer) and belongs
|
||||||
Value* FuncTransform::retCloneIfNotFP(Value *V) {
|
// to an equivalence class i.e. is pool allocated
|
||||||
if (isFuncPtr(V))
|
Value* FuncTransform::retCloneIfFunc(Value *V) {
|
||||||
if (isa<Function>(V))
|
if (Function *fixedFunc = dyn_cast<Function>(V))
|
||||||
if (getFuncClass(V)) {
|
if (getFuncClass(V))
|
||||||
Function *fixedFunc = dyn_cast<Function>(V);
|
|
||||||
return PAInfo.getFuncInfo(*fixedFunc)->Clone;
|
return PAInfo.getFuncInfo(*fixedFunc)->Clone;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuncTransform::visitReturnInst (ReturnInst &I) {
|
void FuncTransform::visitReturnInst (ReturnInst &I) {
|
||||||
if (I.getNumOperands())
|
if (I.getNumOperands())
|
||||||
if (Value *clonedFunc = retCloneIfNotFP(I.getOperand(0))) {
|
if (Value *clonedFunc = retCloneIfFunc(I.getOperand(0))) {
|
||||||
// Cast the clone of I.getOperand(0) to the non-pool-allocated type
|
// Cast the clone of I.getOperand(0) to the non-pool-allocated type
|
||||||
CastInst *CastI = new CastInst(clonedFunc, I.getOperand(0)->getType(),
|
CastInst *CastI = new CastInst(clonedFunc, I.getOperand(0)->getType(),
|
||||||
"", &I);
|
"tmp", &I);
|
||||||
// Insert return instruction that returns the casted value
|
// Insert return instruction that returns the casted value
|
||||||
new ReturnInst(CastI, &I);
|
new ReturnInst(CastI, &I);
|
||||||
|
|
||||||
// Remove original return instruction
|
// Remove original return instruction
|
||||||
I.setName("");
|
|
||||||
I.getParent()->getInstList().erase(&I);
|
I.getParent()->getInstList().erase(&I);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuncTransform::visitStoreInst (StoreInst &I) {
|
void FuncTransform::visitStoreInst (StoreInst &I) {
|
||||||
// Check if a constant function is being stored
|
// Check if a constant function is being stored
|
||||||
if (Value *clonedFunc = retCloneIfNotFP(I.getOperand(0))) {
|
if (Value *clonedFunc = retCloneIfFunc(I.getOperand(0))) {
|
||||||
CastInst *CastI = new CastInst(clonedFunc, I.getOperand(0)->getType(), "",
|
CastInst *CastI = new CastInst(clonedFunc, I.getOperand(0)->getType(),
|
||||||
&I);
|
"tmp", &I);
|
||||||
new StoreInst(CastI, I.getOperand(1), &I);
|
new StoreInst(CastI, I.getOperand(1), &I);
|
||||||
I.setName("");
|
|
||||||
I.getParent()->getInstList().erase(&I);
|
I.getParent()->getInstList().erase(&I);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,11 +630,11 @@ void FuncTransform::visitPHINode(PHINode &I) {
|
||||||
if (isFuncPtr(&I)) {
|
if (isFuncPtr(&I)) {
|
||||||
PHINode *V = new PHINode(I.getType(), I.getName(), &I);
|
PHINode *V = new PHINode(I.getType(), I.getName(), &I);
|
||||||
for (unsigned i = 0 ; i < I.getNumIncomingValues(); ++i) {
|
for (unsigned i = 0 ; i < I.getNumIncomingValues(); ++i) {
|
||||||
if (Value *clonedFunc = retCloneIfNotFP(I.getIncomingValue(i))) {
|
if (Value *clonedFunc = retCloneIfFunc(I.getIncomingValue(i))) {
|
||||||
// Insert CastInst at the end of I.getIncomingBlock(i)
|
// Insert CastInst at the end of I.getIncomingBlock(i)
|
||||||
BasicBlock::iterator BBI = --I.getIncomingBlock(i)->end();
|
BasicBlock::iterator BBI = --I.getIncomingBlock(i)->end();
|
||||||
// BBI now points to the terminator instruction of the basic block.
|
// BBI now points to the terminator instruction of the basic block.
|
||||||
CastInst *CastI = new CastInst(clonedFunc, I.getType(), "", BBI);
|
CastInst *CastI = new CastInst(clonedFunc, I.getType(), "tmp", BBI);
|
||||||
V->addIncoming(CastI, I.getIncomingBlock(i));
|
V->addIncoming(CastI, I.getIncomingBlock(i));
|
||||||
} else {
|
} else {
|
||||||
V->addIncoming(I.getIncomingValue(i), I.getIncomingBlock(i));
|
V->addIncoming(I.getIncomingValue(i), I.getIncomingBlock(i));
|
||||||
|
@ -638,7 +642,6 @@ void FuncTransform::visitPHINode(PHINode &I) {
|
||||||
|
|
||||||
}
|
}
|
||||||
I.replaceAllUsesWith(V);
|
I.replaceAllUsesWith(V);
|
||||||
I.setName("");
|
|
||||||
I.getParent()->getInstList().erase(&I);
|
I.getParent()->getInstList().erase(&I);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -739,8 +742,7 @@ void FuncTransform::visitCallInst(CallInst &CI) {
|
||||||
if (isa<Function>(CastI->getOperand(0)) &&
|
if (isa<Function>(CastI->getOperand(0)) &&
|
||||||
CastI->getOperand(0)->getType() == CastI->getType())
|
CastI->getOperand(0)->getType() == CastI->getType())
|
||||||
CF = dyn_cast<Function>(CastI->getOperand(0));
|
CF = dyn_cast<Function>(CastI->getOperand(0));
|
||||||
} else if (isa<ConstantExpr>(CI.getOperand(0))) {
|
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(CI.getOperand(0))) {
|
||||||
ConstantExpr *CE = dyn_cast<ConstantExpr>(CI.getOperand(0));
|
|
||||||
if (CE->getOpcode() == Instruction::Cast) {
|
if (CE->getOpcode() == Instruction::Cast) {
|
||||||
if (isa<ConstantPointerRef>(CE->getOperand(0)))
|
if (isa<ConstantPointerRef>(CE->getOperand(0)))
|
||||||
return;
|
return;
|
||||||
|
@ -760,24 +762,25 @@ void FuncTransform::visitCallInst(CallInst &CI) {
|
||||||
std::map<unsigned, Value*> PoolArgs;
|
std::map<unsigned, Value*> PoolArgs;
|
||||||
Function *FuncClass;
|
Function *FuncClass;
|
||||||
|
|
||||||
for (vector<Function *>::iterator TFI = PAInfo.CallInstTargets[&CI].begin(),
|
std::pair<multimap<CallInst*, Function*>::iterator, multimap<CallInst*, Function*>::iterator> Targets = PAInfo.CallInstTargets.equal_range(&CI);
|
||||||
TFE = PAInfo.CallInstTargets[&CI].end(); TFI != TFE; ++TFI) {
|
for (multimap<CallInst*, Function*>::iterator TFI = Targets.first,
|
||||||
if (TFI == PAInfo.CallInstTargets[&CI].begin()) {
|
TFE = Targets.second; TFI != TFE; ++TFI) {
|
||||||
FuncClass = PAInfo.FuncECs.findClass(*TFI);
|
if (TFI == Targets.first) {
|
||||||
|
FuncClass = PAInfo.FuncECs.findClass(TFI->second);
|
||||||
// Nothing to transform if there are no pool arguments in this
|
// Nothing to transform if there are no pool arguments in this
|
||||||
// equivalence class of functions.
|
// equivalence class of functions.
|
||||||
if (!PAInfo.EqClass2LastPoolArg.count(FuncClass))
|
if (!PAInfo.EqClass2LastPoolArg.count(FuncClass))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuncInfo *CFI = PAInfo.getFuncInfo(**TFI);
|
FuncInfo *CFI = PAInfo.getFuncInfo(*TFI->second);
|
||||||
|
|
||||||
if (!CFI->ArgNodes.size()) continue; // Nothing to transform...
|
if (!CFI->ArgNodes.size()) continue; // Nothing to transform...
|
||||||
|
|
||||||
DSGraph &CG = PAInfo.getBUDataStructures().getDSGraph(**TFI);
|
DSGraph &CG = PAInfo.getBUDataStructures().getDSGraph(*TFI->second);
|
||||||
std::map<DSNode*, DSNode*> NodeMapping;
|
std::map<DSNode*, DSNode*> NodeMapping;
|
||||||
|
|
||||||
Function::aiterator AI = (*TFI)->abegin(), AE = (*TFI)->aend();
|
Function::aiterator AI = TFI->second->abegin(), AE = TFI->second->aend();
|
||||||
unsigned OpNum = 1;
|
unsigned OpNum = 1;
|
||||||
for ( ; AI != AE; ++AI, ++OpNum) {
|
for ( ; AI != AE; ++AI, ++OpNum) {
|
||||||
if (!isa<Constant>(CI.getOperand(OpNum)))
|
if (!isa<Constant>(CI.getOperand(OpNum)))
|
||||||
|
@ -832,15 +835,16 @@ void FuncTransform::visitCallInst(CallInst &CI) {
|
||||||
|
|
||||||
Value *NewCall;
|
Value *NewCall;
|
||||||
if (Args.size() > CI.getNumOperands() - 1) {
|
if (Args.size() > CI.getNumOperands() - 1) {
|
||||||
|
// If there are any pool arguments
|
||||||
CastInst *CastI =
|
CastInst *CastI =
|
||||||
new CastInst(CI.getOperand(0),
|
new CastInst(CI.getOperand(0),
|
||||||
PAInfo.getFuncInfo(*FuncClass)->Clone->getType(), "", &CI);
|
PAInfo.getFuncInfo(*FuncClass)->Clone->getType(), "tmp",
|
||||||
|
&CI);
|
||||||
NewCall = new CallInst(CastI, Args, Name, &CI);
|
NewCall = new CallInst(CastI, Args, Name, &CI);
|
||||||
} else {
|
} else {
|
||||||
NewCall = new CallInst(CI.getOperand(0), Args, Name, &CI);
|
NewCall = new CallInst(CI.getOperand(0), Args, Name, &CI);
|
||||||
}
|
}
|
||||||
|
|
||||||
CI.setName("");
|
|
||||||
CI.replaceAllUsesWith(NewCall);
|
CI.replaceAllUsesWith(NewCall);
|
||||||
DEBUG(std::cerr << " Result Call: " << *NewCall);
|
DEBUG(std::cerr << " Result Call: " << *NewCall);
|
||||||
}
|
}
|
||||||
|
@ -914,7 +918,7 @@ void FuncTransform::visitCallInst(CallInst &CI) {
|
||||||
// Add the rest of the arguments...
|
// Add the rest of the arguments...
|
||||||
Args.insert(Args.end(), CI.op_begin()+1, CI.op_end());
|
Args.insert(Args.end(), CI.op_begin()+1, CI.op_end());
|
||||||
|
|
||||||
std::string Name = CI.getName(); CI.setName("");
|
std::string Name = CI.getName();
|
||||||
Value *NewCall = new CallInst(CFI->Clone, Args, Name, &CI);
|
Value *NewCall = new CallInst(CFI->Clone, Args, Name, &CI);
|
||||||
CI.replaceAllUsesWith(NewCall);
|
CI.replaceAllUsesWith(NewCall);
|
||||||
DEBUG(std::cerr << " Result Call: " << *NewCall);
|
DEBUG(std::cerr << " Result Call: " << *NewCall);
|
||||||
|
|
Loading…
Reference in New Issue