//===-- 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 }
const Type *PoolDescType =
StructType::get(make_vector<const Type*>(VoidPtrTy, 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() {
map<Function*, Function*> leaderMap = FuncECs.getLeaderMap();
std::cerr << "Indirect Function Map \n";
for (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 (vector<DSCallSite>::iterator CSI = callSites.begin(),
CSE = callSites.end(); CSI != CSE ; ++CSI) {
if (CSI->isIndirectCall()) {
DSNode *DSN = CSI->getCalleeNode();
// assert(DSN->NodeType == DSNode::GlobalNode);
std::vector<GlobalValue*> Callees = DSN->getGlobals();
if (Callees.size() > 0) {
Function *firstCalledF = dyn_cast<Function>(*Callees.begin());
FuncECs.addElement(firstCalledF);
CallInstTargets[&CSI->getCallInst()].push_back(firstCalledF);
if (Callees.size() > 1) {
for (std::vector<GlobalValue*>::iterator CalleesI =
++Callees.begin(), CalleesE = Callees.end();
CalleesI != CalleesE; ++CalleesI) {
Function *calledF = dyn_cast<Function>(*CalleesI);
FuncECs.unionElements(firstCalledF, calledF);
CallInstTargets[&CSI->getCallInst()].push_back(calledF);
}
}
} else {
std::cerr << "Callee has no targets\n";
}
}
}
}
// 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<Function*, Function*> FuncMap;
// Loop over the functions in the original program finding the pool desc.
// arguments necessary for each function that is indirectly callable.
// For each equivalence class, make a list of pool arguments and update
// the PoolArgFirst and PoolArgLast values for each function.
Module::iterator LastOrigFunction = --M.end();
for (Module::iterator I = M.begin(); ; ++I) {
if (!I->isExternal())
FindFunctionPoolArgs(*I);
if (I == LastOrigFunction) break;
}
// Now clone a function using the pool arg list obtained in the previous
// pass over the modules.
// Loop over only the function initially in the program, don't traverse newly
// added ones. If the function uses memory, make its clone.
for (Module::iterator I = M.begin(); ; ++I) {
if