//===-- PoolAllocate.cpp - 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.
// 
//===----------------------------------------------------------------------===//
//
// This transform changes programs so that disjoint data structures are
// allocated out of different pools of memory, increasing locality.
//
//===----------------------------------------------------------------------===//

#include <iostream>

#define DEBUG_TYPE "poolalloc"

#include "dsa/DataStructure.h"
#include "dsa/DSGraph.h"
#include "poolalloc/Heuristic.h"
#include "poolalloc/PoolAllocate.h"
#include "poolalloc/RuntimeChecks.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/CFG.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/FormattedStream.h"
#include "llvm/Support/Timer.h"

using namespace llvm;
using namespace PA;

char PoolAllocate::ID = 0;
char PoolAllocatePassAllPools::ID = 0;
char PoolAllocateGroup::ID = 0;

Type *PoolAllocate::PoolDescPtrTy = 0;

cl::opt<bool> PA::PA_SAFECODE("pa-safecode", cl::ReallyHidden);

namespace {
  RegisterPass<PoolAllocate>
  X("poolalloc", "Pool allocate disjoint data structures");

  RegisterPass<PoolAllocatePassAllPools>
  Y("poolalloc-passing-all-pools", "Pool allocate disjoint data structures");

  RegisterAnalysisGroup<PoolAllocateGroup> PAGroup ("Pool Allocation Group");
  RegisterAnalysisGroup<PoolAllocateGroup> PAGroup1(X);

  STATISTIC (NumArgsAdded, "Number of function arguments added");
  STATISTIC (MaxArgsAdded, "Maximum function arguments added to one function");
  STATISTIC (NumCloned   , "Number of functions cloned");
  STATISTIC (NumPools    , "Number of pools allocated");
  STATISTIC (NumTSPools  , "Number of typesafe pools");
  STATISTIC (NumPoolFree , "Number of poolfree's elided");
  STATISTIC (NumNonprofit, "Number of DSNodes not profitable");
  //  STATISTIC (NumColocated, "Number of DSNodes colocated");

  Type *VoidPtrTy;

  // The type to allocate for a pool descriptor.
  Type *PoolDescType;

  cl::opt<bool>
  DisableInitDestroyOpt("poolalloc-force-simple-pool-init",
                        cl::desc("Always insert poolinit/pooldestroy calls at start and exit of functions"));//, cl::init(true));
  cl::opt<bool>
  DisablePoolFreeOpt("poolalloc-force-all-poolfrees",
                     cl::desc("Do not try to elide poolfree's where possible"));

}

static void
createPoolAllocInit (Module & M) {
  //
  // Create the __poolalloc_init() function.
  //
  Type * VoidType = Type::getVoidTy(M.getContext());
  FunctionType * FTy = FunctionType::get(VoidType,
                                         std::vector<Type*>(),
                                         false);
  Function *InitFunc = Function::Create (FTy,
                                         GlobalValue::ExternalLinkage,
                                         "__poolalloc_init",
                                         &M);

  //
  // Add an entry basic block that just returns.
  //
  BasicBlock * BB = BasicBlock::Create (M.getContext(), "entry", InitFunc);
  ReturnInst::Create(M.getContext(), BB);

  return;
}

//
// Function: createGlobalPoolCtor()
//
// Description:
//  This function creates an empty function which will be a global constructor
//  (i.e., global ctor).  Pool Allocation will eventually add code to it to
//  initialize all of the global pools.
//
Function * PoolAllocate::createGlobalPoolCtor (Module & M) {
  //
  // Create the global pool ctor function.
  //
  LLVMContext & Context = M.getContext();
  Type * VoidType = Type::getVoidTy (Context);
  FunctionType * FTy = FunctionType::get(VoidType,
                                         std::vector<Type*>(),
                                         false);
  Function *InitFunc = Function::Create (FTy,
                                         GlobalValue::ExternalLinkage,
                                         "poolalloc_global_ctor",
                                         &M);

  //
  // Add an entry basic block that just returns.
  //
  BasicBlock * BB = BasicBlock::Create (Context, "entry", InitFunc);
  ReturnInst::Create(Context, BB);

  //
  // Insert the run-time ctor into the ctor list.
  //
  Type * Int32Type = IntegerType::getInt32Ty(Context);
  std::vector<Constant *> CtorInits;

  //
  // We need to ensure that this constructor gets called before any other code
  // in the module executes, so give the constructor a priority of 0 (highest).
  //
  CtorInits.push_back (ConstantInt::get (Int32Type, 0));
  CtorInits.push_back (InitFunc);
  Constant * RuntimeCtorInit = ConstantStruct::getAnon(Context, CtorInits);

  //
  // Get the current set of static global constructors and add the new ctor
  // to the list.
  //
  std::vector<Constant *> CurrentCtors;
  GlobalVariable * GVCtor = M.getNamedGlobal ("llvm.global_ctors");
  if (GVCtor) {
    if (Constant * C = GVCtor->getInitializer()) {
      for (unsigned index = 0; index < C->getNumOperands(); ++index) {
        CurrentCtors.push_back (cast<Constant>(C->getOperand (index)));
      }
    }

    //
    // Rename the global variable so that we can name our global
    // llvm.global_ctors.
    //
    GVCtor->setName ("removed");
  }

  //
  // The ctor list seems to be initialized in different orders on different
  // platforms, and the priority settings don't seem to work.  Examine the
  // module's platform string and take a best guess to the order.
  //
  if (M.getTargetTriple().find ("linux") == std::string::npos)
    CurrentCtors.insert (CurrentCtors.begin(), RuntimeCtorInit);
  else
    CurrentCtors.push_back (RuntimeCtorInit);

  //
  // Create a new initializer.
  //
  ArrayType * AT = ArrayType::get (RuntimeCtorInit-> getType(),
                                         CurrentCtors.size());
  Constant * NewInit=ConstantArray::get (AT, CurrentCtors);

  //
  // Create the new llvm.global_ctors global variable and replace all uses of
  // the old global variable with the new one.
  //
  new GlobalVariable (M,
                      NewInit->getType(),
                      false,
                      GlobalValue::AppendingLinkage,
                      NewInit,
                      "llvm.global_ctors");

  return InitFunc;
}

void PoolAllocate::getAnalysisUsage(AnalysisUsage &AU) const {
  // We will need the heuristic pass to tell us what to do and how to do it

  AU.addRequired<Heuristic>();
  AU.addPreserved<Heuristic>();

  if (dsa_pass_to_use == PASS_EQTD) {
    AU.addRequiredTransitive<EQTDDataStructures>();
    if(lie_preserve_passes != LIE_NONE)
      AU.addPreserved<EQTDDataStructures>();
  } else {
    AU.addRequiredTransitive<EquivBUDataStructures>();
    if(lie_preserve_passes != LIE_NONE)
      AU.addPreserved<EquivBUDataStructures>();
  }

  // Preserve the pool information across passes
  if (lie_preserve_passes == LIE_PRESERVE_ALL)
    AU.setPreservesAll();
}

