[llvm-commits] CVS: poolalloc/lib/PoolAllocate/TransformFunctionBody.cpp PoolAllocate.cpp

Chris Lattner lattner at cs.uiuc.edu
Sun Nov 9 16:15:01 PST 2003


Changes in directory poolalloc/lib/PoolAllocate:

TransformFunctionBody.cpp added (r1.1)
PoolAllocate.cpp updated: 1.32 -> 1.33

---
Log message:

Split all of the low-level function transforming code out into a new file
Preparing to implement the poolinit/pooldestroy movement optimization


---
Diffs of the changes:  (+736 -702)

Index: poolalloc/lib/PoolAllocate/TransformFunctionBody.cpp
diff -c /dev/null poolalloc/lib/PoolAllocate/TransformFunctionBody.cpp:1.1
*** /dev/null	Sun Nov  9 16:14:17 2003
--- poolalloc/lib/PoolAllocate/TransformFunctionBody.cpp	Sun Nov  9 16:14:07 2003
***************
*** 0 ****
--- 1,689 ----
+ //===-- TransformFunctionBody.cpp - Pool Function Transformer -------------===//
+ //
+ // This file defines the PoolAllocate::TransformBody method.
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #define DEBUG_TYPE "PoolAllocation"
+ #include "poolalloc/PoolAllocate.h"
+ #include "llvm/Analysis/DataStructure.h"
+ #include "llvm/Analysis/DSGraph.h"
+ #include "llvm/Function.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/Debug.h"
+ #include "Support/VectorExtras.h"
+ using namespace PA;
+ 
+ namespace {
+   /// FuncTransform - This class implements transformation required of pool
+   /// allocated functions.
+   struct FuncTransform : public InstVisitor<FuncTransform> {
+     PoolAllocate &PAInfo;
+     DSGraph &G;      // The Bottom-up DS Graph
+     DSGraph &TDG;    // The Top-down DS Graph
+     FuncInfo &FI;
+ 
+     // PoolUses - For each pool (identified by the pool descriptor) keep track
+     // of which blocks require the memory in the pool to not be freed.  This
+     // does not include poolfree's.
+     std::set<Value*, BasicBlock*> &PoolUses;
+ 
+     // PoolDestroys - For each pool, keep track of the actual poolfree calls
+     // inserted into the code.  This is seperated out from PoolUses.
+     std::set<Value*, CallInst*>   &PoolFrees;
+ 
+     FuncTransform(PoolAllocate &P, DSGraph &g, DSGraph &tdg, FuncInfo &fi,
+                   std::set<Value*, BasicBlock*> &poolUses,
+                   std::set<Value*, CallInst*> &poolFrees)
+       : PAInfo(P), G(g), TDG(tdg), FI(fi),
+         PoolUses(poolUses), PoolFrees(poolFrees) {
+     }
+ 
+     void visitMallocInst(MallocInst &MI);
+     void visitFreeInst(FreeInst &FI);
+     void visitCallSite(CallSite CS);
+     void visitCallInst(CallInst &CI) { visitCallSite(&CI); }
+     void visitInvokeInst(InvokeInst &II) { visitCallSite(&II); }
+     
+     // The following instructions are never modified by pool allocation
+     void visitBranchInst(BranchInst &I) { }
+     void visitUnwindInst(UnwindInst &I) { }
+     void visitBinaryOperator(Instruction &I) { }
+     void visitShiftInst (ShiftInst &I) { }
+     void visitSwitchInst (SwitchInst &I) { }
+     void visitCastInst (CastInst &I) { }
+     void visitAllocaInst(AllocaInst &I) { }
+     void visitLoadInst(LoadInst &I) { }
+     void visitGetElementPtrInst (GetElementPtrInst &I) { }
+ 
+     void visitReturnInst(ReturnInst &I);
+     void visitStoreInst (StoreInst &I);
+     void visitPHINode(PHINode &I);
+ 
+     void visitVAArgInst(VAArgInst &I) { }
+     void visitVANextInst(VANextInst &I) { }
+ 
+     void visitInstruction(Instruction &I) {
+       std::cerr << "PoolAllocate does not recognize this instruction:\n" << I;
+       abort();
+     }
+ 
+   private:
+     DSNodeHandle& getDSNodeHFor(Value *V) {
+       if (!FI.NewToOldValueMap.empty()) {
+         // If the NewToOldValueMap is in effect, use it.
+         std::map<Value*,const Value*>::iterator I = FI.NewToOldValueMap.find(V);
+         if (I != FI.NewToOldValueMap.end())
+           V = (Value*)I->second;
+       }
+ 
+       return G.getScalarMap()[V];
+     }
+ 
+     DSNodeHandle& getTDDSNodeHFor(Value *V) {
+       if (!FI.NewToOldValueMap.empty()) {
+         // If the NewToOldValueMap is in effect, use it.
+         std::map<Value*,const Value*>::iterator I = FI.NewToOldValueMap.find(V);
+         if (I != FI.NewToOldValueMap.end())
+           V = (Value*)I->second;
+       }
+ 
+       return TDG.getScalarMap()[V];
+     }
+ 
+     Value *getPoolHandle(Value *V) {
+       DSNode *Node = getDSNodeHFor(V).getNode();
+       // Get the pool handle for this DSNode...
+       std::map<DSNode*, Value*>::iterator I = FI.PoolDescriptors.find(Node);
+ 
+       if (I != FI.PoolDescriptors.end()) {
+ 	// Check that the node pointed to by V in the TD DS graph is not
+ 	// collapsed
+ 	DSNode *TDNode = getTDDSNodeHFor(V).getNode();
+ 	if (TDNode->getType() != Type::VoidTy)
+ 	  return I->second;
+ 	else {
+ 	  PAInfo.CollapseFlag = 1;
+ 	  return 0;
+ 	}
+       }
+       else
+ 	return 0;
+ 	  
+     }
+     
+     bool isFuncPtr(Value *V);
+ 
+     Function* getFuncClass(Value *V);
+ 
+     Value* retCloneIfFunc(Value *V);
+   };
+ }
+ 
+ void PoolAllocate::TransformBody(DSGraph &g, DSGraph &tdg, PA::FuncInfo &fi,
+                                  std::set<Value*, BasicBlock*> &poolUses,
+                                  std::set<Value*, CallInst*> &poolFrees,
+                                  Function &F) {
+   FuncTransform(*this, g, tdg, fi, poolUses, poolFrees).visit(F);
+ }
+ 
+ 
+ // Returns true if V is a function pointer
+ bool FuncTransform::isFuncPtr(Value *V) {
+   if (const PointerType *PTy = dyn_cast<PointerType>(V->getType()))
+      return isa<FunctionType>(PTy->getElementType());
+   return false;
+ }
+ 
+ // Given a function pointer, return the function eq. class if one exists
+ Function* FuncTransform::getFuncClass(Value *V) {
+   // Look at DSGraph and see if the set of of functions it could point to
+   // are pool allocated.
+ 
+   if (!isFuncPtr(V))
+     return 0;
+ 
+   // Two cases: 
+   // if V is a constant
+   if (Function *theFunc = dyn_cast<Function>(V)) {
+     if (!PAInfo.FuncECs.findClass(theFunc))
+       // If this function does not belong to any equivalence class
+       return 0;
+     if (PAInfo.EqClass2LastPoolArg.count(PAInfo.FuncECs.findClass(theFunc)))
+       return PAInfo.FuncECs.findClass(theFunc);
+     else
+       return 0;
+   }
+ 
+   // if V is not a constant
+   DSNode *DSN = TDG.getNodeForValue(V).getNode();
+   if (!DSN) {
+     return 0;
+   }
+   const std::vector<GlobalValue*> &Callees = DSN->getGlobals();
+   if (Callees.size() > 0) {
+     Function *calledF = dyn_cast<Function>(*Callees.begin());
+     assert(PAInfo.FuncECs.findClass(calledF) && "should exist in some eq. class");
+     if (PAInfo.EqClass2LastPoolArg.count(PAInfo.FuncECs.findClass(calledF)))
+       return PAInfo.FuncECs.findClass(calledF);
+   }
+ 
+   return 0;
+ }
+ 
+ // Returns the clone if  V is a static function (not a pointer) and belongs 
+ // to an equivalence class i.e. is pool allocated
+ Value* FuncTransform::retCloneIfFunc(Value *V) {
+   if (Function *fixedFunc = dyn_cast<Function>(V))
+     if (getFuncClass(V))
+       return PAInfo.getFuncInfo(*fixedFunc)->Clone;
+   
+   return 0;
+ }
+ 
+ void FuncTransform::visitReturnInst (ReturnInst &RI) {
+   if (RI.getNumOperands())
+     if (Value *clonedFunc = retCloneIfFunc(RI.getOperand(0))) {
+       // Cast the clone of RI.getOperand(0) to the non-pool-allocated type
+       CastInst *CastI = new CastInst(clonedFunc, RI.getOperand(0)->getType(), 
+ 				     "tmp", &RI);
+       // Insert return instruction that returns the casted value
+       ReturnInst *RetI = new ReturnInst(CastI, &RI);
+ 
+       // Remove original return instruction
+       RI.getParent()->getInstList().erase(&RI);
+ 
+       if (!FI.NewToOldValueMap.empty()) {
+ 	std::map<Value*,const Value*>::iterator II =
+ 	  FI.NewToOldValueMap.find(&RI);
+ 	assert(II != FI.NewToOldValueMap.end() && 
+ 	       "RI not found in clone?");
+ 	FI.NewToOldValueMap.insert(std::make_pair(RetI, II->second));
+ 	FI.NewToOldValueMap.erase(II);
+       }
+     }
+ }
+ 
+ void FuncTransform::visitStoreInst (StoreInst &SI) {
+   // Check if a constant function is being stored
+   if (Value *clonedFunc = retCloneIfFunc(SI.getOperand(0))) {
+     CastInst *CastI = new CastInst(clonedFunc, SI.getOperand(0)->getType(), 
+ 				   "tmp", &SI);
+     StoreInst *StoreI = new StoreInst(CastI, SI.getOperand(1), &SI);
+     SI.getParent()->getInstList().erase(&SI);
+     
+     // Update the NewToOldValueMap if this is a clone
+     if (!FI.NewToOldValueMap.empty()) {
+       std::map<Value*,const Value*>::iterator II =
+ 	FI.NewToOldValueMap.find(&SI);
+       assert(II != FI.NewToOldValueMap.end() && 
+ 	     "SI not found in clone?");
+       FI.NewToOldValueMap.insert(std::make_pair(StoreI, II->second));
+       FI.NewToOldValueMap.erase(II);
+     }
+   }
+ }
+ 
+ void FuncTransform::visitPHINode(PHINode &PI) {
+   // If any of the operands of the PHI node is a constant function pointer
+   // that is cloned, the cast instruction has to be inserted at the end of the
+   // previous basic block
+   
+   if (isFuncPtr(&PI)) {
+     PHINode *V = new PHINode(PI.getType(), PI.getName(), &PI);
+     for (unsigned i = 0 ; i < PI.getNumIncomingValues(); ++i) {
+       if (Value *clonedFunc = retCloneIfFunc(PI.getIncomingValue(i))) {
+ 	// Insert CastInst at the end of  PI.getIncomingBlock(i)
+ 	BasicBlock::iterator BBI = --PI.getIncomingBlock(i)->end();
+ 	// BBI now points to the terminator instruction of the basic block.
+ 	CastInst *CastI = new CastInst(clonedFunc, PI.getType(), "tmp", BBI);
+ 	V->addIncoming(CastI, PI.getIncomingBlock(i));
+       } else {
+ 	V->addIncoming(PI.getIncomingValue(i), PI.getIncomingBlock(i));
+       }
+       
+     }
+     PI.replaceAllUsesWith(V);
+     PI.getParent()->getInstList().erase(&PI);
+     
+     DSGraph::ScalarMapTy &SM = G.getScalarMap();
+     DSGraph::ScalarMapTy::iterator PII = SM.find(&PI); 
+ 
+     // Update Scalar map of DSGraph if this is one of the original functions
+     // Otherwise update the NewToOldValueMap
+     if (PII != SM.end()) {
+       SM.insert(std::make_pair(V, PII->second));
+       SM.erase(PII);                     // Destroy the PHINode
+     } else {
+       std::map<Value*,const Value*>::iterator II =
+ 	FI.NewToOldValueMap.find(&PI);
+       assert(II != FI.NewToOldValueMap.end() && 
+ 	     "PhiI not found in clone?");
+       FI.NewToOldValueMap.insert(std::make_pair(V, II->second));
+       FI.NewToOldValueMap.erase(II);
+     }
+   }
+ }
+ 
+ void FuncTransform::visitMallocInst(MallocInst &MI) {
+   // Get the pool handle for the node that this contributes to...
+   Value *PH = getPoolHandle(&MI);
+   
+   // NB: PH is zero even if the node is collapsed
+   if (PH == 0) return;
+ 
+   std::string Name = MI.getName(); MI.setName("");
+ 
+   // Insert a call to poolalloc
+   TargetData &TD = PAInfo.getAnalysis<TargetData>();
+   Value *AllocSize =
+     ConstantUInt::get(Type::UIntTy, TD.getTypeSize(MI.getAllocatedType()));
+ 
+   if (MI.isArrayAllocation())
+     AllocSize = BinaryOperator::create(Instruction::Mul, AllocSize,
+                                        MI.getOperand(0), "sizetmp", &MI);
+ 
+   Value *V = new CallInst(PAInfo.PoolAlloc, make_vector(PH, AllocSize, 0),
+                           Name, &MI);
+ 
+   const Type *phtype = MI.getType()->getElementType();
+   std::map<const Value*, const Type*> &PoolDescType = FI.PoolDescType;
+   if (!PoolDescType.count(PH))
+     PoolDescType[PH] = phtype;
+ 
+   Value *Casted = V;
+ 
+   // Cast to the appropriate type if necessary
+   if (V->getType() != MI.getType())
+     Casted = new CastInst(V, MI.getType(), V->getName(), &MI);
+     
+   // Update def-use info
+   MI.replaceAllUsesWith(Casted);
+ 
+   // Remove old malloc instruction
+   MI.getParent()->getInstList().erase(&MI);
+   
+   DSGraph::ScalarMapTy &SM = G.getScalarMap();
+   DSGraph::ScalarMapTy::iterator MII = SM.find(&MI);
+   
+   // If we are modifying the original function, update the DSGraph... 
+   if (MII != SM.end()) {
+     // V and Casted now point to whatever the original malloc did...
+     SM.insert(std::make_pair(V, MII->second));
+     if (V != Casted)
+       SM.insert(std::make_pair(Casted, MII->second));
+     SM.erase(MII);                     // The malloc is now destroyed
+   } else {             // Otherwise, update the NewToOldValueMap
+     std::map<Value*,const Value*>::iterator MII =
+       FI.NewToOldValueMap.find(&MI);
+     assert(MII != FI.NewToOldValueMap.end() && "MI not found in clone?");
+     FI.NewToOldValueMap.insert(std::make_pair(V, MII->second));
+     if (V != Casted)
+       FI.NewToOldValueMap.insert(std::make_pair(Casted, MII->second));
+     FI.NewToOldValueMap.erase(MII);
+   }
+ }
+ 
+ void FuncTransform::visitFreeInst(FreeInst &FrI) {
+   Value *Arg = FrI.getOperand(0);
+   Value *PH = getPoolHandle(Arg);  // Get the pool handle for this DSNode...
+   if (PH == 0) return;
+ 
+   const Type *phtype = 0;
+   if (const PointerType * ptype = dyn_cast<PointerType>(Arg->getType())) {
+     phtype = ptype->getElementType();
+   }
+   assert((phtype != 0) && "Needs to be implemented \n ");
+   std::map<const Value*, const Type*> &PoolDescType = FI.PoolDescType;
+   if (!PoolDescType.count(PH))
+     PoolDescType[PH] = phtype;
+   
+   // Insert a cast and a call to poolfree...
+   Value *Casted = Arg;
+   if (Arg->getType() != PointerType::get(Type::SByteTy))
+     Casted = new CastInst(Arg, PointerType::get(Type::SByteTy),
+ 				 Arg->getName()+".casted", &FrI);
+ 
+   CallInst *FreeI = new CallInst(PAInfo.PoolFree, make_vector(PH, Casted, 0), 
+ 				 "", &FrI);
+   // Delete the now obsolete free instruction...
+   FrI.getParent()->getInstList().erase(&FrI);
+   
+   // Update the NewToOldValueMap if this is a clone
+   if (!FI.NewToOldValueMap.empty()) {
+     std::map<Value*,const Value*>::iterator II =
+       FI.NewToOldValueMap.find(&FrI);
+     assert(II != FI.NewToOldValueMap.end() && 
+ 	   "FrI not found in clone?");
+     FI.NewToOldValueMap.insert(std::make_pair(FreeI, II->second));
+     FI.NewToOldValueMap.erase(II);
+   }
+ }
+ 
+ static void CalcNodeMapping(DSNodeHandle& Caller, DSNodeHandle& Callee,
+                             std::map<DSNode*, DSNode*> &NodeMapping) {
+   DSNode *CalleeNode = Callee.getNode();
+   DSNode *CallerNode = Caller.getNode();
+ 
+   unsigned CalleeOffset = Callee.getOffset();
+   unsigned CallerOffset = Caller.getOffset();
+ 
+   if (CalleeNode == 0) return;
+ 
+   // If callee has a node and caller doesn't, then a constant argument was
+   // passed by the caller
+   if (CallerNode == 0) {
+     NodeMapping.insert(NodeMapping.end(), std::make_pair(CalleeNode, 
+ 							 (DSNode *) 0));
+   }
+ 
+   // Map the callee node to the caller node. 
+   // NB: The callee node could be of a different type. Eg. if it points to the
+   // field of a struct that the caller points to
+   std::map<DSNode*, DSNode*>::iterator I = NodeMapping.find(CalleeNode);
+   if (I != NodeMapping.end()) {   // Node already in map...
+     assert(I->second == CallerNode && 
+ 	   "Node maps to different nodes on paths?");
+   } else {
+     NodeMapping.insert(I, std::make_pair(CalleeNode, CallerNode));
+     
+     if (CalleeNode->getType() != CallerNode->getType() && CallerOffset == 0) 
+       DEBUG(std::cerr << "NB: Mapping of nodes between different types\n");
+ 
+     // Recursively map the callee links to the caller links starting from the
+     // offset in the node into which they are mapped.
+     // Being a BU Graph, the callee ought to have smaller number of links unless
+     // there is collapsing in the caller
+     unsigned numCallerLinks = CallerNode->getNumLinks() - CallerOffset;
+     unsigned numCalleeLinks = CalleeNode->getNumLinks() - CalleeOffset;
+     
+     if (numCallerLinks > 0) {
+       if (numCallerLinks < numCalleeLinks) {
+ 	DEBUG(std::cerr << "Potential node collapsing in caller\n");
+ 	for (unsigned i = 0, e = numCalleeLinks; i != e; ++i)
+ 	  CalcNodeMapping(CallerNode->getLink(((i%numCallerLinks) << DS::PointerShift) + CallerOffset),
+                           CalleeNode->getLink((i << DS::PointerShift) + CalleeOffset), NodeMapping);
+       } else {
+ 	for (unsigned i = 0, e = numCalleeLinks; i != e; ++i)
+ 	  CalcNodeMapping(CallerNode->getLink((i << DS::PointerShift) + CallerOffset),
+                           CalleeNode->getLink((i << DS::PointerShift) + CalleeOffset), NodeMapping);
+       }
+     } else if (numCalleeLinks > 0) {
+       DEBUG(std::cerr << 
+ 	    "Caller has unexpanded node, due to indirect call perhaps!\n");
+     }
+   }
+ }
+ 
+ void FuncTransform::visitCallSite(CallSite CS) {
+   Function *CF = CS.getCalledFunction();
+   Instruction *TheCall = CS.getInstruction();
+ 
+   // optimization for function pointers that are basically gotten from a cast
+   // with only one use and constant expressions with casts in them
+   if (!CF) {
+     Value *CV = CS.getCalledValue();
+     if (CastInst* CastI = dyn_cast<CastInst>(CV)) {
+       if (isa<Function>(CastI->getOperand(0)) && 
+ 	  CastI->getOperand(0)->getType() == CastI->getType())
+ 	CF = dyn_cast<Function>(CastI->getOperand(0));
+     } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
+       if (CE->getOpcode() == Instruction::Cast)
+ 	if (ConstantPointerRef *CPR
+             = dyn_cast<ConstantPointerRef>(CE->getOperand(0)))
+           CF = dyn_cast<Function>(CPR->getValue());
+     }
+   }
+ 
+   DSGraph &CallerG = G;
+ 
+   std::vector<Value*> Args;  
+ 
+   // We need to figure out which local pool descriptors correspond to the pool
+   // descriptor arguments passed into the function call.  Calculate a mapping
+   // from callee DSNodes to caller DSNodes.  We construct a partial isomophism
+   // between the graphs to figure out which pool descriptors need to be passed
+   // in.  The roots of this mapping is found from arguments and return values.
+   //
+   std::map<DSNode*, DSNode*> NodeMapping;
+ 
+   if (!CF) {   // Indirect call
+     DEBUG(std::cerr << "  Handling call: " << *TheCall);
+     
+     std::map<unsigned, Value*> PoolArgs;
+     Function *FuncClass;
+     
+     std::pair<std::multimap<CallSite, Function*>::iterator,
+               std::multimap<CallSite, Function*>::iterator> Targets =
+       PAInfo.CallSiteTargets.equal_range(CS);
+     for (std::multimap<CallSite, Function*>::iterator TFI = Targets.first,
+ 	   TFE = Targets.second; TFI != TFE; ++TFI) {
+       if (TFI == Targets.first) {
+ 	FuncClass = PAInfo.FuncECs.findClass(TFI->second);
+ 	// Nothing to transform if there are no pool arguments in this
+ 	// equivalence class of functions.
+ 	if (!PAInfo.EqClass2LastPoolArg.count(FuncClass))
+ 	  return;
+       }
+       
+       FuncInfo *CFI = PAInfo.getFuncInfo(*TFI->second);
+ 
+       if (!CFI->ArgNodes.size()) continue;  // Nothing to transform...
+       
+       DSGraph &CG = PAInfo.getBUDataStructures().getDSGraph(*TFI->second);  
+       
+       {
+         Function::aiterator FAI = TFI->second->abegin(),E = TFI->second->aend();
+         CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
+         for ( ; FAI != E && AI != AE; ++FAI, ++AI)
+           if (!isa<Constant>(*AI))
+             CalcNodeMapping(getDSNodeHFor(*AI), CG.getScalarMap()[FAI],
+                             NodeMapping);
+         assert(AI == AE && "Varargs calls not handled yet!");
+       }
+       
+       if (TheCall->getType() != Type::VoidTy)
+         CalcNodeMapping(getDSNodeHFor(TheCall),
+                         CG.getReturnNodeFor(*TFI->second), NodeMapping);
+       
+       // Map the nodes that are pointed to by globals.
+       // For all globals map getDSNodeForGlobal(g)->CG.getDSNodeForGlobal(g)
+       for (DSGraph::ScalarMapTy::iterator SMI = G.getScalarMap().begin(), 
+              SME = G.getScalarMap().end(); SMI != SME; ++SMI)
+         if (isa<GlobalValue>(SMI->first)) { 
+           CalcNodeMapping(SMI->second, 
+                           CG.getScalarMap()[SMI->first], NodeMapping);
+         }
+ 
+       unsigned idx = CFI->PoolArgFirst;
+ 
+       // The following loop determines the pool pointers corresponding to 
+       // CFI.
+       for (unsigned i = 0, e = CFI->ArgNodes.size(); i != e; ++i, ++idx) {
+         if (NodeMapping.count(CFI->ArgNodes[i])) {
+           assert(NodeMapping.count(CFI->ArgNodes[i]) && "Node not in mapping!");
+           DSNode *LocalNode = NodeMapping.find(CFI->ArgNodes[i])->second;
+           if (LocalNode) {
+             assert(FI.PoolDescriptors.count(LocalNode) &&
+                    "Node not pool allocated?");
+             PoolArgs[idx] = FI.PoolDescriptors.find(LocalNode)->second;
+           }
+           else
+             // LocalNode is null when a constant is passed in as a parameter
+             PoolArgs[idx] = Constant::getNullValue(PoolAllocate::PoolDescPtrTy);
+         } else {
+           PoolArgs[idx] = Constant::getNullValue(PoolAllocate::PoolDescPtrTy);
+         }
+       }
+     }
+     
+     // Push the pool arguments into Args.
+     if (PAInfo.EqClass2LastPoolArg.count(FuncClass)) {
+       for (int i = 0; i <= PAInfo.EqClass2LastPoolArg[FuncClass]; ++i) {
+         if (PoolArgs.find(i) != PoolArgs.end())
+           Args.push_back(PoolArgs[i]);
+         else
+           Args.push_back(Constant::getNullValue(PoolAllocate::PoolDescPtrTy));
+       }
+     
+       assert(Args.size()== (unsigned) PAInfo.EqClass2LastPoolArg[FuncClass] + 1
+              && "Call has same number of pool args as the called function");
+     }
+ 
+     // Add the rest of the arguments (the original arguments of the function)...
+     Args.insert(Args.end(), CS.arg_begin(), CS.arg_end());
+     
+     std::string Name = TheCall->getName(); TheCall->setName("");
+     
+     Value *NewCall;
+     Value *CalledValuePtr = CS.getCalledValue();
+     if (Args.size() > (unsigned)CS.arg_size()) {
+       // If there are any pool arguments
+       CalledValuePtr = new CastInst(CS.getCalledValue(), 
+                        PAInfo.getFuncInfo(*FuncClass)->Clone->getType(), "tmp", 
+                                     TheCall);
+     }
+ 
+     if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
+       NewCall = new InvokeInst(CalledValuePtr, II->getNormalDest(),
+                                II->getExceptionalDest(), Args, Name, TheCall);
+     } else {
+       NewCall = new CallInst(CalledValuePtr, Args, Name, TheCall);
+     }
+ 
+     TheCall->replaceAllUsesWith(NewCall);
+     DEBUG(std::cerr << "  Result Call: " << *NewCall);
+       
+     if (TheCall->getType() != Type::VoidTy) {
+       // If we are modifying the original function, update the DSGraph... 
+       DSGraph::ScalarMapTy &SM = G.getScalarMap();
+       DSGraph::ScalarMapTy::iterator CII = SM.find(TheCall);
+       if (CII != SM.end()) {
+ 	SM.insert(std::make_pair(NewCall, CII->second));
+ 	SM.erase(CII);                     // Destroy the CallInst
+       } else { 
+ 	// Otherwise update the NewToOldValueMap with the new CI return value
+ 	std::map<Value*,const Value*>::iterator CII = 
+ 	  FI.NewToOldValueMap.find(TheCall);
+ 	assert(CII != FI.NewToOldValueMap.end() && "CI not found in clone?");
+ 	FI.NewToOldValueMap.insert(std::make_pair(NewCall, CII->second));
+ 	FI.NewToOldValueMap.erase(CII);
+       }
+     } else if (!FI.NewToOldValueMap.empty()) {
+       std::map<Value*,const Value*>::iterator II =
+ 	FI.NewToOldValueMap.find(TheCall);
+       assert(II != FI.NewToOldValueMap.end() && 
+ 	     "CI not found in clone?");
+       FI.NewToOldValueMap.insert(std::make_pair(NewCall, II->second));
+       FI.NewToOldValueMap.erase(II);
+     }
+   } else {
+     FuncInfo *CFI = PAInfo.getFuncInfo(*CF);
+ 
+     if (CFI == 0 || CFI->Clone == 0) return;  // Nothing to transform...
+     
+     DEBUG(std::cerr << "  Handling call: " << *TheCall);
+     
+     DSGraph &CG = PAInfo.getBUDataStructures().getDSGraph(*CF);  // Callee graph
+ 
+     {
+       Function::aiterator FAI = CF->abegin(), E = CF->aend();
+       CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
+       for ( ; FAI != E && AI != AE; ++FAI, ++AI)
+         if (!isa<Constant>(*AI))
+           CalcNodeMapping(getDSNodeHFor(*AI), CG.getScalarMap()[FAI],
+                           NodeMapping);
+       assert(AI == AE && "Varargs calls not handled yet!");
+     }
+ 
+     // Map the return value as well...
+     if (TheCall->getType() != Type::VoidTy)
+       CalcNodeMapping(getDSNodeHFor(TheCall), CG.getReturnNodeFor(*CF),
+ 		      NodeMapping);
+ 
+     // Map the nodes that are pointed to by globals.
+     // For all globals map getDSNodeForGlobal(g)->CG.getDSNodeForGlobal(g)
+     for (DSGraph::ScalarMapTy::iterator SMI = G.getScalarMap().begin(), 
+ 	   SME = G.getScalarMap().end(); SMI != SME; ++SMI)
+       if (isa<GlobalValue>(SMI->first)) 
+ 	CalcNodeMapping(SMI->second, 
+ 			CG.getScalarMap()[SMI->first], NodeMapping);
+ 
+     // Okay, now that we have established our mapping, we can figure out which
+     // pool descriptors to pass in...
+ 
+     // Add an argument for each pool which must be passed in...
+     if (CFI->PoolArgFirst != 0) {
+       for (int i = 0; i < CFI->PoolArgFirst; ++i)
+ 	Args.push_back(Constant::getNullValue(PoolAllocate::PoolDescPtrTy));  
+     }
+ 
+     for (unsigned i = 0, e = CFI->ArgNodes.size(); i != e; ++i) {
+       if (NodeMapping.count(CFI->ArgNodes[i])) {
+ 
+ 	DSNode *LocalNode = NodeMapping.find(CFI->ArgNodes[i])->second;
+ 	if (LocalNode) {
+ 	  assert(FI.PoolDescriptors.count(LocalNode) &&
+                  "Node not pool allocated?");
+ 	  Args.push_back(FI.PoolDescriptors.find(LocalNode)->second);
+ 	} else
+ 	  Args.push_back(Constant::getNullValue(PoolAllocate::PoolDescPtrTy));
+       } else {
+ 	Args.push_back(Constant::getNullValue(PoolAllocate::PoolDescPtrTy));
+       }
+     }
+ 
+     Function *FuncClass = PAInfo.FuncECs.findClass(CF);
+     
+     if (PAInfo.EqClass2LastPoolArg.count(FuncClass))
+       for (int i = CFI->PoolArgLast; 
+ 	   i <= PAInfo.EqClass2LastPoolArg[FuncClass]; ++i)
+ 	Args.push_back(Constant::getNullValue(PoolAllocate::PoolDescPtrTy));
+ 
+     // Add the rest of the arguments...
+     Args.insert(Args.end(), CS.arg_begin(), CS.arg_end());
+     
+     std::string Name = TheCall->getName(); TheCall->setName("");
+ 
+     Value *NewCall;
+     if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
+       NewCall = new InvokeInst(CFI->Clone, II->getNormalDest(),
+                                II->getExceptionalDest(), Args, Name, TheCall);
+     } else {
+       NewCall = new CallInst(CFI->Clone, Args, Name, TheCall);
+     }
+ 
+     TheCall->replaceAllUsesWith(NewCall);
+     DEBUG(std::cerr << "  Result Call: " << *NewCall);
+ 
+     if (TheCall->getType() != Type::VoidTy) {
+       // If we are modifying the original function, update the DSGraph... 
+       DSGraph::ScalarMapTy &SM = G.getScalarMap();
+       DSGraph::ScalarMapTy::iterator CII = SM.find(TheCall); 
+       if (CII != SM.end()) {
+ 	SM.insert(std::make_pair(NewCall, CII->second));
+ 	SM.erase(CII);                     // Destroy the CallInst
+       } else { 
+ 	// Otherwise update the NewToOldValueMap with the new CI return value
+ 	std::map<Value*,const Value*>::iterator CNII = 
+ 	  FI.NewToOldValueMap.find(TheCall);
+ 	assert(CNII != FI.NewToOldValueMap.end() && CNII->second && 
+ 	       "CI not found in clone?");
+ 	FI.NewToOldValueMap.insert(std::make_pair(NewCall, CNII->second));
+ 	FI.NewToOldValueMap.erase(CNII);
+       }
+     } else if (!FI.NewToOldValueMap.empty()) {
+       std::map<Value*,const Value*>::iterator II =
+ 	FI.NewToOldValueMap.find(TheCall);
+       assert(II != FI.NewToOldValueMap.end() && "CI not found in clone?");
+       FI.NewToOldValueMap.insert(std::make_pair(NewCall, II->second));
+       FI.NewToOldValueMap.erase(II);
+     }
+   }
+ 
+   TheCall->getParent()->getInstList().erase(TheCall);
+ }


