//===-- PoolAllocate.cpp - Pool Allocation Pass ---------------------------===//
//
// This transform changes programs so that disjoint data structures are
// allocated out of different pools of memory, increasing locality.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/PoolAllocate.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Analysis/DataStructure.h"
#include "llvm/Analysis/DSGraph.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/InstVisitor.h"
#include "Support/Statistic.h"
#include "Support/VectorExtras.h"
using namespace PA;
namespace {
const Type *VoidPtrTy = PointerType::get(Type::SByteTy);
// 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 =
StructType::get(make_vector<const Type*>(VoidPtrTy, Type::UIntTy,
Type::UIntTy, 0));
const PointerType *PoolDescPtr = PointerType::get(PoolDescType);
RegisterOpt<PoolAllocate>
X("poolalloc", "Pool allocate disjoint data structures");
}
void PoolAllocate::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<BUDataStructures>();
AU.addRequired<TDDataStructures>();
AU.addRequired<TargetData>();
}
// Prints out the functions mapped to the leader of the equivalence class they
// belong to.
void PoolAllocate::printFuncECs() {
std::map<Function*, Function*> &leaderMap = FuncECs.getLeaderMap();
std::cerr << "Indirect Function Map \n";
for (std::map<Function*, Function*>::iterator LI = leaderMap.begin(),
LE = leaderMap.end(); LI != LE; ++LI) {
std::cerr << LI->first->getName() << ": leader is "
<< LI->second->getName() << "\n";
}
}
void PoolAllocate::buildIndirectFunctionSets(Module &M) {
// Iterate over the module looking for indirect calls to functions
// Get top down DSGraph for the functions
TDDS = &getAnalysis<TDDataStructures>();
for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
DEBUG(std::cerr << "Processing indirect calls function:" << MI->getName() << "\n");
if (MI->isExternal())
continue;
DSGraph &TDG = TDDS->getDSGraph(*MI);
std::vector<DSCallSite> callSites = TDG.getFunctionCalls();
// For each call site in the function
// All the functions that can be called at the call site are put in the
// same equivalence class.
for (std::vector<DSCallSite>::iterator CSI = callSites.begin(),
CSE = callSites.end(); CSI != CSE ; ++CSI) {
if (CSI->isIndirectCall()) {
DSNode *DSN = CSI->getCalleeNode();
if (DSN->isIncomplete())
std::cerr << "Incomplete node " << CSI->getCallInst();
// assert(DSN->isGlobalNode());
const std::vector<GlobalValue*> &Callees = DSN->getGlobals();
if (Callees.size() > 0) {
Function *firstCalledF = dyn_cast<Function>(*Callees.begin());
FuncECs.addElement(firstCalledF);
CallInstTargets.insert(std::pair<CallInst*,Function*>
(&CSI->getCallInst(),
firstCalledF));
if (Callees.size() > 1) {
for (std::vector<GlobalValue*>::const_iterator CalleesI =
Callees.begin()+1, CalleesE = Callees.end();
CalleesI != CalleesE; ++CalleesI) {
Function *calledF = dyn_cast<Function>(*CalleesI);
FuncECs.unionSetsWith(firstCalledF, calledF);
CallInstTargets.insert(std::pair<CallInst*,Function*>
(&CSI->getCallInst(), calledF));
}
}
} else {
std::cerr << "No targets " << CSI->getCallInst();
}
}
}
}
// Print the equivalence classes
DEBUG(printFuncECs());
}
bool PoolAllocate::run(Module &M) {
if (M.begin() == M.end()) return false;
CurModule = &M;
AddPoolPrototypes();
BU = &getAnalysis<BUDataStructures>();
buildIndirectFunctionSets(M);
std::map<Func