bool PoolAllocate::runOnModule(Module &M) {
  if (M.begin() == M.end()) return false;
  CurModule = &M;

  //
  // Get pointers to 8 and 32 bit LLVM integer types.
  //
  VoidType  = Type::getVoidTy(M.getContext());
  Int8Type  = IntegerType::getInt8Ty(M.getContext());
  Int32Type = IntegerType::getInt32Ty(M.getContext());

  //
  // Get references to the DSA information.  For SAFECode, we need Top-Down
  // DSA.  For Automatic Pool Allocation only, we need Bottom-Up DSA.  In all
  // cases, we need to use the Equivalence-Class version of DSA.
  //
  // FIXME: Is the PASS_DEFAULT value used?
  //
  if (dsa_pass_to_use == PASS_EQTD)
    Graphs = &getAnalysis<EQTDDataStructures>();    
  else
    Graphs = &getAnalysis<EquivBUDataStructures>();

  //
  // Get the heuristic pass and then tell it who we are.
  //
  CurHeuristic = &getAnalysis<Heuristic>();
  CurHeuristic->Initialize (*this);

  // Add the pool* prototypes to the module
  AddPoolPrototypes(&M);

  // Create the global ctor function for initializing the global pools.
  GlobalPoolCtor = createGlobalPoolCtor (M);

  // Create the pools for memory objects reachable by global variables.
  if (SetupGlobalPools(M))
    return true;

  //
  // Find the DSNodes for each function that will require pool descriptor 
  // arguments to be passed into the function.
  //
  FindPoolArgs (M);

  // Map that maps an original function to its clone
  std::map<Function*, Function*> FuncMap;

  //
  // Functions that require pool handles to be passed in as parameters will
  // need to be cloned.  Scan through the set of all functions and record which
  // ones need to be cloned.
  //
  // We record the list of functions to clone and then clone them to avoid
  // iterator invalidation errors (creating a function clone adds a function to
  // the set of functions in a Module).  This may be a little slower, but
  // random memory errors are a pain to debug.
  //
  std::vector<Function *> FunctionsToClone;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    if (!I->isDeclaration() && Graphs->hasDSGraph(*I)) {
      FunctionsToClone.push_back (I);
    }
  }

  //
  // 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 needs new
  // arguments, make its clone.
  //
  // FIXME: Should use a isClone() method.
  //
  std::set<Function*> ClonedFunctions;
  Function *MainFunc = M.getFunction("main");
  while (FunctionsToClone.size()) {
    //
    // Remove a function from the list of functions to clone.
    //
    Function * Original = FunctionsToClone.back();
    FunctionsToClone.pop_back ();

    // Don't clone 'main'!
    if (Original == MainFunc) {
      continue;
    }

    //
    // Clone the function.  Record a pointer to the new clone if one was
    // created.
    //
    if (Function *Clone = MakeFunctionClone(*Original)) {
      FuncMap[Original] = Clone;
      ClonedFunctions.insert(Clone);
    }
  }

  //
  // Now that all call targets are available, rewrite the function bodies of
  // the clones or the original function (if the original has no clone).
  //
  // FIXME: Use utility methods to make this code more readable!
  //
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    if (!I->isDeclaration() && !ClonedFunctions.count(I) &&
        Graphs->hasDSGraph(*I)) {
      std::map<Function*, Function*>::iterator FI = FuncMap.find(I);
      ProcessFunctionBody(*I, FI != FuncMap.end() ? *FI->second : *I);
    }
  }

  //
  // Replace any remaining uses of original functions with the transformed
  // function i.e., the cloned function.
  //
  for (std::map<Function *, Function *>::iterator I = FuncMap.begin(),
                                                  E = FuncMap.end();
                                                  I != E; ++I) {
    Function *F = I->first;

    //
    // Scan through all uses of the original function.  Replace it as long as
    // the use is not a Call or Invoke instruction that
    //  o) is within an original function (all such call instructions should
    //     have been transformed already), and
    //  o) the called function is the function that we're replacing
    //
    std::vector<User *> toReplace;
    for (Function::user_iterator User = F->user_begin();
                                User != F->user_end();
                                ++User) {
      if (CallInst * CI = dyn_cast<CallInst>(*User)) {
        if (CI->getCalledFunction() == F)
          if ((FuncMap.find(CI->getParent()->getParent())) != FuncMap.end())
            continue;
      }

      if (InvokeInst * CI = dyn_cast<InvokeInst>(*User)) {
        if (CI->getCalledFunction() == F)
          if ((FuncMap.find(CI->getParent()->getParent())) != FuncMap.end())
            continue;
      }

      //
      // We want to replace this use.  Add it to the worklist.
      //
      toReplace.push_back (*User);
    }

    //
    // Now do replacement on all items within the worklist.
    //
    while (toReplace.size()) {
      llvm::User * user = toReplace.back();
      toReplace.pop_back();

      Constant* CEnew = ConstantExpr::getPointerCast(I->second, F->getType());

      //
      // We must handle Constants specially; we cannot call replaceUsesOfWith()
      // on a constant because they are uniqued.
      //
      if (Constant *C = dyn_cast<Constant>(user)) {
        if (!isa<GlobalValue>(C)) {
          //
          // Scan through all operands in the constant.  If they are the
          // function that we want to replace, then add them to a worklist (we
          // use a worklist to avoid iterator invalidation errors).
          //
          std::vector<Use *> ReplaceWorklist;
          for (User::op_iterator use = user->op_begin();
               use != user->op_end();
               ++use) {
            if (use->get() == F) {
              ReplaceWorklist.push_back (use);
            }
          }

          //
          // Do replacements in the worklist.
          //
          for (unsigned index = 0; index < ReplaceWorklist.size(); ++index)
            C->replaceUsesOfWithOnConstant(F, CEnew, ReplaceWorklist[index]);
          continue;
        }
      }
      user->replaceUsesOfWith (F, CEnew);
    }
  }

  //
  // Add an empty __poolalloc_init() function.  SAFECode will call this to
  // intialize things; we don't make use of it with real pool allocation.
  //
  createPoolAllocInit (M);

  //
  // FIXME: Make name more descriptive and explain, in a comment here, what this
  //        code is trying to do (namely, avoid optimizations for performance
  //        overhead measurements?).
  //
  // FIXME: Breaks invalid C code. Remove from poolalloc and move to a separate pass.
  
  #if 0
  if (CurHeuristic->IsRealHeuristic())
    MicroOptimizePoolCalls();
  #endif
 
  return true;
}

// AddPoolPrototypes - Add prototypes for the pool functions to the specified
// module and update the Pool* instance variables to point to them.
//
// NOTE: If these are changed, make sure to update PoolOptimize.cpp as well!
//
void PoolAllocate::AddPoolPrototypes(Module* M) {
  if (VoidPtrTy == 0) {
    // NOTE: If these are changed, make sure to update PoolOptimize.cpp as well!
    VoidPtrTy = PointerType::getUnqual(Int8Type);
    PoolDescType = getPoolType(&M->getContext());
    PoolDescPtrTy = PointerType::getUnqual(PoolDescType);
  }

  // TODO: I'm not sure how to do this on mainline.
  //M->addTypeName("PoolDescriptor", PoolDescType);

  
  // Get poolinit function.
  PoolInit = M->getOrInsertFunction("poolinit", VoidType,
                                            PoolDescPtrTy, Int32Type,
                                            Int32Type, NULL);

  // Get pooldestroy function.
  PoolDestroy = M->getOrInsertFunction("pooldestroy", VoidType,
                                               PoolDescPtrTy, NULL);
  
  // The poolalloc function.
  PoolAlloc = M->getOrInsertFunction("poolalloc", 
                                             VoidPtrTy, PoolDescPtrTy,
                                             Int32Type, NULL);
  
  // The poolrealloc function.
  PoolRealloc = M->getOrInsertFunction("poolrealloc",
                                               VoidPtrTy, PoolDescPtrTy,
                                               VoidPtrTy, Int32Type, NULL);

  // The poolcalloc function.
  PoolCalloc = M->getOrInsertFunction("poolcalloc",
                                      VoidPtrTy, PoolDescPtrTy,
                                      Int32Type, Int32Type, NULL);

  // The poolmemalign function.
  PoolMemAlign = M->getOrInsertFunction("poolmemalign",
                                                VoidPtrTy, PoolDescPtrTy,
                                                Int32Type, Int32Type, 
                                                NULL);

  // The poolstrdup function.
  PoolStrdup = M->getOrInsertFunction("poolstrdup",
                                               VoidPtrTy, PoolDescPtrTy,
                                               VoidPtrTy, NULL);
  // The poolmemalign function.
  // Get the poolfree function.
  PoolFree = M->getOrInsertFunction("poolfree", VoidType,
                                            PoolDescPtrTy, VoidPtrTy, NULL);
  //Get the poolregister function
  PoolRegister = M->getOrInsertFunction("poolregister", VoidType,
                                 PoolDescPtrTy, VoidPtrTy, Int32Type, NULL);

  Function* pthread_create_func = M->getFunction("pthread_create");
  if(pthread_create_func)
  {
      Function::arg_iterator i = pthread_create_func->arg_begin();
      std::vector<Type*> non_vararg_params;
      non_vararg_params.push_back(i++->getType());
      non_vararg_params.push_back(i++->getType());
      non_vararg_params.push_back(i++->getType());
      non_vararg_params.push_back(Int32Type);
      PoolThreadWrapper = M->getOrInsertFunction("poolalloc_pthread_create",FunctionType::get(Int32Type,non_vararg_params,true));
  }
}

