From d2d3a16641a411006078cc25b59382635d51f925 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 29 Mar 2002 03:40:59 +0000 Subject: [PATCH] Flesh out a bunch more code, print allocations that are poolable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2031 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/OldPoolAllocate.cpp | 159 +++++++++++++++++++++++-- 1 file changed, 149 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/IPO/OldPoolAllocate.cpp b/lib/Transforms/IPO/OldPoolAllocate.cpp index 53c9c94e37c..c116ed1c66b 100644 --- a/lib/Transforms/IPO/OldPoolAllocate.cpp +++ b/lib/Transforms/IPO/OldPoolAllocate.cpp @@ -9,25 +9,164 @@ #include "llvm/Transforms/IPO/PoolAllocate.h" #include "llvm/Analysis/DataStructure.h" #include "llvm/Pass.h" +#include "llvm/Module.h" +#include "llvm/Function.h" +#include "llvm/iMemory.h" +#include - +// Define the pass class that we implement... namespace { - struct PoolAllocate : public Pass { - bool run(Module *M) { - DataStructure &DS = getAnalysis(); - return false; + class PoolAllocate : public Pass { + // PoolTy - The type of a scalar value that contains a pool pointer. + PointerType *PoolTy; + public: + + PoolAllocate() { + // Initialize the PoolTy instance variable, since the type never changes. + vector PoolElements; + PoolElements.push_back(PointerType::get(Type::SByteTy)); + PoolElements.push_back(Type::UIntTy); + PoolTy = PointerType::get(StructType::get(PoolElements)); + // PoolTy = { sbyte*, uint }* + + CurModule = 0; DS = 0; + PoolInit = PoolDestroy = PoolAlloc = PoolFree = 0; } - // getAnalysisUsageInfo - This function works on the call graph of a module. - // It is capable of updating the call graph to reflect the new state of the - // module. + bool run(Module *M); + + // getAnalysisUsageInfo - This function requires data structure information + // to be able to see what is pool allocatable. // virtual void getAnalysisUsageInfo(Pass::AnalysisSet &Required, - Pass::AnalysisSet &Destroyed, - Pass::AnalysisSet &Provided) { + Pass::AnalysisSet &,Pass::AnalysisSet &) { Required.push_back(DataStructure::ID); } + + private: + // CurModule - The module being processed. + Module *CurModule; + + // DS - The data structure graph for the module being processed. + DataStructure *DS; + + // Prototypes that we add to support pool allocation... + Function *PoolInit, *PoolDestroy, *PoolAlloc, *PoolFree; + + // addPoolPrototypes - Add prototypes for the pool methods to the specified + // module and update the Pool* instance variables to point to them. + // + void addPoolPrototypes(Module *M); + + // processFunction - Convert a function to use pool allocation where + // available. + // + bool processFunction(Function *F); }; } + + +// isNotPoolableAlloc - This is a predicate that returns true if the specified +// allocation node in a data structure graph is eligable for pool allocation. +// +static bool isNotPoolableAlloc(const AllocDSNode *DS) { + if (DS->isAllocaNode()) return false; // Do not pool allocate alloca's. + + MallocInst *MI = cast(DS->getAllocation()); + if (MI->isArrayAllocation() && !isa(MI->getArraySize())) + return false; // Do not allow variable size allocations... + + return true; +} + + +// processFunction - Convert a function to use pool allocation where +// available. +// +bool PoolAllocate::processFunction(Function *F) { + // Get the closed datastructure graph for the current function... if there are + // any allocations in this graph that are not escaping, we need to pool + // allocate them here! + // + FunctionDSGraph &IPGraph = DS->getClosedDSGraph(F); + + // Get all of the allocations that do not escape the current function. Since + // they are still live (they exist in the graph at all), this means we must + // have scalar references to these nodes, but the scalars are never returned. + // + std::vector Allocs; + IPGraph.getNonEscapingAllocations(Allocs); + + // Filter out allocations that we cannot handle. Currently, this includes + // variable sized array allocations and alloca's (which we do not want to + // pool allocate) + // + Allocs.erase(remove_if(Allocs.begin(), Allocs.end(), isNotPoolableAlloc), + Allocs.end()); + + + if (Allocs.empty()) return false; // Nothing to do. + + // Loop through the value map looking for scalars that refer to nonescaping + // allocations. + // + map &ValMap = IPGraph.getValueMap(); + vector > Scalars; + + for (map::iterator I = ValMap.begin(), + E = ValMap.end(); I != E; ++I) { + const PointerValSet &PVS = I->second; // Set of things pointed to by scalar + // Check to see if the scalar points to anything that is an allocation... + for (unsigned i = 0, e = PVS.size(); i != e; ++i) + if (AllocDSNode *Alloc = dyn_cast(PVS[i].Node)) { + assert(PVS[i].Index == 0 && "Nonzero not handled yet!"); + + // If the allocation is in the nonescaping set... + if (find(Allocs.begin(), Allocs.end(), Alloc) != Allocs.end()) + // Add it to the list of scalars we have + Scalars.push_back(make_pair(I->first, Alloc)); + } + } + + cerr << "In '" << F->getName() + << "': Found the following values that point to poolable nodes:\n"; + + for (unsigned i = 0, e = Scalars.size(); i != e; ++i) + Scalars[i].first->dump(); + return false; +} + + +// Prototypes that we add to support pool allocation... +Function *PoolInit, *PoolDestroy, *PoolAlloc, *PoolFree; + +// addPoolPrototypes - Add prototypes for the pool methods to the specified +// module and update the Pool* instance variables to point to them. +// +void PoolAllocate::addPoolPrototypes(Module *M) { + //M->getOrCreate... + +} + + +bool PoolAllocate::run(Module *M) { + addPoolPrototypes(M); + CurModule = M; + + DS = &getAnalysis(); + bool Changed = false; + for (Module::iterator I = M->begin(); I != M->end(); ++I) + if (!(*I)->isExternal()) + Changed |= processFunction(*I); + + CurModule = 0; + DS = 0; + return false; +} + + +// createPoolAllocatePass - Global function to access the functionality of this +// pass... +// Pass *createPoolAllocatePass() { return new PoolAllocate(); }