[llvm-commits] [poolalloc] r74892 - in /poolalloc/trunk: include/poolalloc/PoolAllocate.h lib/PoolAllocate/PAMultipleGlobalPool.cpp
Haohui Mai
mai4 at uiuc.edu
Mon Jul 6 21:18:07 PDT 2009
Author: mai4
Date: Mon Jul 6 23:18:07 2009
New Revision: 74892
URL: http://llvm.org/viewvc/llvm-project?rev=74892&view=rev
Log:
Context-insensitive pool allocation.
Added:
poolalloc/trunk/lib/PoolAllocate/PAMultipleGlobalPool.cpp
Modified:
poolalloc/trunk/include/poolalloc/PoolAllocate.h
Modified: poolalloc/trunk/include/poolalloc/PoolAllocate.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/poolalloc/PoolAllocate.h?rev=74892&r1=74891&r2=74892&view=diff
==============================================================================
--- poolalloc/trunk/include/poolalloc/PoolAllocate.h (original)
+++ poolalloc/trunk/include/poolalloc/PoolAllocate.h Mon Jul 6 23:18:07 2009
@@ -25,7 +25,9 @@
#include "llvm/Support/CallSite.h"
#include "llvm/ADT/EquivalenceClasses.h"
#include "llvm/ADT/VectorExtras.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/CommandLine.h"
+
#include "dsa/DataStructure.h"
#include "poolalloc/ADT/HashExtras.h"
#include "poolalloc/Config/config.h"
@@ -461,6 +463,36 @@
}
};
-}
+/// PoolAllocateMultipleGlobalPool
+/// Context-insensitive pool allocation. It pool allocates objects into multiple
+/// global pools. It does not need to rewrite the functions declarations, which
+/// simplifies the implementation a lot. Technically, PoolAllocateSimple, which
+/// pool allocates everything into a single global pool, is a
+/// special case of PoolAllocateMultipleGlobalPool.
+///
+/// It requires some work on code clean up to make these two pass integrate
+/// nicely.
+class PoolAllocateMultipleGlobalPool : public PoolAllocate {
+ TargetData * TD;
+ void ProcessFunctionBodySimple(Function& F, TargetData & TD);
+ /// Mapping between DSNodes and Pool descriptors. For this pass, it is a
+ /// one-to-one relationship.
+ DenseMap<const DSNode *, GlobalVariable *> PoolMap;
+public:
+ static char ID;
+ PoolAllocateMultipleGlobalPool(bool passAllArgs=false, bool SAFECode = true)
+ : PoolAllocate (passAllArgs, SAFECode, (intptr_t)&ID) {}
+ ~PoolAllocateMultipleGlobalPool();
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+ virtual bool runOnModule(Module &M);
+ void CreateGlobalPool(unsigned RecSize, unsigned Align,
+ Module& M);
+
+ virtual Value * getGlobalPool (const DSNode * Node);
+ virtual Value * getPool (const DSNode * N, Function & F);
+
+};
+
+}
#endif
Added: poolalloc/trunk/lib/PoolAllocate/PAMultipleGlobalPool.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/PoolAllocate/PAMultipleGlobalPool.cpp?rev=74892&view=auto
==============================================================================
--- poolalloc/trunk/lib/PoolAllocate/PAMultipleGlobalPool.cpp (added)
+++ poolalloc/trunk/lib/PoolAllocate/PAMultipleGlobalPool.cpp Mon Jul 6 23:18:07 2009
@@ -0,0 +1,352 @@
+//===-- PAMultipleGlobalPool.cpp - Multiple Global Pool Allocation Pass ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A minimal poolallocator that assignes all allocation to multiple global
+// pools.
+//
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "poolalloc"
+
+#include "dsa/DataStructure.h"
+#include "dsa/DSGraph.h"
+#include "dsa/CallTargets.h"
+#include "poolalloc/PoolAllocate.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/Constants.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Timer.h"
+
+#include <iostream>
+
+using namespace llvm;
+using namespace PA;
+
+char llvm::PoolAllocateMultipleGlobalPool::ID = 0;
+
+namespace {
+ RegisterPass<PoolAllocateMultipleGlobalPool>
+ X("poolalloc-multi-global-pool", "Pool allocate objects into multiple global pools");
+
+ RegisterAnalysisGroup<PoolAllocateGroup> PAGroup1(X);
+}
+
+static inline Value *
+castTo (Value * V, const Type * Ty, std::string Name, Instruction * InsertPt) {
+ //
+ // Don't bother creating a cast if it's already the correct type.
+ //
+ if (V->getType() == Ty)
+ return V;
+
+ //
+ // If it's a constant, just create a constant expression.
+ //
+ if (Constant * C = dyn_cast<Constant>(V)) {
+ Constant * CE = ConstantExpr::getZExtOrBitCast (C, Ty);
+ return CE;
+ }
+
+ //
+ // Otherwise, insert a cast instruction.
+ //
+ return CastInst::CreateZExtOrBitCast (V, Ty, Name, InsertPt);
+}
+
+void PoolAllocateMultipleGlobalPool::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<TargetData>();
+ AU.addRequired<SteensgaardDataStructures>();
+ // It is a big lie.
+ AU.setPreservesAll();
+}
+
+bool PoolAllocateMultipleGlobalPool::runOnModule(Module &M) {
+ if (M.begin() == M.end()) return false;
+ Graphs = &getAnalysis<SteensgaardDataStructures>();
+ assert (Graphs && "No DSA pass available!\n");
+
+ TargetData & TD = getAnalysis<TargetData>();
+
+ // Add the pool* prototypes to the module
+ AddPoolPrototypes(&M);
+
+ //
+ // Create the global pool.
+ //
+ CreateGlobalPool(32, 1, M);
+
+ //
+ // Now that all call targets are available, rewrite the function bodies of the
+ // clones.
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ std::string name = I->getName();
+ if (name == "poolalloc.init") continue;
+ if (!(I->isDeclaration()))
+ ProcessFunctionBodySimple(*I, TD);
+ }
+
+ return true;
+}
+
+void
+PoolAllocateMultipleGlobalPool::ProcessFunctionBodySimple (Function& F, TargetData & TD) {
+ std::vector<Instruction*> toDelete;
+ std::vector<ReturnInst*> Returns;
+
+ //
+ // Create a silly Function Info structure for this function.
+ //
+ FuncInfo FInfo(F);
+ FunctionInfo.insert (std::make_pair(&F, FInfo));
+
+ //
+ // Get the DSGraph for this function.
+ //
+ DSGraph* ECG = Graphs->getDSGraph(F);
+
+ for (Function::iterator i = F.begin(), e = F.end(); i != e; ++i)
+ for (BasicBlock::iterator ii = i->begin(), ee = i->end(); ii != ee; ++ii) {
+ if (MallocInst * MI = dyn_cast<MallocInst>(ii)) {
+ // Associate the global pool decriptor with the DSNode
+ DSNode * Node = ECG->getNodeForValue(MI).getNode();
+ GlobalVariable * Pool = PoolMap[Node];
+ FInfo.PoolDescriptors.insert(std::make_pair(Node,Pool));
+
+ // Mark the malloc as an instruction to delete
+ toDelete.push_back(ii);
+
+ // Create instructions to calculate the size of the allocation in
+ // bytes
+ Value * AllocSize;
+ if (MI->isArrayAllocation()) {
+ Value * NumElements = MI->getArraySize();
+ Value * ElementSize = ConstantInt::get (Type::Int32Ty,
+ TD.getTypeAllocSize(MI->getAllocatedType()));
+ AllocSize = BinaryOperator::Create (Instruction::Mul,
+ ElementSize,
+ NumElements,
+ "sizetmp",
+ MI);
+ } else {
+ AllocSize = ConstantInt::get (Type::Int32Ty,
+ TD.getTypeAllocSize(MI->getAllocatedType()));
+ }
+
+ Value* args[] = {Pool, AllocSize};
+ Instruction* x = CallInst::Create(PoolAlloc, &args[0], &args[2], MI->getName(), ii);
+ ii->replaceAllUsesWith(CastInst::CreatePointerCast(x, ii->getType(), "", ii));
+ } else if (CallInst * CI = dyn_cast<CallInst>(ii)) {
+ CallSite CS(CI);
+ Function *CF = CS.getCalledFunction();
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(CS.getCalledValue()))
+ if (CE->getOpcode() == Instruction::BitCast &&
+ isa<Function>(CE->getOperand(0)))
+ CF = cast<Function>(CE->getOperand(0));
+ if (CF && (CF->isDeclaration()) && (CF->getName() == "realloc")) {
+ // Associate the global pool decriptor with the DSNode
+ DSNode * Node = ECG->getNodeForValue(CI).getNode();
+ GlobalVariable * Pool = PoolMap[Node];
+
+ FInfo.PoolDescriptors.insert(std::make_pair(Node,Pool));
+
+ // Mark the realloc as an instruction to delete
+ toDelete.push_back(ii);
+
+ // Insertion point - Instruction before which all our instructions go
+ Instruction *InsertPt = CI;
+ Value *OldPtr = CS.getArgument(0);
+ Value *Size = CS.getArgument(1);
+
+ // Ensure the size and pointer arguments are of the correct type
+ if (Size->getType() != Type::Int32Ty)
+ Size = CastInst::CreateIntegerCast (Size,
+ Type::Int32Ty,
+ false,
+ Size->getName(),
+ InsertPt);
+
+ static Type *VoidPtrTy = PointerType::getUnqual(Type::Int8Ty);
+ if (OldPtr->getType() != VoidPtrTy)
+ OldPtr = CastInst::CreatePointerCast (OldPtr,
+ VoidPtrTy,
+ OldPtr->getName(),
+ InsertPt);
+
+ std::string Name = CI->getName(); CI->setName("");
+ Value* Opts[3] = {Pool, OldPtr, Size};
+ Instruction *V = CallInst::Create (PoolRealloc,
+ Opts,
+ Opts + 3,
+ Name,
+ InsertPt);
+ Instruction *Casted = V;
+ if (V->getType() != CI->getType())
+ Casted = CastInst::CreatePointerCast (V, CI->getType(), V->getName(), InsertPt);
+
+ // Update def-use info
+ CI->replaceAllUsesWith(Casted);
+ } else if (CF && (CF->isDeclaration()) && (CF->getName() == "calloc")) {
+ // Associate the global pool decriptor with the DSNode
+ DSNode * Node = ECG->getNodeForValue(CI).getNode();
+ GlobalVariable * Pool = PoolMap[Node];
+ FInfo.PoolDescriptors.insert(std::make_pair(Node,Pool));
+
+ // Mark the realloc as an instruction to delete
+ toDelete.push_back(ii);
+
+ // Insertion point - Instruction before which all our instructions go
+ Instruction *InsertPt = CI;
+ Value *NumElements = CS.getArgument(0);
+ Value *Size = CS.getArgument(1);
+
+ // Ensure the size and pointer arguments are of the correct type
+ if (Size->getType() != Type::Int32Ty)
+ Size = CastInst::CreateIntegerCast (Size,
+ Type::Int32Ty,
+ false,
+ Size->getName(),
+ InsertPt);
+
+ if (NumElements->getType() != Type::Int32Ty)
+ NumElements = CastInst::CreateIntegerCast (Size,
+ Type::Int32Ty,
+ false,
+ NumElements->getName(),
+ InsertPt);
+
+ std::string Name = CI->getName(); CI->setName("");
+ Value* Opts[3] = {Pool, NumElements, Size};
+ Instruction *V = CallInst::Create (PoolCalloc,
+ Opts,
+ Opts + 3,
+ Name,
+ InsertPt);
+
+ Instruction *Casted = V;
+ if (V->getType() != CI->getType())
+ Casted = CastInst::CreatePointerCast (V, CI->getType(), V->getName(), InsertPt);
+
+ // Update def-use info
+ CI->replaceAllUsesWith(Casted);
+ } else if (CF && (CF->isDeclaration()) && (CF->getName() == "strdup")) {
+ // Associate the global pool decriptor with the DSNode
+ DSNode * Node = ECG->getNodeForValue(CI).getNode();
+ GlobalVariable * Pool = PoolMap[Node];
+ FInfo.PoolDescriptors.insert(std::make_pair(Node, Pool));
+
+ // Mark the realloc as an instruction to delete
+ toDelete.push_back(ii);
+
+ // Insertion point - Instruction before which all our instructions go
+ Instruction *InsertPt = CI;
+ Value *OldPtr = CS.getArgument(0);
+
+ // Ensure the size and pointer arguments are of the correct type
+ static Type *VoidPtrTy = PointerType::getUnqual(Type::Int8Ty);
+ if (OldPtr->getType() != VoidPtrTy)
+ OldPtr = CastInst::CreatePointerCast (OldPtr,
+ VoidPtrTy,
+ OldPtr->getName(),
+ InsertPt);
+
+ std::string Name = CI->getName(); CI->setName("");
+ Value* Opts[2] = {Pool, OldPtr};
+ Instruction *V = CallInst::Create (PoolStrdup,
+ Opts,
+ Opts + 2,
+ Name,
+ InsertPt);
+ Instruction *Casted = V;
+ if (V->getType() != CI->getType())
+ Casted = CastInst::CreatePointerCast (V, CI->getType(), V->getName(), InsertPt);
+
+ // Update def-use info
+ CI->replaceAllUsesWith(Casted);
+ }
+ } else if (FreeInst * FI = dyn_cast<FreeInst>(ii)) {
+ Type * VoidPtrTy = PointerType::getUnqual(Type::Int8Ty);
+ Value * FreedNode = castTo (FI->getPointerOperand(), VoidPtrTy, "cast", ii);
+ DSNode * Node = ECG->getNodeForValue(FreedNode).getNode();
+ GlobalVariable * Pool = PoolMap[Node];
+ toDelete.push_back(ii);
+ Value* args[] = {Pool, FreedNode};
+ CallInst::Create(PoolFree, &args[0], &args[2], "", ii);
+ } else if (isa<ReturnInst>(ii)) {
+ Returns.push_back(cast<ReturnInst>(ii));
+ }
+ }
+
+ //delete malloc and alloca insts
+ for (unsigned x = 0; x < toDelete.size(); ++x)
+ toDelete[x]->eraseFromParent();
+}
+
+/// CreateGlobalPool - Create a global pool descriptor object, and insert a
+/// poolinit for it into poolalloc.init
+void
+PoolAllocateMultipleGlobalPool::CreateGlobalPool (unsigned RecSize,
+ unsigned Align,
+ Module& M) {
+
+ Function *InitFunc = Function::Create
+ (FunctionType::get(Type::VoidTy, std::vector<const Type*>(), false),
+ GlobalValue::InternalLinkage, "poolalloc.init", &M);
+
+ BasicBlock * BB = BasicBlock::Create("entry", InitFunc);
+
+ SteensgaardDataStructures * DS = dynamic_cast<SteensgaardDataStructures*>(Graphs);
+
+ assert (DS && "PoolAllocateMultipleGlobalPools requires Steensgaard Data Structure!");
+
+ DSGraph * G = DS->getResultGraph();
+ for(DSGraph::node_const_iterator I = G->node_begin(),
+ E = G->node_end(); I != E; ++I) {
+
+ GlobalVariable *GV =
+ new GlobalVariable(getPoolType(), false, GlobalValue::ExternalLinkage,
+ Constant::getNullValue(getPoolType()),
+ "__poolalloc_GlobalPool",
+ &M);
+
+ Value *ElSize = ConstantInt::get(Type::Int32Ty, RecSize);
+ Value *AlignV = ConstantInt::get(Type::Int32Ty, Align);
+ Value* Opts[3] = {GV, ElSize, AlignV};
+
+ CallInst::Create(PoolInit, Opts, Opts + 3, "", BB);
+ PoolMap[&(*I)] = GV;
+ }
+
+ ReturnInst::Create(BB);
+}
+
+Value *
+PoolAllocateMultipleGlobalPool::getGlobalPool (const DSNode * Node) {
+ Value * Pool = PoolMap[Node];
+ assert (Pool && "Every DSNode corresponds to a pool handle!");
+ return Pool;
+}
+
+Value *
+PoolAllocateMultipleGlobalPool::getPool (const DSNode * N, Function & F) {
+ return getGlobalPool(N);
+}
+
+PoolAllocateMultipleGlobalPool::~PoolAllocateMultipleGlobalPool() {}
More information about the llvm-commits
mailing list