static void getCallsOf(Constant *C, std::vector<CallInst*> &Calls) {
  // Get the Function out of the constant
  Function * F;
  ConstantExpr * CE;
  if (!(F=dyn_cast<Function>(C))) {
    if ((CE = dyn_cast<ConstantExpr>(C)) && (CE->isCast()))
      F = dyn_cast<Function>(CE->getOperand(0));
    else
      assert (0 && "Constant is not a Function of ConstantExpr!"); 
  }
  Calls.clear();
  for (Value::user_iterator UI = F->user_begin(), E = F->user_end(); UI != E; ++UI)
    Calls.push_back(cast<CallInst>(*UI));
}

//
// Function: OptimizePointerNotNull()
//
// Inputs:
//  V       - ???
//  Context - The LLVM Context to which any values we insert into the program
//            will belong.
//
static void
OptimizePointerNotNull(Value *V, LLVMContext * Context) {
  for (Value::user_iterator I = V->user_begin(), E = V->user_end(); I != E; ++I) {
    Instruction *User = cast<Instruction>(*I);
    if (isa<ICmpInst>(User) && cast<ICmpInst>(User)->isEquality()) {
      ICmpInst * ICI = cast<ICmpInst>(User);
      if (isa<Constant>(User->getOperand(1)) && 
          cast<Constant>(User->getOperand(1))->isNullValue()) {
        bool CondIsTrue = ICI->getPredicate() == ICmpInst::ICMP_NE;
        Type * Int1Type  = IntegerType::getInt1Ty(*Context);
        User->replaceAllUsesWith(ConstantInt::get(Int1Type, CondIsTrue));
      }
    } else if ((User->getOpcode() == Instruction::Trunc) ||
               (User->getOpcode() == Instruction::ZExt) ||
               (User->getOpcode() == Instruction::SExt) ||
               (User->getOpcode() == Instruction::FPToUI) ||
               (User->getOpcode() == Instruction::FPToSI) ||
               (User->getOpcode() == Instruction::UIToFP) ||
               (User->getOpcode() == Instruction::SIToFP) ||
               (User->getOpcode() == Instruction::FPTrunc) ||
               (User->getOpcode() == Instruction::FPExt) ||
               (User->getOpcode() == Instruction::PtrToInt) ||
               (User->getOpcode() == Instruction::IntToPtr) ||
               (User->getOpcode() == Instruction::BitCast)) {
      // Casted pointers are also not null.
      if (isa<PointerType>(User->getType()))
        OptimizePointerNotNull(User, Context);
    } else if (User->getOpcode() == Instruction::GetElementPtr) {
      // GEP'd pointers are also not null.
      OptimizePointerNotNull(User, Context);
    }
  }
}

/// FIXME: Should these be in the pooloptimize pass?
///
/// MicroOptimizePoolCalls - Apply any microoptimizations to calls to pool
/// allocation function calls that we can.  This runs after the whole program
/// has been transformed.
void PoolAllocate::MicroOptimizePoolCalls() {
  // Optimize poolalloc
  std::vector<CallInst*> Calls;
  getCallsOf(PoolAlloc, Calls);
  for (unsigned i = 0, e = Calls.size(); i != e; ++i) {
    CallInst *CI = Calls[i];
    // poolalloc never returns null.  Loop over all uses of the call looking for
    // set(eq|ne) X, null.
    OptimizePointerNotNull(CI, &CI->getContext());
  }

  // TODO: poolfree accepts a null pointer, so remove any check above it, like
  // 'if (P) poolfree(P)'
}

//
// Function: GetNodesReachableFromGlobals()
//
// Description:
//  This function finds all DSNodes which are reachable from globals.  It finds
//  DSNodes both within the local DSGraph as well as in the Globals graph that
//  are reachable from globals.
//
// Inputs:
//  G - The DSGraph for which to find DSNodes which are reachable by globals.
//      This DSGraph can either by a DSGraph associated with a function *or*
//      it can be the globals graph itself.
//
// Outputs:
//  NodesFromGlobals - A reference to a container object in which to record
//                     DSNodes reachable from globals.  DSNodes are *added* to
//                     this container; it is not cleared by this function.
//                     DSNodes from both the local and globals graph are added.
static inline void
GetNodesReachableFromGlobals (DSGraph* G,
                              DenseSet<const DSNode*> &NodesFromGlobals) {
  //
  // Get the globals graph associated with this DSGraph.  If the globals graph
  // is NULL, then the graph that was passed in *is* the globals graph.
  //
  DSGraph * GlobalsGraph = G->getGlobalsGraph();
  if (!GlobalsGraph)
    GlobalsGraph = G;

  //
  // Find all DSNodes which are reachable in the globals graph.
  //
  for (DSGraph::node_iterator NI = GlobalsGraph->node_begin();
       NI != GlobalsGraph->node_end();
       ++NI) {
    NI->markReachableNodes(NodesFromGlobals);
  }

  //
  // Now the fun part.  Find DSNodes in the local graph that correspond to
  // those nodes reachable in the globals graph.  Add them to the set of
  // reachable nodes, too.
  //
  if (G->getGlobalsGraph()) {
    //
    // Compute a mapping between local DSNodes and DSNodes in the globals
    // graph.
    //
    DSGraph::NodeMapTy NodeMap;
    G->computeGToGGMapping (NodeMap);

    //
    // Scan through all DSNodes in the local graph.  If a local DSNode has a
    // corresponding DSNode in the globals graph that is reachable from a 
    // global, then add the local DSNode to the set of DSNodes reachable from a
    // global.
    //
    // FIXME: A node's existance within the global DSGraph is probably
    //        sufficient evidence that it is reachable from a global.
    //
    DSGraph::node_iterator ni = G->node_begin();
    for (; ni != G->node_end(); ++ni) {
      DSNode * N = ni;
      if (NodesFromGlobals.count (NodeMap[N].getNode()))
        NodesFromGlobals.insert (N);
    }
  }
}