Index: poolalloc/lib/PoolAllocate/PoolAllocate.cpp
diff -u poolalloc/lib/PoolAllocate/PoolAllocate.cpp:1.32 poolalloc/lib/PoolAllocate/PoolAllocate.cpp:1.33
--- poolalloc/lib/PoolAllocate/PoolAllocate.cpp:1.32	Sat Nov  8 16:36:55 2003
+++ poolalloc/lib/PoolAllocate/PoolAllocate.cpp	Sun Nov  9 16:14:07 2003
@@ -10,17 +10,18 @@
 #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/DerivedTypes.h"
 #include "llvm/Instructions.h"
+#include "llvm/Module.h"
 #include "llvm/Target/TargetData.h"
-#include "llvm/Support/InstVisitor.h"
 #include "Support/Debug.h"
 #include "Support/VectorExtras.h"
 #include "Support/Statistic.h"
 using namespace PA;
 
+const Type *PoolAllocate::PoolDescPtrTy = 0;
+
 namespace {
   Statistic<> NumArgsAdded("poolalloc", "Number of function arguments added");
   Statistic<> NumCloned   ("poolalloc", "Number of functions cloned");
@@ -35,8 +36,6 @@
   //                        poolfree?)
   const Type *PoolDescType;
   
-  const PointerType *PoolDescPtr;
-  
   RegisterOpt<PoolAllocate>
   X("poolalloc", "Pool allocate disjoint data structures");
 }
