Made changes suggested by Chris

llvm-svn: 6606
This commit is contained in:
Sumant Kowshik 2003-06-04 08:03:57 +00:00
parent 061d15551f
commit c318ca1a51
2 changed files with 57 additions and 53 deletions

View File

@ -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);

View File

@ -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);