//
// Method: FindPoolArgs()
//
// Description:
//  Loop over the functions in the original program finding the pool descriptor
//  arguments necessary for each function.
//
void
PoolAllocate::FindPoolArgs (Module & M) {
  //
  // Scan through each equivalence class.  The Equivalence Class Bottom-Up
  // pass guarantees that each function that is the target of an indirect
  // function call will have the same DSGraph and will have identical DSNodes
  // for corresponding arguments.  Therefore, we want to process all the
  // functions in the same equivalence class once to avoid doing extra work.
  //
  const DSCallGraph & callgraph = Graphs->getCallGraph();
  DSGraph* G = Graphs->getGlobalsGraph();
  DSGraph::ScalarMapTy& SM = G->getScalarMap();
  for (DSCallGraph::callee_key_iterator ii = callgraph.key_begin(),
       ee = callgraph.key_end(); ii != ee; ++ii) {
    bool isIndirect = ((*ii).getCalledFunction() == NULL);
    bool externFunctionFound = false;

    if (isIndirect) {
      std::vector<const Function *> Functions;
      DSCallGraph::callee_iterator csi = callgraph.callee_begin(*ii),
                                   cse = callgraph.callee_end(*ii);
      while(csi != cse) {
        const Function *F = *csi;
        DSCallGraph::scc_iterator sccii = callgraph.scc_begin(F),
                                sccee = callgraph.scc_end(F);
        for(;sccii != sccee; ++sccii) {
          DSGraph::ScalarMapTy::const_iterator I = SM.find(SM.getLeaderForGlobal(*sccii));
          if (I != SM.end()) {
            if ((*sccii)->isDeclaration()) {
              externFunctionFound = true;
              break;
            }
            Functions.push_back (*sccii);
          }
        }
        ++csi;
      }
      const Function *F1 = (*ii).getInstruction()->getParent()->getParent();
      F1 = callgraph.sccLeader(&*F1);

      DSCallGraph::scc_iterator sccii = callgraph.scc_begin(F1),
                                sccee = callgraph.scc_end(F1);
      for(;sccii != sccee; ++sccii) {
        DSGraph::ScalarMapTy::const_iterator I = SM.find(SM.getLeaderForGlobal(*sccii));
        if (I != SM.end()) {
          if ((*sccii)->isDeclaration()) {
            externFunctionFound = true;
            break;
          }
          Functions.push_back (*sccii);
        }
      }
      bool doNotPassPools = externFunctionFound;
      // go through the list of functions to check if any is external
      // or callable from an incomplete call site. Then no pool args 
      // are needed; else find pool args. 
      if(!doNotPassPools){
        for (unsigned index = 0; index < Functions.size(); ++index) {
          const Function * F = Functions[index];
          if (callgraph.called_from_incomplete_site(F)){
            doNotPassPools = true;
            break;
          }
        }
      }
       
      if(doNotPassPools) {
        // For functions that are in the same equivalence class as an 
        // external function, we cannot pass pool args. Because we 
        // cannot know which function the call site calls, the 
        // internal function or the external ones. 
        // FIXME: Solve this by devirtualizing the call site.
        for (unsigned index = 0; index < Functions.size(); ++index) {
          Function * F = const_cast<Function*>(Functions[index]);
          if (FunctionInfo.find (F) != FunctionInfo.end()) {
#ifndef NDEBUG
            FuncInfo & FI =  FunctionInfo.find(F)->second;
            assert(FI.ArgNodes.size() == 0);
#endif
            continue;
          }
          // TODO: Original code was:
          // FunctionInfo.insert(std::make_pair(F, FuncInfo(*F))).first->second;
          // But this has unused components.. (.first->second?)
          // So just inserting the function info, and hoping for the best.
          FunctionInfo.insert(std::make_pair(F, FuncInfo(*F)));
        }
      } else {
        FindFunctionPoolArgs (Functions);
      }
    }
  }
  
  //
  // Make sure every function has a FuncInfo structure.
  //
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    if (!I->isDeclaration() && Graphs->hasDSGraph(*I)) {
      if (FunctionInfo.find (I) == FunctionInfo.end()) {
        std::vector<const Function *> Functions;
        Functions.push_back(I);
        FindFunctionPoolArgs (Functions);
      }
    }
  }

  return;
}

/// FindFunctionPoolArgs - In the first pass over the program, we decide which
/// arguments will have to be added for each function, build the FunctionInfo
/// map and recording this info in the ArgNodes set.
void
PoolAllocate::FindFunctionPoolArgs (const std::vector<const Function *> & Functions) {
  //
  // If there are no functions to process, then do nothing.
  //
  if (Functions.size() == 0)
    return;

  //
  // Find all of the DSNodes which could possibly require a pool to be passed
  // in.  Collect these DSNodes into one big container.
  //
  std::vector<DSNodeHandle> RootNodes;
  for (unsigned index = 0; index < Functions.size(); ++index) {
    //
    // Get the DSGraph of the function.
    //
    const Function * F = Functions[index];
    DSGraph* G = Graphs->getDSGraph (*F);

    //
    // Get all of the DSNodes which could possibly require a pool to be
    // passed into the function.
    //
    G->getFunctionArgumentsForCall (F, RootNodes);
  }

  //
  // If there is no memory activity in any of these functions, then nothing is
  // required.
  //
  if (RootNodes.size() == 0)
    return;

  //
  // Now find all nodes which are reachable from these argument DSNodes.
  //
  DenseSet<const DSNode*> MarkedNodes;
  for (unsigned index = 0; index < RootNodes.size(); ++index) {
    if (DSNode * N = RootNodes[index].getNode()) {
      N->markReachableNodes(MarkedNodes);
    }
  }

  //
  // Determine which DSNodes are reachable from globals.  If a node is
  // reachable from a global, we will create a global pool for it, so no
  // argument passage is required.
  //
  if (!PassAllArguments) {
    std::map<const DSNode*, Value*>::iterator gni;
    for (gni = GlobalNodes.begin(); gni != GlobalNodes.end(); ++gni) {
      MarkedNodes.erase(gni->first);
    }
  }

#if 0
  DenseSet<const DSNode*> NodesFromGlobals;
  for (unsigned index = 0; index < Functions.size(); ++index) {
    //
    // Get the DSGraph of the function.
    //
    const Function * F = Functions[index];
    DSGraph* G = Graphs->getDSGraph(*F);
    GetNodesReachableFromGlobals (G, NodesFromGlobals);
  }

  //
  // Remove any nodes reachable from a global.  These nodes will be put into
  // global pools, which do not require arguments to be passed in.  Also, erase
  // any marked node that is not a heap node.  Since no allocations or frees
  // will be done with it, it needs no argument.
  //
  // FIXME:
  //  1) PassAllArguments seems to be ignored here.  Why is that?
  //  2) Should the heap node check be part of the PassAllArguments check?
  //  3) SAFECode probably needs to pass the pool even if it's not a heap node.
  //     We should probably just do what the heuristic tells us to do.
  //
  for (DenseSet<const DSNode*>::iterator I = MarkedNodes.begin(),
         E = MarkedNodes.end(); I != E; ) {
    const DSNode *N = *I; ++I;
    if ((!(1 || N->isHeapNode()) && !PassAllArguments) ||
        NodesFromGlobals.count(N))
      MarkedNodes.erase(N);
  }
#endif

  //
  // Create new FuncInfo entries for all of the functions.  Each one will have
  // the same set of DSNodes passed in.
  //
  for (unsigned index = 0; index < Functions.size(); ++index) {
    Function * F = const_cast<Function*>(Functions[index]);
    if (FunctionInfo.find (F) != FunctionInfo.end()) {
#ifndef NDEBUG
      FuncInfo & FI =  FunctionInfo.find(F)->second;
      assert(FI.ArgNodes.size() == MarkedNodes.size());
#endif
      continue;
    }

    FuncInfo & FI =
            FunctionInfo.insert(std::make_pair(F, FuncInfo(*F))).first->second;
    //
    // DenseSet does not have iterator traits, so we cannot use an insert()
    // method that takes iterators.  Instead, we must use a loop to insert each
    // element into MarkedNodes and ArgNodes one at a time.
    //
    for (DenseSet<const DSNode*>::iterator ii = MarkedNodes.begin(),
         ee = MarkedNodes.end(); ii != ee; ++ii) {
      FI.MarkedNodes.insert(*ii);
      FI.ArgNodes.insert(FI.ArgNodes.end(), *ii);
    }
  }
}