@@ -131,7 +130,7 @@
     PoolDescType =
       StructType::get(make_vector<const Type*>(VoidPtrTy, VoidPtrTy,
                                                Type::UIntTy, Type::UIntTy, 0));
-    PoolDescPtr = PointerType::get(PoolDescType);
+    PoolDescPtrTy = PointerType::get(PoolDescType);
   }
   
   AddPoolPrototypes();
@@ -186,20 +185,20 @@
   
   // Get poolinit function...
   PoolInit = CurModule->getOrInsertFunction("poolinit", Type::VoidTy,
-                                            PoolDescPtr, Type::UIntTy, 0);
+                                            PoolDescPtrTy, Type::UIntTy, 0);
 
   // Get pooldestroy function...
   PoolDestroy = CurModule->getOrInsertFunction("pooldestroy", Type::VoidTy,
-                                               PoolDescPtr, 0);
+                                               PoolDescPtrTy, 0);
   
   // The poolalloc function
   PoolAlloc = CurModule->getOrInsertFunction("poolalloc", 
-                                             VoidPtrTy, PoolDescPtr,
+                                             VoidPtrTy, PoolDescPtrTy,
                                              Type::UIntTy, 0);
   
   // Get the poolfree function...
   PoolFree = CurModule->getOrInsertFunction("poolfree", Type::VoidTy,
-                                            PoolDescPtr, VoidPtrTy, 0);  
+                                            PoolDescPtrTy, VoidPtrTy, 0);  
 }
 
 // Inline the DSGraphs of functions corresponding to the potential targets at