//
// Method: MakeFunctionClone()
//
// Description:
//  If the specified function needs to be modified for pool allocation support,
//  make a clone of it, adding additional arguments as necessary, and return
//  it.
//
// Return value:
//  NULL - The function did not need to be cloned.
//  Otherwise, a pointer to the clone of the function is returned.
//
Function *
PoolAllocate::MakeFunctionClone (Function & F) {
  //
  // If the DSGraph for this function has no DSNodes, then we don't need to
  // make a clone.
  //
  DSGraph* G = Graphs->getDSGraph(F);
  if (G->node_begin() == G->node_end()) return 0;

  //
  // There is no need to clone a function if no pools need to be passed in!
  //
  FuncInfo &FI = *getFuncInfo(F);
  if (FI.ArgNodes.empty())
    return 0;

  // Update statistics..
  NumArgsAdded += FI.ArgNodes.size();
  if (MaxArgsAdded < FI.ArgNodes.size())
    MaxArgsAdded = FI.ArgNodes.size();
  ++NumCloned;
 
  //
  // Determine the type of the new function.  We will insert new parameters
  // for the pools to pass into the function, and then we will insert the
  // original parameter values after that.
  //
  std::vector<Type*> ArgTys(FI.ArgNodes.size(), PoolDescPtrTy);
  FunctionType *OldFuncTy = F.getFunctionType();
  ArgTys.reserve(OldFuncTy->getNumParams() + FI.ArgNodes.size());
  ArgTys.insert(ArgTys.end(), OldFuncTy->param_begin(), OldFuncTy->param_end());

  // Create the new function prototype
  FunctionType *FuncTy = FunctionType::get(OldFuncTy->getReturnType(), ArgTys,
                                           OldFuncTy->isVarArg());

  //
  // FIXME: Can probably add new function to module during creation
  //
  // Create the new function...
  //
  Function *New = Function::Create(FuncTy, Function::InternalLinkage, F.getName().str() + "_clone");
  F.getParent()->getFunctionList().insert(&F, New);
  CloneToOrigMap[New] = &F;   // Remember original function.

  // Set the rest of the new arguments names to be PDa<n> and add entries to the
  // pool descriptors map
  std::map<const DSNode*, Value*> &PoolDescriptors = FI.PoolDescriptors;
  Function::arg_iterator NI = New->arg_begin();
  for (unsigned i = 0, e = FI.ArgNodes.size(); i != e; ++i, ++NI) {
    NI->setName("PDa");
    PoolDescriptors[FI.ArgNodes[i]] = NI;
  }

  //
  // Map the existing arguments of the old function to the corresponding
  // arguments of the new function, and copy over the names.
  //
  //
  ValueToValueMapTy ValueMap;
  // FIXME: Remove use of SAFECodeEnabled flag
  // FIXME: Is FI.ValueMap empty?  We should put an assert to verify that it
  //        is.
  if (SAFECodeEnabled)
    for (std::map<const Value*, Value*>::iterator I = FI.ValueMap.begin(),
           E = FI.ValueMap.end(); I != E; ++I)
      ValueMap.insert(std::make_pair(I->first, I->second));

  for (Function::arg_iterator I = F.arg_begin();
       NI != New->arg_end(); ++I, ++NI) {
    ValueMap[I] = NI;
    NI->setName(I->getName());
  }

  // Perform the cloning.
  SmallVector<ReturnInst*,100> Returns;
  // TODO: Evalute the boolean parameter here...
  CloneFunctionInto(New, &F, ValueMap, true, Returns);

  //
  // Invert the ValueMap into the NewToOldValueMap.
  //
  std::map<Value*, const Value*> &NewToOldValueMap = FI.NewToOldValueMap;
  for (ValueToValueMapTy::iterator I = ValueMap.begin(),
         E = ValueMap.end(); I != E; ++I)
    NewToOldValueMap.insert(std::make_pair(I->second, I->first));

  //
  // The CloneFunctionInto() copies over all the parameter attributes from the
  // old function to the new function.  However, it may place the sret
  // attribute on a parameter that is no longer the first parameter.  Since
  // sret is required to be on the first parameter, go find any use of it and
  // strip it off.  This is safe since it is only used for calling conventions
  // and optimization hints.
  //
  Function::ArgumentListType & ArgList = New->getArgumentList ();
  Function::ArgumentListType::iterator arg = ArgList.begin();
  AttrBuilder B;
  B.addAttribute(Attribute::StructRet);
  for (; arg != ArgList.end(); ++arg) {
    arg->removeAttr(AttributeSet::get(F.getContext(), 0, B));
  }

  //
  // The CloneFunctionInto() function does not ensure that the clone has the
  // same calling convention as the original function.  Since pool allocation
  // merely replaces uses of the old function with the clone, both must have
  // the same calling convention.  Make sure the new function has the same
  // calling convention as the original function.
  //
  New->setCallingConv (F.getCallingConv());

  return FI.Clone = New;
}

//
// FIXME: Update comment
//
// SetupGlobalPools - Create global pools for all DSNodes in the globals graph
// which contain heap objects.  If a global variable points to a piece of memory
// allocated from the heap, this pool gets a global lifetime.  This is
// implemented by making the pool descriptor be a global variable of its own,
// and initializing the pool on entrance to main.  Note that we never destroy
// the pool because it has global lifetime.
//
// This method returns true if correct pool allocation of the module cannot be
// performed because there is no main function for the module and there are
// global pools.
//
bool PoolAllocate::SetupGlobalPools(Module &M) {
  //
  // Find all of the DSNodes which are reachable from globals and may require
  // pools.
  //
  std::vector<const DSNode*> NodesToPA;
  CurHeuristic->getGlobalPoolNodes (NodesToPA);

  errs() << "Pool allocating " << NodesToPA.size() << " global nodes!\n";

  DSGraph* GG = Graphs->getGlobalsGraph();
  std::vector<Heuristic::OnePool> ResultPools;
  CurHeuristic->AssignToPools(NodesToPA, 0, GG, ResultPools);

  BasicBlock::iterator InsertPt = GlobalPoolCtor->getEntryBlock().begin();

  //
  // Create a set of the DSNodes globally reachable from memory.  We'll assign
  // NULL pool handles for those nodes which are globally reachable but for
  // which the heuristic did not assign a pool.
  //
  std::set<const DSNode *> GlobalHeapNodes (NodesToPA.begin(), NodesToPA.end());

  // Perform all global assignments as specified.
  for (unsigned i = 0, e = ResultPools.size(); i != e; ++i) {
    Heuristic::OnePool &Pool = ResultPools[i];
    Value *PoolDesc = Pool.PoolDesc;
    if (PoolDesc == 0) {
      PoolDesc = CreateGlobalPool(Pool.PoolSize, Pool.PoolAlignment, "GlobalPool", InsertPt);

      if (Pool.NodesInPool.size() == 1 &&
          !Pool.NodesInPool[0]->isNodeCompletelyFolded())
        ++NumTSPools;
    }
    for (unsigned N = 0, e = Pool.NodesInPool.size(); N != e; ++N) {
      GlobalNodes[Pool.NodesInPool[N]] = PoolDesc;
      GlobalHeapNodes.erase(Pool.NodesInPool[N]);  // Handled!
    }
  }

  // Any unallocated DSNodes get null pool descriptor pointers.
  for (std::set<const DSNode*>::iterator I = GlobalHeapNodes.begin(),
         E = GlobalHeapNodes.end(); I != E; ++I) {
    GlobalNodes[*I] = ConstantPointerNull::get(PointerType::getUnqual(PoolDescType));
    ++NumNonprofit;
  }

  return false;
}