@@ -371,7 +370,7 @@
     FI.ArgNodes.reserve(MarkedNodes.size());
     for (hash_set<DSNode*>::iterator I = MarkedNodes.begin(),
 	   E = MarkedNodes.end(); I != E; ++I) {
-      ArgTys.push_back(PoolDescPtr);      // Add the appropriate # of pool descs
+      ArgTys.push_back(PoolDescPtrTy);    // Add the appropriate # of pool descs
       FI.ArgNodes.push_back(*I);
     }
     if (FI.ArgNodes.empty()) return 0;      // No nodes to be pool allocated!
@@ -383,10 +382,8 @@
 		   EqClass2LastPoolArg[FuncECs.findClass(&F)] + 1);
     FI.ArgNodes.reserve(EqClass2LastPoolArg[FuncECs.findClass(&F)] + 1);
     
-    for (int i = 0; i <= EqClass2LastPoolArg[FuncECs.findClass(&F)]; ++i) {
-      ArgTys.push_back(PoolDescPtr);      // Add the appropriate # of pool 
-                                          // descs
-    }
+    for (int i = 0; i <= EqClass2LastPoolArg[FuncECs.findClass(&F)]; ++i)
+      ArgTys.push_back(PoolDescPtrTy);    // Add the appropriate # of pool descs
 
     for (hash_set<DSNode*>::iterator I = MarkedNodes.begin(),
 	   E = MarkedNodes.end(); I != E; ++I) {
@@ -484,41 +481,6 @@
 }
 
 
-// processFunction - Pool allocate any data structures which are contained in
-// the specified function...
-//
-void PoolAllocate::ProcessFunctionBody(Function &F, Function &NewF) {
-  DSGraph &G = BU->getDSGraph(F);
-
-  std::vector<DSNode*> &Nodes = G.getNodes();
-  if (Nodes.empty()) return;     // Quick exit if nothing to do...
-  
-  FuncInfo &FI = FunctionInfo[&F];   // Get FuncInfo for F
-  hash_set<DSNode*> &MarkedNodes = FI.MarkedNodes;
-  
-  DEBUG(std::cerr << "[" << F.getName() << "] Pool Allocate: ");
-  
-  // Loop over all of the nodes which are non-escaping, adding pool-allocatable
-  // ones to the NodesToPA vector.
-  std::vector<DSNode*> NodesToPA;
-  for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
-    if (Nodes[i]->isHeapNode() &&   // Pick nodes with heap elems
-        !MarkedNodes.count(Nodes[i]))              // Can't be marked
-      NodesToPA.push_back(Nodes[i]);
-  
-  DEBUG(std::cerr << NodesToPA.size() << " nodes to pool allocate\n");
-  if (!NodesToPA.empty()) {
-    // Create pool construction/destruction code
-    std::map<DSNode*, Value*> &PoolDescriptors = FI.PoolDescriptors;
-    std::map<const Value*, const Type*> &PoolDescTypeMap = FI.PoolDescType;
-    CreatePools(NewF, NodesToPA, PoolDescriptors, PoolDescTypeMap);
-  }
-  
-  // Transform the body of the function now...
-  TransformFunctionBody(NewF, F, G, FI);
-}
-
-
 // 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.
@@ -526,7 +488,8 @@
 void PoolAllocate::CreatePools(Function &F,
                                const std::vector<DSNode*> &NodesToPA,
                                std::map<DSNode*, Value*> &PoolDescriptors,
-			       std::map<const Value *, const Type *> &PoolDescTypeMap) {
+			       std::map<const Value *,
+                                        const Type *> &PoolDescTypeMap) {
   // Find all of the return nodes in the CFG...
   std::vector<BasicBlock*> ReturnNodes;
   for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
@@ -552,11 +515,10 @@
     if (Node->getType() != Type::VoidTy) {
       ElSize = ConstantUInt::get(Type::UIntTy, TD.getTypeSize(Node->getType()));
       Eltype = Node->getType();
-    }
-    else {
-      DEBUG(std::cerr << "Potential node collapsing in " << F.getName() 
-		<< ". All Data Structures may not be pool allocated\n");
-      ElSize = ConstantUInt::get(Type::UIntTy, 0);
+    } else {
+      std::cerr << "Node collapsing in '" << F.getName() 
+		<< "'. All Data Structures may not be pool allocated\n";
+      ElSize = ConstantUInt::get(Type::UIntTy, 1);
     }
     
     // Insert the call to initialize the pool...
@@ -575,658 +537,41 @@
 }
 
 