/// CreateGlobalPool - Create a global pool descriptor object, and insert a
/// poolinit for it into main.  IPHint is an instruction that we should insert
/// the poolinit before if not null.
GlobalVariable *PoolAllocate::CreateGlobalPool(unsigned RecSize, unsigned Align,
                                               std::string name, Instruction *IPHint) {
  GlobalVariable *GV =
    new GlobalVariable(*CurModule,
                       PoolDescType, false, GlobalValue::InternalLinkage, 
                       ConstantAggregateZero::get(PoolDescType), name);

  // Update the global DSGraph to include this.
  DSNode *GNode = Graphs->getGlobalsGraph()->addObjectToGraph(GV);
  GNode->setModifiedMarker()->setReadMarker();

  BasicBlock::iterator InsertPt;
  if (IPHint)
    InsertPt = IPHint;
  else {
    InsertPt = GlobalPoolCtor->getEntryBlock().begin();
    while (isa<AllocaInst>(InsertPt)) ++InsertPt;
  }

  Value *ElSize = ConstantInt::get(Int32Type, RecSize);
  Value *AlignV = ConstantInt::get(Int32Type, Align);
  Value* Opts[3] = {GV, ElSize, AlignV};
  CallInst::Create(PoolInit, Opts, "", InsertPt);
  ++NumPools;
  return GV;
}


// CreatePools - This creates the pool initialization and destruction code for
// the DSNodes specified by the NodesToPA list.  This adds an entry to the
// PoolDescriptors map for each DSNode.
//
// Note that this method does not insert calls to poolinit() or pooldestroy().
// Those are added later.
//
void
PoolAllocate::CreatePools (Function &F, DSGraph* DSG,
                           const std::vector<const DSNode*> &NodesToPA,
                           std::map<const DSNode*, Value*> &PoolDescriptors) {
  //
  // If there are no pools to create, then do nothing.
  //
  if (NodesToPA.empty()) return;

  std::vector<Heuristic::OnePool> ResultPools;
  CurHeuristic->AssignToPools(NodesToPA, &F, NodesToPA[0]->getParentGraph(),
                              ResultPools);

  std::set<const DSNode*> UnallocatedNodes(NodesToPA.begin(), NodesToPA.end());

  BasicBlock::iterator InsertPoint = F.front().begin();

  // Is this main?  If so, make the pool descriptors globals, not automatic
  // vars.
  bool IsMain = F.getName().str() == "main" && F.hasExternalLinkage();

  //
  // Create each pool and update the DSGraph to account for the new pool.
  // Additionally, update the mapping between DSNodes and pools.
  //
  for (unsigned i = 0, e = ResultPools.size(); i != e; ++i) {
    Heuristic::OnePool &Pool = ResultPools[i];
    Value *PoolDesc = Pool.PoolDesc;
    if (PoolDesc == 0) {
      //
      // Create a pool descriptor for the pool.  The poolinit will be inserted
      // later.
      //
      if (!IsMain) {
        PoolDesc = new AllocaInst(PoolDescType, 0, "PD", InsertPoint);

#if 0
        //
        // Create a node in DSG to represent the new alloca.
        //
        // Note:
        //  Disable this for now.  Other passes don't look up DSNodes for pool
        //  handles, and doing this seems to blow up memory consumption.  So,
        //  for now, don't do this.
        //
        DSNode *NewNode = DSG->addObjectToGraph(PoolDesc);
        NewNode->setModifiedMarker()->setReadMarker();  // This is M/R
#endif
      } else {
        PoolDesc = CreateGlobalPool(Pool.PoolSize, Pool.PoolAlignment,
                                    "PoolForMain", InsertPoint);

        // Add the global node to main's graph.
        DSNode *NewNode = DSG->addObjectToGraph(PoolDesc);
        NewNode->setModifiedMarker()->setReadMarker();  // This is M/R

        if (Pool.NodesInPool.size() == 1 &&
            !Pool.NodesInPool[0]->isNodeCompletelyFolded())
          ++NumTSPools;
      }
    }

    //
    // Update the mapping of DSNodes to pool descriptors.
    //
    // FIXME:
    //  What are unallocated DSNodes?
    //
    for (unsigned N = 0, e = Pool.NodesInPool.size(); N != e; ++N) {
      PoolDescriptors[Pool.NodesInPool[N]] = PoolDesc;
      UnallocatedNodes.erase(Pool.NodesInPool[N]);  // Handled!
    }
  }

  //
  // Any unallocated DSNodes get null pool descriptor pointers.
  //
  for (std::set<const DSNode*>::iterator I = UnallocatedNodes.begin(),
         E = UnallocatedNodes.end(); I != E; ++I) {
    PoolDescriptors[*I] = ConstantPointerNull::get(PointerType::getUnqual(PoolDescType));
    ++NumNonprofit;
  }
}

//
// Method: processFunction()
//
// Description:
//  Pool allocate any data structures which are contained in the specified
//  function.
//
void
PoolAllocate::ProcessFunctionBody(Function &F, Function &NewF) {
  //
  // Get the DSGraph of the function and the FuncInfo of the function.  We'll
  // need th former and be updatting the latter.
  //
  DSGraph* G = Graphs->getDSGraph(F);
  FuncInfo & FI = *getFuncInfo(F);

  //
  // Get the mapping between local DSNodes and DSNodes in the globals graph
  //
  DSGraph::NodeMapTy GlobalsGraphNodeMapping;
  G->computeGToGGMapping(GlobalsGraphNodeMapping);

  //
  // Determine which DSNodes have already been assigned global pools.  Record
  // this information in the function's FuncInfo structure.
  //
  for (DSGraph::node_iterator I = G->node_begin(), E = G->node_end();
       I != E;
       ++I){
    // Get the global DSNode matching this DSNode
    DSNode * N = I;

    // If the local DSNode was assigned a global pool, update the pool
    // descriptors for the function
    if (GlobalNodes[N]) {
      FI.PoolDescriptors[N] = GlobalNodes[N];
    }

    // If a corresponding global DSNode was assigned a global pool, update the
    // pool descriptors for the function
    DSNode * GGN = GlobalsGraphNodeMapping[N].getNode();
    if (GGN && GlobalNodes[GGN]) {
      FI.PoolDescriptors[N] = GlobalNodes[GGN];
    }
  }

  //
  // Ask the heuristic for the list of DSNodes which should get local pools.
  //
  std::vector<const DSNode *> LocalNodes;
  CurHeuristic->getLocalPoolNodes (F, LocalNodes);

  //
  // Remove from the set all of the DSNodes which are poolallocated in a caller
  // function.
  //
  for (unsigned index = 0; index < LocalNodes.size(); ++index) {
    if (FI.MarkedNodes.count (LocalNodes[index]) == 0) {
      FI.NodesToPA.push_back (LocalNodes[index]);
    }
  }

  //
  // Add code to create the pools that are local to this function.
  //
  if (!FI.NodesToPA.empty()) {
    errs() << "[" << F.getName().str() << "] " << FI.NodesToPA.size()
              << " nodes pool allocatable\n";
    CreatePools(NewF, G, FI.NodesToPA, FI.PoolDescriptors);
  } else {
    DEBUG(errs() << "[" << F.getName().str() << "] transforming body.\n");
  }

  // Transform the body of the function now... collecting information about uses
  // of the pools.
  std::multimap<AllocaInst*, Instruction*> PoolUses;
  std::multimap<AllocaInst*, CallInst*> PoolFrees;
  TransformBody(G, FI, PoolUses, PoolFrees, NewF);

  // Create pool construction/destruction code
  if (!FI.NodesToPA.empty())
    InitializeAndDestroyPools(NewF, FI.NodesToPA, FI.PoolDescriptors,
                              PoolUses, PoolFrees);

  //
  // Some heuristics want to do special transformation to the function.  Let
  // them do so here.
  //
  CurHeuristic->HackFunctionBody(NewF, FI.PoolDescriptors);
}

template<class IteratorTy>
static void AllOrNoneInSet(IteratorTy S, IteratorTy E,
                           std::set<BasicBlock*> &Blocks, bool &AllIn,
                           bool &NoneIn) {
  AllIn = true;
  NoneIn = true;
  for (; S != E; ++S)
    if (Blocks.count(*S))
      NoneIn = false;
    else
      AllIn = false;
}

static void DeleteIfIsPoolFree(Instruction *I, AllocaInst *PD,
                             std::multimap<AllocaInst*, CallInst*> &PoolFrees) {
  std::multimap<AllocaInst*, CallInst*>::iterator PFI, PFE;
  if (dyn_cast<CallInst>(I))
    for (tie(PFI,PFE) = PoolFrees.equal_range(PD); PFI != PFE; ++PFI)
      if (PFI->second == I) {
        PoolFrees.erase(PFI);
        I->eraseFromParent();
        ++NumPoolFree;
        return;
      }
}

void PoolAllocate::CalculateLivePoolFreeBlocks(std::set<BasicBlock*>&LiveBlocks,
                                               Value *PD) {
  for (Value::user_iterator I = PD->user_begin(), E = PD->user_end(); I != E; ++I){
    //
    // The only users of the pool should be call, invoke, and cast
    // instructions.  We know that poolfree() and pooldestroy() do not need to
    // cast pool handles, so if we see a non-call instruction, we know it's not
    // used in a poolfree() or pooldestroy() call.
    //
    if (Instruction * Inst = dyn_cast<Instruction>(*I)) {
      if (!isa<CallInst>(*I)) {
        // This block and every block that can reach this block must keep pool
        // frees.
        for (idf_ext_iterator<BasicBlock*, std::set<BasicBlock*> >
               DI = idf_ext_begin(Inst->getParent(), LiveBlocks),
               DE = idf_ext_end(Inst->getParent(), LiveBlocks);
             DI != DE; ++DI)
          /* empty */;
        continue;
      }
    }

    CallSite U = CallSite(I->stripPointerCasts());
    if (U.getCalledValue() != PoolFree && U.getCalledValue() != PoolDestroy) {
      // This block and every block that can reach this block must keep pool
      // frees.
      for (idf_ext_iterator<BasicBlock*, std::set<BasicBlock*> >
             DI = idf_ext_begin(U.getInstruction()->getParent(), LiveBlocks),
             DE = idf_ext_end(U.getInstruction()->getParent(), LiveBlocks);
           DI != DE; ++DI)
        /* empty */;
    }
  }
}