-namespace {
-  /// FuncTransform - This class implements transformation required of pool
-  /// allocated functions.
-  struct FuncTransform : public InstVisitor<FuncTransform> {
-    PoolAllocate &PAInfo;
-    DSGraph &G;      // The Bottom-up DS Graph
-    DSGraph &TDG;    // The Top-down DS Graph
-    FuncInfo &FI;
 
-    FuncTransform(PoolAllocate &P, DSGraph &g, DSGraph &tdg, FuncInfo &fi)
-      : PAInfo(P), G(g), TDG(tdg), FI(fi) {
-    }
-
-    void visitMallocInst(MallocInst &MI);
-    void visitFreeInst(FreeInst &FI);
-    void visitCallSite(CallSite CS);
-    void visitCallInst(CallInst &CI) { visitCallSite(&CI); }
-    void visitInvokeInst(InvokeInst &II) { visitCallSite(&II); }
-    
-    // The following instructions are never modified by pool allocation
-    void visitBranchInst(BranchInst &I) { }
-    void visitUnwindInst(UnwindInst &I) { }
-    void visitBinaryOperator(Instruction &I) { }
-    void visitShiftInst (ShiftInst &I) { }
-    void visitSwitchInst (SwitchInst &I) { }
-    void visitCastInst (CastInst &I) { }
-    void visitAllocaInst(AllocaInst &I) { }
-    void visitLoadInst(LoadInst &I) { }
-    void visitGetElementPtrInst (GetElementPtrInst &I) { }
-
-    void visitReturnInst(ReturnInst &I);
-    void visitStoreInst (StoreInst &I);
-    void visitPHINode(PHINode &I);
-
-    void visitVAArgInst(VAArgInst &I) { }
-    void visitVANextInst(VANextInst &I) { }
-
-    void visitInstruction(Instruction &I) {
-      std::cerr << "PoolAllocate does not recognize this instruction:\n" << I;
-      abort();
-    }
-
-  private:
-    DSNodeHandle& getDSNodeHFor(Value *V) {
-      //      if (isa<Constant>(V))
-      //	return DSNodeHandle();
-
-      if (!FI.NewToOldValueMap.empty()) {
-        // If the NewToOldValueMap is in effect, use it.
-        std::map<Value*,const Value*>::iterator I = FI.NewToOldValueMap.find(V);
-        if (I != FI.NewToOldValueMap.end())
-          V = (Value*)I->second;
-      }
-
-      return G.getScalarMap()[V];
-    }
-
-    DSNodeHandle& getTDDSNodeHFor(Value *V) {
-      if (!FI.NewToOldValueMap.empty()) {
-        // If the NewToOldValueMap is in effect, use it.
-        std::map<Value*,const Value*>::iterator I = FI.NewToOldValueMap.find(V);
-        if (I != FI.NewToOldValueMap.end())
-          V = (Value*)I->second;
-      }
-
-      return TDG.getScalarMap()[V];
-    }
-
-    Value *getPoolHandle(Value *V) {
-      DSNode *Node = getDSNodeHFor(V).getNode();
-      // Get the pool handle for this DSNode...
-      std::map<DSNode*, Value*>::iterator I = FI.PoolDescriptors.find(Node);
-
-      if (I != FI.PoolDescriptors.end()) {
-	// Check that the node pointed to by V in the TD DS graph is not
-	// collapsed
-	DSNode *TDNode = getTDDSNodeHFor(V).getNode();
-	if (TDNode->getType() != Type::VoidTy)
-	  return I->second;
-	else {
-	  PAInfo.CollapseFlag = 1;
-	  return 0;
-	}
-      }
-      else
-	return 0;
-	  
-    }
-    
-    bool isFuncPtr(Value *V);
-
-    Function* getFuncClass(Value *V);
-
-    Value* retCloneIfFunc(Value *V);
-  };
-}
-
-void PoolAllocate::TransformFunctionBody(Function &F, Function &OldF,
-                                         DSGraph &G, FuncInfo &FI) {
-  FuncTransform(*this, G, TDDS->getDSGraph(OldF), FI).visit(F);
-}
-
-// Returns true if V is a function pointer
-bool FuncTransform::isFuncPtr(Value *V) {
-  if (const PointerType *PTy = dyn_cast<PointerType>(V->getType()))
-     return isa<FunctionType>(PTy->getElementType());
-  return false;
-}
-
-// Given a function pointer, return the function eq. class if one exists
-Function* FuncTransform::getFuncClass(Value *V) {
-  // Look at DSGraph and see if the set of of functions it could point to
-  // are pool allocated.
-
-  if (!isFuncPtr(V))
-    return 0;
-
-  // Two cases: 
-  // if V is a constant
-  if (Function *theFunc = dyn_cast<Function>(V)) {
-    if (!PAInfo.FuncECs.findClass(theFunc))
-      // If this function does not belong to any equivalence class
-      return 0;
-    if (PAInfo.EqClass2LastPoolArg.count(PAInfo.FuncECs.findClass(theFunc)))
-      return PAInfo.FuncECs.findClass(theFunc);
-    else
-      return 0;
-  }
-
-  // if V is not a constant
-  DSNode *DSN = TDG.getNodeForValue(V).getNode();
-  if (!DSN) {
-    return 0;
-  }
-  const std::vector<GlobalValue*> &Callees = DSN->getGlobals();
-  if (Callees.size() > 0) {
-    Function *calledF = dyn_cast<Function>(*Callees.begin());
-    assert(PAInfo.FuncECs.findClass(calledF) && "should exist in some eq. class");
-    if (PAInfo.EqClass2LastPoolArg.count(PAInfo.FuncECs.findClass(calledF)))
-      return PAInfo.FuncECs.findClass(calledF);
-  }
-
-  return 0;
-}
+// processFunction - Pool allocate any data structures which are contained in
+// the specified function...
+//
+void PoolAllocate::ProcessFunctionBody(Function &F, Function &NewF) {
+  DSGraph &G = BU->getDSGraph(F);
 
-// Returns the clone if  V is a static function (not a pointer) and belongs 
-// to an equivalence class i.e. is pool allocated
-Value* FuncTransform::retCloneIfFunc(Value *V) {
-  if (Function *fixedFunc = dyn_cast<Function>(V))
-    if (getFuncClass(V))
-      return PAInfo.getFuncInfo(*fixedFunc)->Clone;
+  std::vector<DSNode*> &Nodes = G.getNodes();
+  if (Nodes.empty()) return;     // Quick exit if nothing to do...
   
-  return 0;
-}
-
-void FuncTransform::visitReturnInst (ReturnInst &RI) {
-  if (RI.getNumOperands())
-    if (Value *clonedFunc = retCloneIfFunc(RI.getOperand(0))) {
-      // Cast the clone of RI.getOperand(0) to the non-pool-allocated type
-      CastInst *CastI = new CastInst(clonedFunc, RI.getOperand(0)->getType(), 
-				     "tmp", &RI);
-      // Insert return instruction that returns the casted value
-      ReturnInst *RetI = new ReturnInst(CastI, &RI);
-
-      // Remove original return instruction
-      RI.getParent()->getInstList().erase(&RI);
-
-      if (!FI.NewToOldValueMap.empty()) {
-	std::map<Value*,const Value*>::iterator II =
-	  FI.NewToOldValueMap.find(&RI);
-	assert(II != FI.NewToOldValueMap.end() && 
-	       "RI not found in clone?");
-	FI.NewToOldValueMap.insert(std::make_pair(RetI, II->second));
-	FI.NewToOldValueMap.erase(II);
-      }
-    }
-}
-
-void FuncTransform::visitStoreInst (StoreInst &SI) {
-  // Check if a constant function is being stored
-  if (Value *clonedFunc = retCloneIfFunc(SI.getOperand(0))) {
-    CastInst *CastI = new CastInst(clonedFunc, SI.getOperand(0)->getType(), 
-				   "tmp", &SI);
-    StoreInst *StoreI = new StoreInst(CastI, SI.getOperand(1), &SI);
-    SI.getParent()->getInstList().erase(&SI);
-    
-    // Update the NewToOldValueMap if this is a clone
-    if (!FI.NewToOldValueMap.empty()) {
-      std::map<Value*,const Value*>::iterator II =
-	FI.NewToOldValueMap.find(&SI);
-      assert(II != FI.NewToOldValueMap.end() && 
-	     "SI not found in clone?");
-      FI.NewToOldValueMap.insert(std::make_pair(StoreI, II->second));
-      FI.NewToOldValueMap.erase(II);
-    }
-  }
-}
-
-void FuncTransform::visitPHINode(PHINode &PI) {
-  // If any of the operands of the PHI node is a constant function pointer
-  // that is cloned, the cast instruction has to be inserted at the end of the
-  // previous basic block
-  
-  if (isFuncPtr(&PI)) {
-    PHINode *V = new PHINode(PI.getType(), PI.getName(), &PI);
-    for (unsigned i = 0 ; i < PI.getNumIncomingValues(); ++i) {
-      if (Value *clonedFunc = retCloneIfFunc(PI.getIncomingValue(i))) {
-	// Insert CastInst at the end of  PI.getIncomingBlock(i)
-	BasicBlock::iterator BBI = --PI.getIncomingBlock(i)->end();
-	// BBI now points to the terminator instruction of the basic block.
-	CastInst *CastI = new CastInst(clonedFunc, PI.getType(), "tmp", BBI);
-	V->addIncoming(CastI, PI.getIncomingBlock(i));
-      } else {
-	V->addIncoming(PI.getIncomingValue(i), PI.getIncomingBlock(i));
-      }
-      
-    }
-    PI.replaceAllUsesWith(V);
-    PI.getParent()->getInstList().erase(&PI);
-    
-    DSGraph::ScalarMapTy &SM = G.getScalarMap();
-    DSGraph::ScalarMapTy::iterator PII = SM.find(&PI); 
-
-    // Update Scalar map of DSGraph if this is one of the original functions
-    // Otherwise update the NewToOldValueMap
-    if (PII != SM.end()) {
-      SM.insert(std::make_pair(V, PII->second));
-      SM.erase(PII);                     // Destroy the PHINode
-    } else {
-      std::map<Value*,const Value*>::iterator II =
-	FI.NewToOldValueMap.find(&PI);
-      assert(II != FI.NewToOldValueMap.end() && 
-	     "PhiI not found in clone?");
-      FI.NewToOldValueMap.insert(std::make_pair(V, II->second));
-      FI.NewToOldValueMap.erase(II);
-    }
-  }
-}
-
-void FuncTransform::visitMallocInst(MallocInst &MI) {
-  // Get the pool handle for the node that this contributes to...
-  Value *PH = getPoolHandle(&MI);
+  FuncInfo &FI = FunctionInfo[&F];   // Get FuncInfo for F
+  hash_set<DSNode*> &MarkedNodes = FI.MarkedNodes;
   
-  // NB: PH is zero even if the node is collapsed
-  if (PH == 0) return;
-
-  std::string Name = MI.getName(); MI.setName("");
-
-  // Insert a call to poolalloc
-  TargetData &TD = PAInfo.getAnalysis<TargetData>();
-  Value *AllocSize =
-    ConstantUInt::get(Type::UIntTy, TD.getTypeSize(MI.getAllocatedType()));
-
-  if (MI.isArrayAllocation())
-    AllocSize = BinaryOperator::create(Instruction::Mul, AllocSize,
-                                       MI.getOperand(0), "sizetmp", &MI);
-
-  Value *V = new CallInst(PAInfo.PoolAlloc, make_vector(PH, AllocSize, 0),
-                          Name, &MI);
-
-  const Type *phtype = MI.getType()->getElementType();
-  std::map<const Value*, const Type*> &PoolDescType = FI.PoolDescType;
-  if (!PoolDescType.count(PH))
-    PoolDescType[PH] = phtype;
-
-  Value *Casted = V;
-
-  // Cast to the appropriate type if necessary
-  if (V->getType() != MI.getType())
-    Casted = new CastInst(V, MI.getType(), V->getName(), &MI);
-    
-  // Update def-use info
-  MI.replaceAllUsesWith(Casted);
-
-  // Remove old malloc instruction
-  MI.getParent()->getInstList().erase(&MI);
+  DEBUG(std::cerr << "[" << F.getName() << "] Pool Allocate: ");
   
-  DSGraph::ScalarMapTy &SM = G.getScalarMap();
-  DSGraph::ScalarMapTy::iterator MII = SM.find(&MI);
+  // Loop over all of the nodes which are non-escaping, adding pool-allocatable
+  // ones to the NodesToPA vector.
+  std::vector<DSNode*> NodesToPA;
+  for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
+    if (Nodes[i]->isHeapNode() &&   // Pick nodes with heap elems
+        !MarkedNodes.count(Nodes[i]))              // Can't be marked
+      NodesToPA.push_back(Nodes[i]);
   
-  // If we are modifying the original function, update the DSGraph... 
-  if (MII != SM.end()) {
-    // V and Casted now point to whatever the original malloc did...
-    SM.insert(std::make_pair(V, MII->second));
-    if (V != Casted)
-      SM.insert(std::make_pair(Casted, MII->second));
-    SM.erase(MII);                     // The malloc is now destroyed
-  } else {             // Otherwise, update the NewToOldValueMap
-    std::map<Value*,const Value*>::iterator MII =
-      FI.NewToOldValueMap.find(&MI);
-    assert(MII != FI.NewToOldValueMap.end() && "MI not found in clone?");
-    FI.NewToOldValueMap.insert(std::make_pair(V, MII->second));
-    if (V != Casted)
-      FI.NewToOldValueMap.insert(std::make_pair(Casted, MII->second));
-    FI.NewToOldValueMap.erase(MII);
-  }
-}
-
-void FuncTransform::visitFreeInst(FreeInst &FrI) {
-  Value *Arg = FrI.getOperand(0);
-  Value *PH = getPoolHandle(Arg);  // Get the pool handle for this DSNode...
-  if (PH == 0) return;
-
-  const Type *phtype = 0;
-  if (const PointerType * ptype = dyn_cast<PointerType>(Arg->getType())) {
-    phtype = ptype->getElementType();
-  }
-  assert((phtype != 0) && "Needs to be implemented \n ");
-  std::map<const Value*, const Type*> &PoolDescType = FI.PoolDescType;
-  if (!PoolDescType.count(PH))
-    PoolDescType[PH] = phtype;
-  
-  // Insert a cast and a call to poolfree...
-  Value *Casted = Arg;
-  if (Arg->getType() != PointerType::get(Type::SByteTy))
-    Casted = new CastInst(Arg, PointerType::get(Type::SByteTy),
-				 Arg->getName()+".casted", &FrI);
-
-  CallInst *FreeI = new CallInst(PAInfo.PoolFree, make_vector(PH, Casted, 0), 
-				 "", &FrI);
-  // Delete the now obsolete free instruction...
-  FrI.getParent()->getInstList().erase(&FrI);
-  
-  // Update the NewToOldValueMap if this is a clone
-  if (!FI.NewToOldValueMap.empty()) {
-    std::map<Value*,const Value*>::iterator II =
-      FI.NewToOldValueMap.find(&FrI);
-    assert(II != FI.NewToOldValueMap.end() && 
-	   "FrI not found in clone?");
-    FI.NewToOldValueMap.insert(std::make_pair(FreeI, II->second));
-    FI.NewToOldValueMap.erase(II);
-  }
-}
-
-static void CalcNodeMapping(DSNodeHandle& Caller, DSNodeHandle& Callee,
-                            std::map<DSNode*, DSNode*> &NodeMapping) {
-  DSNode *CalleeNode = Callee.getNode();
-  DSNode *CallerNode = Caller.getNode();
-
-  unsigned CalleeOffset = Callee.getOffset();
-  unsigned CallerOffset = Caller.getOffset();
-
-  if (CalleeNode == 0) return;
-
-  // If callee has a node and caller doesn't, then a constant argument was
-  // passed by the caller
-  if (CallerNode == 0) {
-    NodeMapping.insert(NodeMapping.end(), std::make_pair(CalleeNode, 
-							 (DSNode *) 0));
-  }
-
-  // Map the callee node to the caller node. 
-  // NB: The callee node could be of a different type. Eg. if it points to the
-  // field of a struct that the caller points to
-  std::map<DSNode*, DSNode*>::iterator I = NodeMapping.find(CalleeNode);
-  if (I != NodeMapping.end()) {   // Node already in map...
-    assert(I->second == CallerNode && 
-	   "Node maps to different nodes on paths?");
-  } else {
-    NodeMapping.insert(I, std::make_pair(CalleeNode, CallerNode));
-    
-    if (CalleeNode->getType() != CallerNode->getType() && CallerOffset == 0) 
-      DEBUG(std::cerr << "NB: Mapping of nodes between different types\n");
-
-    // Recursively map the callee links to the caller links starting from the
-    // offset in the node into which they are mapped.
-    // Being a BU Graph, the callee ought to have smaller number of links unless
-    // there is collapsing in the caller
-    unsigned numCallerLinks = CallerNode->getNumLinks() - CallerOffset;
-    unsigned numCalleeLinks = CalleeNode->getNumLinks() - CalleeOffset;
-    
-    if (numCallerLinks > 0) {
-      if (numCallerLinks < numCalleeLinks) {
-	DEBUG(std::cerr << "Potential node collapsing in caller\n");
-	for (unsigned i = 0, e = numCalleeLinks; i != e; ++i)
-	  CalcNodeMapping(CallerNode->getLink(((i%numCallerLinks) << DS::PointerShift) + CallerOffset), CalleeNode->getLink((i << DS::PointerShift) + CalleeOffset), NodeMapping);
-      } else {
-	for (unsigned i = 0, e = numCalleeLinks; i != e; ++i)
-	  CalcNodeMapping(CallerNode->getLink((i << DS::PointerShift) + CallerOffset), CalleeNode->getLink((i << DS::PointerShift) + CalleeOffset), NodeMapping);
-      }
-    } else if (numCalleeLinks > 0) {
-      DEBUG(std::cerr << 
-	    "Caller has unexpanded node, due to indirect call perhaps!\n");
-    }
+  DEBUG(std::cerr << NodesToPA.size() << " nodes to pool allocate\n");
+  if (!NodesToPA.empty()) {
+    // Create pool construction/destruction code
+    std::map<DSNode*, Value*> &PoolDescriptors = FI.PoolDescriptors;
+    std::map<const Value*, const Type*> &PoolDescTypeMap = FI.PoolDescType;
+    CreatePools(NewF, NodesToPA, PoolDescriptors, PoolDescTypeMap);
   }
+  
+  // Transform the body of the function now... collecting information about uses
+  // of the pools.
+  std::set<Value*, BasicBlock*> PoolUses;
+  std::set<Value*, CallInst*> PoolFrees;
+  TransformBody(G, TDDS->getDSGraph(F), FI, PoolUses, PoolFrees, NewF);
 }
 
-void FuncTransform::visitCallSite(CallSite CS) {
-  Function *CF = CS.getCalledFunction();
-  Instruction *TheCall = CS.getInstruction();
-
-  // optimization for function pointers that are basically gotten from a cast
-  // with only one use and constant expressions with casts in them
-  if (!CF) {
-    Value *CV = CS.getCalledValue();
-    if (CastInst* CastI = dyn_cast<CastInst>(CV)) {
-      if (isa<Function>(CastI->getOperand(0)) && 
-	  CastI->getOperand(0)->getType() == CastI->getType())
-	CF = dyn_cast<Function>(CastI->getOperand(0));
-    } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
-      if (CE->getOpcode() == Instruction::Cast)
-	if (ConstantPointerRef *CPR
-            = dyn_cast<ConstantPointerRef>(CE->getOperand(0)))
-          CF = dyn_cast<Function>(CPR->getValue());
-    }
-  }
-
-  DSGraph &CallerG = G;
-
-  std::vector<Value*> Args;  
-
-  // We need to figure out which local pool descriptors correspond to the pool
-  // descriptor arguments passed into the function call.  Calculate a mapping
-  // from callee DSNodes to caller DSNodes.  We construct a partial isomophism
-  // between the graphs to figure out which pool descriptors need to be passed
-  // in.  The roots of this mapping is found from arguments and return values.
-  //
-  std::map<DSNode*, DSNode*> NodeMapping;
-
-  if (!CF) {   // Indirect call
-    DEBUG(std::cerr << "  Handling call: " << *TheCall);
-    
-    std::map<unsigned, Value*> PoolArgs;
-    Function *FuncClass;
-    
-    std::pair<std::multimap<CallSite, Function*>::iterator,
-              std::multimap<CallSite, Function*>::iterator> Targets =
-      PAInfo.CallSiteTargets.equal_range(CS);
-    for (std::multimap<CallSite, Function*>::iterator TFI = Targets.first,
-	   TFE = Targets.second; TFI != TFE; ++TFI) {
-      if (TFI == Targets.first) {
-	FuncClass = PAInfo.FuncECs.findClass(TFI->second);
-	// Nothing to transform if there are no pool arguments in this
-	// equivalence class of functions.
-	if (!PAInfo.EqClass2LastPoolArg.count(FuncClass))
-	  return;
-      }
-      
-      FuncInfo *CFI = PAInfo.getFuncInfo(*TFI->second);
-
-      if (!CFI->ArgNodes.size()) continue;  // Nothing to transform...
-      
-      DSGraph &CG = PAInfo.getBUDataStructures().getDSGraph(*TFI->second);  
-      
-      {
-        Function::aiterator FAI = TFI->second->abegin(),E = TFI->second->aend();
-        CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
-        for ( ; FAI != E && AI != AE; ++FAI, ++AI)
-          if (!isa<Constant>(*AI))
-            CalcNodeMapping(getDSNodeHFor(*AI), CG.getScalarMap()[FAI],
-                            NodeMapping);
-        assert(AI == AE && "Varargs calls not handled yet!");
-      }
-      
-      if (TheCall->getType() != Type::VoidTy)
-        CalcNodeMapping(getDSNodeHFor(TheCall),
-                        CG.getReturnNodeFor(*TFI->second), NodeMapping);
-      
-      // Map the nodes that are pointed to by globals.
-      // For all globals map getDSNodeForGlobal(g)->CG.getDSNodeForGlobal(g)
-      for (DSGraph::ScalarMapTy::iterator SMI = G.getScalarMap().begin(), 
-             SME = G.getScalarMap().end(); SMI != SME; ++SMI)
-        if (isa<GlobalValue>(SMI->first)) { 
-          CalcNodeMapping(SMI->second, 
-                          CG.getScalarMap()[SMI->first], NodeMapping);
-        }
-
-      unsigned idx = CFI->PoolArgFirst;
-
-      // The following loop determines the pool pointers corresponding to 
-      // CFI.
-      for (unsigned i = 0, e = CFI->ArgNodes.size(); i != e; ++i, ++idx) {
-        if (NodeMapping.count(CFI->ArgNodes[i])) {
-          assert(NodeMapping.count(CFI->ArgNodes[i]) && "Node not in mapping!");
-          DSNode *LocalNode = NodeMapping.find(CFI->ArgNodes[i])->second;
-          if (LocalNode) {
-            assert(FI.PoolDescriptors.count(LocalNode) &&
-                   "Node not pool allocated?");
-            PoolArgs[idx] = FI.PoolDescriptors.find(LocalNode)->second;
-          }
-          else
-            // LocalNode is null when a constant is passed in as a parameter
-            PoolArgs[idx] = Constant::getNullValue(PoolDescPtr);
-        } else {
-          PoolArgs[idx] = Constant::getNullValue(PoolDescPtr);
-        }
-      }
-    }
-    
-    // Push the pool arguments into Args.
-    if (PAInfo.EqClass2LastPoolArg.count(FuncClass)) {
-      for (int i = 0; i <= PAInfo.EqClass2LastPoolArg[FuncClass]; ++i) {
-        if (PoolArgs.find(i) != PoolArgs.end())
-          Args.push_back(PoolArgs[i]);
-        else
-          Args.push_back(Constant::getNullValue(PoolDescPtr));
-      }
-    
-      assert(Args.size()== (unsigned) PAInfo.EqClass2LastPoolArg[FuncClass] + 1
-             && "Call has same number of pool args as the called function");
-    }
-
-    // Add the rest of the arguments (the original arguments of the function)...
-    Args.insert(Args.end(), CS.arg_begin(), CS.arg_end());
-    
-    std::string Name = TheCall->getName(); TheCall->setName("");
-    
-    Value *NewCall;
-    Value *CalledValuePtr = CS.getCalledValue();
-    if (Args.size() > (unsigned)CS.arg_size()) {
-      // If there are any pool arguments
-      CalledValuePtr = new CastInst(CS.getCalledValue(), 
-                       PAInfo.getFuncInfo(*FuncClass)->Clone->getType(), "tmp", 
-                                    TheCall);
-    }
-
-    if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
-      NewCall = new InvokeInst(CalledValuePtr, II->getNormalDest(),
-                               II->getExceptionalDest(), Args, Name, TheCall);
-    } else {
-      NewCall = new CallInst(CalledValuePtr, Args, Name, TheCall);
-    }
-
-    TheCall->replaceAllUsesWith(NewCall);
-    DEBUG(std::cerr << "  Result Call: " << *NewCall);
-      
-    if (TheCall->getType() != Type::VoidTy) {
-      // If we are modifying the original function, update the DSGraph... 
-      DSGraph::ScalarMapTy &SM = G.getScalarMap();
-      DSGraph::ScalarMapTy::iterator CII = SM.find(TheCall);
-      if (CII != SM.end()) {
-	SM.insert(std::make_pair(NewCall, CII->second));
-	SM.erase(CII);                     // Destroy the CallInst
-      } else { 
-	// Otherwise update the NewToOldValueMap with the new CI return value
-	std::map<Value*,const Value*>::iterator CII = 
-	  FI.NewToOldValueMap.find(TheCall);
-	assert(CII != FI.NewToOldValueMap.end() && "CI not found in clone?");
-	FI.NewToOldValueMap.insert(std::make_pair(NewCall, CII->second));
-	FI.NewToOldValueMap.erase(CII);
-      }
-    } else if (!FI.NewToOldValueMap.empty()) {
-      std::map<Value*,const Value*>::iterator II =
-	FI.NewToOldValueMap.find(TheCall);
-      assert(II != FI.NewToOldValueMap.end() && 
-	     "CI not found in clone?");
-      FI.NewToOldValueMap.insert(std::make_pair(NewCall, II->second));
-      FI.NewToOldValueMap.erase(II);
-    }
-  } else {
-    FuncInfo *CFI = PAInfo.getFuncInfo(*CF);
-
-    if (CFI == 0 || CFI->Clone == 0) return;  // Nothing to transform...
-    
-    DEBUG(std::cerr << "  Handling call: " << *TheCall);
-    
-    DSGraph &CG = PAInfo.getBUDataStructures().getDSGraph(*CF);  // Callee graph
-
-    {
-      Function::aiterator FAI = CF->abegin(), E = CF->aend();
-      CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
-      for ( ; FAI != E && AI != AE; ++FAI, ++AI)
-        if (!isa<Constant>(*AI))
-          CalcNodeMapping(getDSNodeHFor(*AI), CG.getScalarMap()[FAI],
-                          NodeMapping);
-      assert(AI == AE && "Varargs calls not handled yet!");
-    }
-
-    // Map the return value as well...
-    if (TheCall->getType() != Type::VoidTy)
-      CalcNodeMapping(getDSNodeHFor(TheCall), CG.getReturnNodeFor(*CF),
-		      NodeMapping);
-
-    // Map the nodes that are pointed to by globals.
-    // For all globals map getDSNodeForGlobal(g)->CG.getDSNodeForGlobal(g)
-    for (DSGraph::ScalarMapTy::iterator SMI = G.getScalarMap().begin(), 
-	   SME = G.getScalarMap().end(); SMI != SME; ++SMI)
-      if (isa<GlobalValue>(SMI->first)) 
-	CalcNodeMapping(SMI->second, 
-			CG.getScalarMap()[SMI->first], NodeMapping);
-
-    // Okay, now that we have established our mapping, we can figure out which
-    // pool descriptors to pass in...
-
-    // Add an argument for each pool which must be passed in...
-    if (CFI->PoolArgFirst != 0) {
-      for (int i = 0; i < CFI->PoolArgFirst; ++i)
-	Args.push_back(Constant::getNullValue(PoolDescPtr));  
-    }
-
-    for (unsigned i = 0, e = CFI->ArgNodes.size(); i != e; ++i) {
-      if (NodeMapping.count(CFI->ArgNodes[i])) {
-
-	DSNode *LocalNode = NodeMapping.find(CFI->ArgNodes[i])->second;
-	if (LocalNode) {
-	  assert(FI.PoolDescriptors.count(LocalNode) &&
-                 "Node not pool allocated?");
-	  Args.push_back(FI.PoolDescriptors.find(LocalNode)->second);
-	} else
-	  Args.push_back(Constant::getNullValue(PoolDescPtr));
-      } else {
-	Args.push_back(Constant::getNullValue(PoolDescPtr));
-      }
-    }
-
-    Function *FuncClass = PAInfo.FuncECs.findClass(CF);
-    
-    if (PAInfo.EqClass2LastPoolArg.count(FuncClass))
-      for (int i = CFI->PoolArgLast; 
-	   i <= PAInfo.EqClass2LastPoolArg[FuncClass]; ++i)
-	Args.push_back(Constant::getNullValue(PoolDescPtr));
-
-    // Add the rest of the arguments...
-    Args.insert(Args.end(), CS.arg_begin(), CS.arg_end());
-    
-    std::string Name = TheCall->getName(); TheCall->setName("");
-
-    Value *NewCall;
-    if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
-      NewCall = new InvokeInst(CFI->Clone, II->getNormalDest(),
-                               II->getExceptionalDest(), Args, Name, TheCall);
-    } else {
-      NewCall = new CallInst(CFI->Clone, Args, Name, TheCall);
-    }
-
-    TheCall->replaceAllUsesWith(NewCall);
-    DEBUG(std::cerr << "  Result Call: " << *NewCall);
-
-    if (TheCall->getType() != Type::VoidTy) {
-      // If we are modifying the original function, update the DSGraph... 
-      DSGraph::ScalarMapTy &SM = G.getScalarMap();
-      DSGraph::ScalarMapTy::iterator CII = SM.find(TheCall); 
-      if (CII != SM.end()) {
-	SM.insert(std::make_pair(NewCall, CII->second));
-	SM.erase(CII);                     // Destroy the CallInst
-      } else { 
-	// Otherwise update the NewToOldValueMap with the new CI return value
-	std::map<Value*,const Value*>::iterator CNII = 
-	  FI.NewToOldValueMap.find(TheCall);
-	assert(CNII != FI.NewToOldValueMap.end() && CNII->second && 
-	       "CI not found in clone?");
-	FI.NewToOldValueMap.insert(std::make_pair(NewCall, CNII->second));
-	FI.NewToOldValueMap.erase(CNII);
-      }
-    } else if (!FI.NewToOldValueMap.empty()) {
-      std::map<Value*,const Value*>::iterator II =
-	FI.NewToOldValueMap.find(TheCall);
-      assert(II != FI.NewToOldValueMap.end() && "CI not found in clone?");
-      FI.NewToOldValueMap.insert(std::make_pair(NewCall, II->second));
-      FI.NewToOldValueMap.erase(II);
-    }
-  }
-
-  TheCall->getParent()->getInstList().erase(TheCall);
-}





More information about the llvm-commits mailing list