/// InitializeAndDestroyPools- This inserts calls to poolinit and pooldestroy
/// into the function to initialize and destroy one pool.
///
void PoolAllocate::InitializeAndDestroyPool(Function &F, const DSNode *Node,
                          std::map<const DSNode*, Value*> &PoolDescriptors,
                          std::multimap<AllocaInst*, Instruction*> &PoolUses,
                          std::multimap<AllocaInst*, CallInst*> &PoolFrees) {
  AllocaInst *PD = cast<AllocaInst>(PoolDescriptors[Node]);

  // Convert the PoolUses/PoolFrees sets into something specific to this pool: a
  // set of which blocks are immediately using the pool.
  std::set<BasicBlock*> UsingBlocks;
    
  std::multimap<AllocaInst*, Instruction*>::iterator PUI, PUE;
  tie(PUI, PUE) = PoolUses.equal_range(PD);
  for (; PUI != PUE; ++PUI)
    UsingBlocks.insert(PUI->second->getParent());
    
  // To calculate all of the basic blocks which require the pool to be
  // initialized before, do a depth first search on the CFG from the using
  // blocks.
  std::set<BasicBlock*> InitializedBefore;
  std::set<BasicBlock*> DestroyedAfter;
  for (std::set<BasicBlock*>::iterator I = UsingBlocks.begin(),
         E = UsingBlocks.end(); I != E; ++I) {
    for (df_ext_iterator<BasicBlock*, std::set<BasicBlock*> >
           DI = df_ext_begin(*I, InitializedBefore),
           DE = df_ext_end(*I, InitializedBefore); DI != DE; ++DI)
      /* empty */;
      
    for (idf_ext_iterator<BasicBlock*, std::set<BasicBlock*> >
           DI = idf_ext_begin(*I, DestroyedAfter),
           DE = idf_ext_end(*I, DestroyedAfter); DI != DE; ++DI)
      /* empty */;
  }
  // Now that we have created the sets, intersect them.
  std::set<BasicBlock*> LiveBlocks;
  std::set_intersection(InitializedBefore.begin(),InitializedBefore.end(),
                        DestroyedAfter.begin(), DestroyedAfter.end(),
                        std::inserter(LiveBlocks, LiveBlocks.end()));
  InitializedBefore.clear();
  DestroyedAfter.clear();
    
  DEBUG(errs() << "POOL: " << PD->getName().str() << " information:\n");
  DEBUG(errs() << "  Live in blocks: ");
  DEBUG(for (std::set<BasicBlock*>::iterator I = LiveBlocks.begin(),
               E = LiveBlocks.end(); I != E; ++I)
          errs() << (*I)->getName().str() << " ");
  DEBUG(errs() << "\n");
    
 
  std::vector<Instruction*> PoolInitPoints;
  std::vector<Instruction*> PoolDestroyPoints;

  if (DisableInitDestroyOpt) {
    // Insert poolinit calls after all of the allocas...
    Instruction *InsertPoint;
    for (BasicBlock::iterator I = F.front().begin();
         isa<AllocaInst>(InsertPoint = I); ++I)
      /*empty*/;
    PoolInitPoints.push_back(InsertPoint);

    if (F.getName().str() != "main")
      for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
        if (isa<ReturnInst>(BB->getTerminator()) ||
            isa<ResumeInst>(BB->getTerminator()))
          PoolDestroyPoints.push_back(BB->getTerminator());
  } else {
    // Keep track of the blocks we have inserted poolinit/destroy into.
    std::set<BasicBlock*> PoolInitInsertedBlocks, PoolDestroyInsertedBlocks;
    
    for (std::set<BasicBlock*>::iterator I = LiveBlocks.begin(),
           E = LiveBlocks.end(); I != E; ++I) {
      BasicBlock *BB = *I;
      TerminatorInst *Term = BB->getTerminator();
      
      // Check the predecessors of this block.  If any preds are not in the
      // set, or if there are no preds, insert a pool init.
      bool AllIn, NoneIn;
      AllOrNoneInSet(pred_begin(BB), pred_end(BB), LiveBlocks, AllIn,
                     NoneIn);
      
      if (NoneIn) {
        if (!PoolInitInsertedBlocks.count(BB)) {
          BasicBlock::iterator It = BB->begin();
          while (isa<AllocaInst>(It) || isa<PHINode>(It)) ++It;
#if 0
          // Move through all of the instructions not in the pool
          while (!PoolUses.count(std::make_pair(PD, It)))
            // Advance past non-users deleting any pool frees that we run
            // across.
            DeleteIfIsPoolFree(It++, PD, PoolFrees);
#endif
          PoolInitPoints.push_back(It);
          PoolInitInsertedBlocks.insert(BB);
        }
      } else if (!AllIn) {
      TryAgainPred:
        for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E;
             ++PI)
          if (!LiveBlocks.count(*PI) && !PoolInitInsertedBlocks.count(*PI)){
            if (SplitCriticalEdge(BB, PI))
              // If the critical edge was split, *PI was invalidated
              goto TryAgainPred;
            
            // Insert at the end of the predecessor, before the terminator.
            PoolInitPoints.push_back((*PI)->getTerminator());
            PoolInitInsertedBlocks.insert(*PI);
          }
      }
      // Check the successors of this block.  If some succs are not in the
      // set, insert destroys on those successor edges.  If all succs are
      // not in the set, insert a destroy in this block.
      AllOrNoneInSet(succ_begin(BB), succ_end(BB), LiveBlocks,
                     AllIn, NoneIn);
      
      if (NoneIn) {
        // Insert before the terminator.
        if (!PoolDestroyInsertedBlocks.count(BB)) {
          BasicBlock::iterator It = Term;
          
          // Rewind to the first using instruction.
#if 0
          while (!PoolUses.count(std::make_pair(PD, It)))
            DeleteIfIsPoolFree(It--, PD, PoolFrees);
          ++It;
#endif
     
          // Insert after the first using instruction
          PoolDestroyPoints.push_back(It);
          PoolDestroyInsertedBlocks.insert(BB);
        }
      } else if (!AllIn) {
        for (succ_iterator SI = succ_begin(BB), E = succ_end(BB);
             SI != E; ++SI)
          if (!LiveBlocks.count(*SI) &&
              !PoolDestroyInsertedBlocks.count(*SI)) {
            // If this edge is critical, split it.
            SplitCriticalEdge(BB, SI);
            
            // Insert at entry to the successor, but after any PHI nodes.
            BasicBlock::iterator It = (*SI)->begin();
            while (isa<PHINode>(It)) ++It;
            PoolDestroyPoints.push_back(It);
            PoolDestroyInsertedBlocks.insert(*SI);
          }
      }
    }
  }

  DEBUG(errs() << "  Init in blocks: ");

  // Insert the calls to initialize the pool.
  unsigned ElSizeV = Heuristic::getRecommendedSize(Node);
  Value *ElSize = ConstantInt::get(Int32Type, ElSizeV);
  unsigned AlignV = Heuristic::getRecommendedAlignment(Node);
  Value *Align  = ConstantInt::get(Int32Type, AlignV);

  for (unsigned i = 0, e = PoolInitPoints.size(); i != e; ++i) {
    Value* Opts[3] = {PD, ElSize, Align};
    CallInst::Create(PoolInit, Opts,  "", PoolInitPoints[i]);
    DEBUG(errs() << PoolInitPoints[i]->getParent()->getName().str() << " ");
  }

  DEBUG(errs() << "\n  Destroy in blocks: ");

  // Loop over all of the places to insert pooldestroy's...
  for (unsigned i = 0, e = PoolDestroyPoints.size(); i != e; ++i) {
    // Insert the pooldestroy call for this pool.
    CallInst::Create(PoolDestroy, PD, "", PoolDestroyPoints[i]);
    DEBUG(errs() << PoolDestroyPoints[i]->getParent()->getName().str()<<" ");
  }
  DEBUG(errs() << "\n\n");

  // We are allowed to delete any poolfree's which occur between the last
  // call to poolalloc, and the call to pooldestroy.  Figure out which
  // basic blocks have this property for this pool.
  std::set<BasicBlock*> PoolFreeLiveBlocks;
  if (!DisablePoolFreeOpt)
    CalculateLivePoolFreeBlocks(PoolFreeLiveBlocks, PD);
  else
    PoolFreeLiveBlocks = LiveBlocks;

  // Delete any pool frees which are not in live blocks, for correctness.
  std::multimap<AllocaInst*, CallInst*>::iterator PFI, PFE;
  for (tie(PFI,PFE) = PoolFrees.equal_range(PD); PFI != PFE; ) {
    CallInst *PoolFree = (PFI++)->second;
    if (!LiveBlocks.count(PoolFree->getParent()) ||
        !PoolFreeLiveBlocks.count(PoolFree->getParent()))
      DeleteIfIsPoolFree(PoolFree, PD, PoolFrees);
  }
}


/// InitializeAndDestroyPools - This inserts calls to poolinit and pooldestroy
/// into the function to initialize and destroy the pools in the NodesToPA list.
///
void PoolAllocate::InitializeAndDestroyPools(Function &F,
                               const std::vector<const DSNode*> &NodesToPA,
                          std::map<const DSNode*, Value*> &PoolDescriptors,
                          std::multimap<AllocaInst*, Instruction*> &PoolUses,
                          std::multimap<AllocaInst*, CallInst*> &PoolFrees) {
  std::set<AllocaInst*> AllocasHandled;

  // Insert all of the poolinit/destroy calls into the function.
  for (unsigned i = 0, e = NodesToPA.size(); i != e; ++i) {
    const DSNode *Node = NodesToPA[i];

    if (isa<GlobalVariable>(PoolDescriptors[Node]) ||
        isa<ConstantPointerNull>(PoolDescriptors[Node]))
      continue;

    assert(isa<AllocaInst>(PoolDescriptors[Node]) && "Why pool allocate this?");
    AllocaInst *PD = cast<AllocaInst>(PoolDescriptors[Node]);
    
    //
    // FIXME: What is the purpose of the PoolUses and AllocasHandled code
    //        below?
    // FIXME: Turn this into an assert and fix the problem!!
    //assert(PoolUses.count(PD) && "Pool is not used, but is marked heap?!");
    if (!PoolUses.count(PD) && !PoolFrees.count(PD)) continue;
    if (!AllocasHandled.insert(PD).second) continue;
    
    ++NumPools;
    if (!Node->isNodeCompletelyFolded())
      ++NumTSPools;
    
    InitializeAndDestroyPool(F, Node, PoolDescriptors, PoolUses, PoolFrees);
  }
}

//
// Function: getNumInitialPoolArguments()
//
// Description:
//  This function determines if the specified function has inital pool arguments
//  that should be replaced, and if so, returns the numbers of initial pool arguments
//  to replace.
//
// Inputs:
//  funcname - A reference to a string containing the name of the function.
//
// Return value:
//  0 - The function does not have any initial pool arguments to replace.
//  Otherwise, the number of initial pool arguments to replace.
//
unsigned PoolAllocate::getNumInitialPoolArguments(StringRef FuncName) {
  const unsigned EntryCount =
    sizeof(RuntimeCheckEntries) / sizeof(RuntimeCheckEntries[0]);

  for (unsigned Index = 0; Index < EntryCount; ++Index) {

    if (RuntimeCheckEntries[Index].Function == FuncName)
      return RuntimeCheckEntries[Index].PoolArgc;

    else if (RuntimeCheckEntries[Index].CheckKind == CStdLibCheck) {
      // Check for _debug() versions of CStdLib functions.
      std::string DebugName =
        RuntimeCheckEntries[Index].Function + std::string("_debug");

      if (DebugName == FuncName)
        return RuntimeCheckEntries[Index].PoolArgc;
    }
  }
  
  return 0;
}
