mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5786 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			447 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			447 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===-- PoolAllocate.cpp - Pool Allocation Pass ---------------------------===//
 | |
| //
 | |
| // This transform changes programs so that disjoint data structures are
 | |
| // allocated out of different pools of memory, increasing locality.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "llvm/Transforms/PoolAllocate.h"
 | |
| #include "llvm/Transforms/Utils/Cloning.h"
 | |
| #include "llvm/Analysis/DataStructure.h"
 | |
| #include "llvm/Analysis/DSGraph.h"
 | |
| #include "llvm/Module.h"
 | |
| #include "llvm/DerivedTypes.h"
 | |
| #include "llvm/Constants.h"
 | |
| #include "llvm/Instructions.h"
 | |
| #include "llvm/Target/TargetData.h"
 | |
| #include "llvm/Support/InstVisitor.h"
 | |
| #include "Support/Statistic.h"
 | |
| #include "Support/VectorExtras.h"
 | |
| 
 | |
| using namespace PA;
 | |
| 
 | |
| namespace {
 | |
|   const Type *VoidPtrTy = PointerType::get(Type::SByteTy);
 | |
|   // The type to allocate for a pool descriptor: { sbyte*, uint }
 | |
|   const Type *PoolDescType =
 | |
|     StructType::get(make_vector<const Type*>(VoidPtrTy, Type::UIntTy, 0));
 | |
|   const PointerType *PoolDescPtr = PointerType::get(PoolDescType);
 | |
| 
 | |
|   RegisterOpt<PoolAllocate>
 | |
|   X("poolalloc", "Pool allocate disjoint data structures");
 | |
| }
 | |
| 
 | |
| void PoolAllocate::getAnalysisUsage(AnalysisUsage &AU) const {
 | |
|   AU.addRequired<BUDataStructures>();
 | |
|   AU.addRequired<TargetData>();
 | |
| }
 | |
| 
 | |
| bool PoolAllocate::run(Module &M) {
 | |
|   if (M.begin() == M.end()) return false;
 | |
|   CurModule = &M;
 | |
|   
 | |
|   AddPoolPrototypes();
 | |
|   BU = &getAnalysis<BUDataStructures>();
 | |
| 
 | |
|   std::map<Function*, Function*> FuncMap;
 | |
| 
 | |
|   // Loop over only the function initially in the program, don't traverse newly
 | |
|   // added ones.  If the function uses memory, make its clone.
 | |
|   Module::iterator LastOrigFunction = --M.end();
 | |
|   for (Module::iterator I = M.begin(); ; ++I) {
 | |
|     if (!I->isExternal())
 | |
|       if (Function *R = MakeFunctionClone(*I))
 | |
|         FuncMap[I] = R;
 | |
|     if (I == LastOrigFunction) break;
 | |
|   }
 | |
| 
 | |
|   ++LastOrigFunction;
 | |
| 
 | |
|   // Now that all call targets are available, rewrite the function bodies of the
 | |
|   // clones.
 | |
|   for (Module::iterator I = M.begin(); I != LastOrigFunction; ++I)
 | |
|     if (!I->isExternal()) {
 | |
|       std::map<Function*, Function*>::iterator FI = FuncMap.find(I);
 | |
|       ProcessFunctionBody(*I, FI != FuncMap.end() ? *FI->second : *I);
 | |
|     }
 | |
| 
 | |
|   FunctionInfo.clear();
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| 
 | |
| // AddPoolPrototypes - Add prototypes for the pool functions to the specified
 | |
| // module and update the Pool* instance variables to point to them.
 | |
| //
 | |
| void PoolAllocate::AddPoolPrototypes() {
 | |
|   CurModule->addTypeName("PoolDescriptor", PoolDescType);
 | |
| 
 | |
|   // Get poolinit function...
 | |
|   FunctionType *PoolInitTy =
 | |
|     FunctionType::get(Type::VoidTy,
 | |
|                       make_vector<const Type*>(PoolDescPtr, Type::UIntTy, 0),
 | |
|                       false);
 | |
|   PoolInit = CurModule->getOrInsertFunction("poolinit", PoolInitTy);
 | |
| 
 | |
|   // Get pooldestroy function...
 | |
|   std::vector<const Type*> PDArgs(1, PoolDescPtr);
 | |
|   FunctionType *PoolDestroyTy =
 | |
|     FunctionType::get(Type::VoidTy, PDArgs, false);
 | |
|   PoolDestroy = CurModule->getOrInsertFunction("pooldestroy", PoolDestroyTy);
 | |
| 
 | |
|   // Get the poolalloc function...
 | |
|   FunctionType *PoolAllocTy = FunctionType::get(VoidPtrTy, PDArgs, false);
 | |
|   PoolAlloc = CurModule->getOrInsertFunction("poolalloc", PoolAllocTy);
 | |
| 
 | |
|   // Get the poolfree function...
 | |
|   PDArgs.push_back(VoidPtrTy);       // Pointer to free
 | |
|   FunctionType *PoolFreeTy = FunctionType::get(Type::VoidTy, PDArgs, false);
 | |
|   PoolFree = CurModule->getOrInsertFunction("poolfree", PoolFreeTy);
 | |
| 
 | |
| #if 0
 | |
|   Args[0] = Type::UIntTy;            // Number of slots to allocate
 | |
|   FunctionType *PoolAllocArrayTy = FunctionType::get(VoidPtrTy, Args, true);
 | |
|   PoolAllocArray = CurModule->getOrInsertFunction("poolallocarray",
 | |
|                                                   PoolAllocArrayTy);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| // MakeFunctionClone - If the specified function needs to be modified for pool
 | |
| // allocation support, make a clone of it, adding additional arguments as
 | |
| // neccesary, and return it.  If not, just return null.
 | |
| //
 | |
| Function *PoolAllocate::MakeFunctionClone(Function &F) {
 | |
|   DSGraph &G = BU->getDSGraph(F);
 | |
|   std::vector<DSNode*> &Nodes = G.getNodes();
 | |
|   if (Nodes.empty()) return 0;  // No memory activity, nothing is required
 | |
| 
 | |
|   FuncInfo &FI = FunctionInfo[&F];   // Create a new entry for F
 | |
|   FI.Clone = 0;
 | |
| 
 | |
|   // Find DataStructure nodes which are allocated in pools non-local to the
 | |
|   // current function.  This set will contain all of the DSNodes which require
 | |
|   // pools to be passed in from outside of the function.
 | |
|   hash_set<DSNode*> &MarkedNodes = FI.MarkedNodes;
 | |
| 
 | |
|   // Mark globals and incomplete nodes as live... (this handles arguments)
 | |
|   if (F.getName() != "main")
 | |
|     for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
 | |
|       if (Nodes[i]->NodeType & (DSNode::GlobalNode | DSNode::Incomplete) &&
 | |
|           Nodes[i]->NodeType & (DSNode::HeapNode))
 | |
|         Nodes[i]->markReachableNodes(MarkedNodes);
 | |
| 
 | |
|   // Marked the returned node as alive...
 | |
|   if (DSNode *RetNode = G.getRetNode().getNode())
 | |
|     if (RetNode->NodeType & DSNode::HeapNode)
 | |
|       RetNode->markReachableNodes(MarkedNodes);
 | |
| 
 | |
|   if (MarkedNodes.empty())   // We don't need to clone the function if there
 | |
|     return 0;                // are no incoming arguments to be added.
 | |
| 
 | |
|   // Figure out what the arguments are to be for the new version of the function
 | |
|   const FunctionType *OldFuncTy = F.getFunctionType();
 | |
|   std::vector<const Type*> ArgTys;
 | |
|   ArgTys.reserve(OldFuncTy->getParamTypes().size() + MarkedNodes.size());
 | |
| 
 | |
|   FI.ArgNodes.reserve(MarkedNodes.size());
 | |
|   for (hash_set<DSNode*>::iterator I = MarkedNodes.begin(),
 | |
|          E = MarkedNodes.end(); I != E; ++I)
 | |
|     if ((*I)->NodeType & DSNode::Incomplete) {
 | |
|       ArgTys.push_back(PoolDescPtr);      // Add the appropriate # of pool descs
 | |
|       FI.ArgNodes.push_back(*I);
 | |
|     }
 | |
|   if (FI.ArgNodes.empty()) return 0;      // No nodes to be pool allocated!
 | |
| 
 | |
|   ArgTys.insert(ArgTys.end(), OldFuncTy->getParamTypes().begin(),
 | |
|                 OldFuncTy->getParamTypes().end());
 | |
| 
 | |
| 
 | |
|   // Create the new function prototype
 | |
|   FunctionType *FuncTy = FunctionType::get(OldFuncTy->getReturnType(), ArgTys,
 | |
|                                            OldFuncTy->isVarArg());
 | |
|   // Create the new function...
 | |
|   Function *New = new Function(FuncTy, GlobalValue::InternalLinkage,
 | |
|                                F.getName(), F.getParent());
 | |
| 
 | |
|   // Set the rest of the new arguments names to be PDa<n> and add entries to the
 | |
|   // pool descriptors map
 | |
|   std::map<DSNode*, Value*> &PoolDescriptors = FI.PoolDescriptors;
 | |
|   Function::aiterator NI = New->abegin();
 | |
|   for (unsigned i = 0, e = FI.ArgNodes.size(); i != e; ++i, ++NI) {
 | |
|     NI->setName("PDa");  // Add pd entry
 | |
|     PoolDescriptors.insert(std::make_pair(FI.ArgNodes[i], NI));
 | |
|   }
 | |
| 
 | |
|   // Map the existing arguments of the old function to the corresponding
 | |
|   // arguments of the new function.
 | |
|   std::map<const Value*, Value*> ValueMap;
 | |
|   for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I, ++NI) {
 | |
|     ValueMap[I] = NI;
 | |
|     NI->setName(I->getName());
 | |
|   }
 | |
| 
 | |
|   // Populate the value map with all of the globals in the program.
 | |
|   // FIXME: This should be unneccesary!
 | |
|   Module &M = *F.getParent();
 | |
|   for (Module::iterator I = M.begin(), E=M.end(); I!=E; ++I)    ValueMap[I] = I;
 | |
|   for (Module::giterator I = M.gbegin(), E=M.gend(); I!=E; ++I) ValueMap[I] = I;
 | |
| 
 | |
|   // Perform the cloning.
 | |
|   std::vector<ReturnInst*> Returns;
 | |
|   CloneFunctionInto(New, &F, ValueMap, Returns);
 | |
| 
 | |
|   // Invert the ValueMap into the NewToOldValueMap
 | |
|   std::map<Value*, const Value*> &NewToOldValueMap = FI.NewToOldValueMap;
 | |
|   for (std::map<const Value*, Value*>::iterator I = ValueMap.begin(),
 | |
|          E = ValueMap.end(); I != E; ++I)
 | |
|     NewToOldValueMap.insert(std::make_pair(I->second, I->first));
 | |
|   
 | |
|   return FI.Clone = New;
 | |
| }
 | |
| 
 | |
| 
 | |
| // 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]->NodeType & DSNode::HeapNode &&   // Pick nodes with heap elems
 | |
|         !(Nodes[i]->NodeType & DSNode::Array) &&   // Doesn't handle arrays yet.
 | |
|         !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;
 | |
|     CreatePools(NewF, NodesToPA, PoolDescriptors);
 | |
|   }
 | |
| 
 | |
|   // Transform the body of the function now...
 | |
|   TransformFunctionBody(NewF, 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.
 | |
| //
 | |
| void PoolAllocate::CreatePools(Function &F,
 | |
|                                const std::vector<DSNode*> &NodesToPA,
 | |
|                                std::map<DSNode*, Value*> &PoolDescriptors) {
 | |
|   // 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)
 | |
|     if (isa<ReturnInst>(I->getTerminator()))
 | |
|       ReturnNodes.push_back(I);
 | |
| 
 | |
|   TargetData &TD = getAnalysis<TargetData>();
 | |
| 
 | |
|   // Loop over all of the pools, inserting code into the entry block of the
 | |
|   // function for the initialization and code in the exit blocks for
 | |
|   // destruction.
 | |
|   //
 | |
|   Instruction *InsertPoint = F.front().begin();
 | |
|   for (unsigned i = 0, e = NodesToPA.size(); i != e; ++i) {
 | |
|     DSNode *Node = NodesToPA[i];
 | |
| 
 | |
|     // Create a new alloca instruction for the pool...
 | |
|     Value *AI = new AllocaInst(PoolDescType, 0, "PD", InsertPoint);
 | |
| 
 | |
|     Value *ElSize =
 | |
|       ConstantUInt::get(Type::UIntTy, TD.getTypeSize(Node->getType()));
 | |
| 
 | |
|     // Insert the call to initialize the pool...
 | |
|     new CallInst(PoolInit, make_vector(AI, ElSize, 0), "", InsertPoint);
 | |
| 
 | |
|     // Update the PoolDescriptors map
 | |
|     PoolDescriptors.insert(std::make_pair(Node, AI));
 | |
| 
 | |
|     // Insert a call to pool destroy before each return inst in the function
 | |
|     for (unsigned r = 0, e = ReturnNodes.size(); r != e; ++r)
 | |
|       new CallInst(PoolDestroy, make_vector(AI, 0), "",
 | |
|                    ReturnNodes[r]->getTerminator());
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| namespace {
 | |
|   /// FuncTransform - This class implements transformation required of pool
 | |
|   /// allocated functions.
 | |
|   struct FuncTransform : public InstVisitor<FuncTransform> {
 | |
|     PoolAllocate &PAInfo;
 | |
|     DSGraph &G;
 | |
|     FuncInfo &FI;
 | |
| 
 | |
|     FuncTransform(PoolAllocate &P, DSGraph &g, FuncInfo &fi)
 | |
|       : PAInfo(P), G(g), FI(fi) {}
 | |
| 
 | |
|     void visitMallocInst(MallocInst &MI);
 | |
|     void visitFreeInst(FreeInst &FI);
 | |
|     void visitCallInst(CallInst &CI);
 | |
| 
 | |
|   private:
 | |
|     DSNode *getDSNodeFor(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].getNode();
 | |
|     }
 | |
|     Value *getPoolHandle(Value *V) {
 | |
|       DSNode *Node = getDSNodeFor(V);
 | |
|       // Get the pool handle for this DSNode...
 | |
|       std::map<DSNode*, Value*>::iterator I = FI.PoolDescriptors.find(Node);
 | |
|       return I != FI.PoolDescriptors.end() ? I->second : 0;
 | |
|     }
 | |
|   };
 | |
| }
 | |
| 
 | |
| void PoolAllocate::TransformFunctionBody(Function &F, DSGraph &G, FuncInfo &FI){
 | |
|   FuncTransform(*this, G, FI).visit(F);
 | |
| }
 | |
| 
 | |
| 
 | |
| void FuncTransform::visitMallocInst(MallocInst &MI) {
 | |
|   // Get the pool handle for the node that this contributes to...
 | |
|   Value *PH = getPoolHandle(&MI);
 | |
|   if (PH == 0) return;
 | |
|   
 | |
|   // Insert a call to poolalloc
 | |
|   Value *V = new CallInst(PAInfo.PoolAlloc, make_vector(PH, 0),
 | |
|                           MI.getName(), &MI);
 | |
|   MI.setName("");  // Nuke MIs name
 | |
|   
 | |
|   // Cast to the appropriate type...
 | |
|   Value *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);
 | |
|   
 | |
|   hash_map<Value*, DSNodeHandle> &SM = G.getScalarMap();
 | |
|   hash_map<Value*, DSNodeHandle>::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));
 | |
|     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));
 | |
|     FI.NewToOldValueMap.insert(std::make_pair(Casted, MII->second));
 | |
|     FI.NewToOldValueMap.erase(MII);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void FuncTransform::visitFreeInst(FreeInst &FI) {
 | |
|   Value *Arg = FI.getOperand(0);
 | |
|   Value *PH = getPoolHandle(Arg);  // Get the pool handle for this DSNode...
 | |
|   if (PH == 0) return;
 | |
|   // Insert a cast and a call to poolfree...
 | |
|   Value *Casted = new CastInst(Arg, PointerType::get(Type::SByteTy),
 | |
|                                Arg->getName()+".casted", &FI);
 | |
|   new CallInst(PAInfo.PoolFree, make_vector(PH, Casted, 0), "", &FI);
 | |
|   
 | |
|   // Delete the now obsolete free instruction...
 | |
|   FI.getParent()->getInstList().erase(&FI);
 | |
| }
 | |
| 
 | |
| static void CalcNodeMapping(DSNode *Caller, DSNode *Callee,
 | |
|                             std::map<DSNode*, DSNode*> &NodeMapping) {
 | |
|   if (Callee == 0) return;
 | |
|   assert(Caller && "Callee has node but caller doesn't??");
 | |
| 
 | |
|   std::map<DSNode*, DSNode*>::iterator I = NodeMapping.find(Callee);
 | |
|   if (I != NodeMapping.end()) {   // Node already in map...
 | |
|     assert(I->second == Caller && "Node maps to different nodes on paths?");
 | |
|   } else {
 | |
|     NodeMapping.insert(I, std::make_pair(Callee, Caller));
 | |
|     
 | |
|     // Recursively add pointed to nodes...
 | |
|     for (unsigned i = 0, e = Callee->getNumLinks(); i != e; ++i)
 | |
|       CalcNodeMapping(Caller->getLink(i << DS::PointerShift).getNode(),
 | |
|                       Callee->getLink(i << DS::PointerShift).getNode(),
 | |
|                       NodeMapping);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void FuncTransform::visitCallInst(CallInst &CI) {
 | |
|   Function *CF = CI.getCalledFunction();
 | |
|   assert(CF && "FIXME: Pool allocation doesn't handle indirect calls!");
 | |
| 
 | |
|   FuncInfo *CFI = PAInfo.getFuncInfo(*CF);
 | |
|   if (CFI == 0 || CFI->Clone == 0) return;  // Nothing to transform...
 | |
| 
 | |
|   DEBUG(std::cerr << "  Handling call: " << CI);
 | |
| 
 | |
|   DSGraph &CG = PAInfo.getBUDataStructures().getDSGraph(*CF);  // Callee graph
 | |
| 
 | |
|   // 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;
 | |
| 
 | |
|   Function::aiterator AI = CF->abegin(), AE = CF->aend();
 | |
|   unsigned OpNum = 1;
 | |
|   for (; AI != AE; ++AI, ++OpNum)
 | |
|     CalcNodeMapping(getDSNodeFor(CI.getOperand(OpNum)),
 | |
|                     CG.getScalarMap()[AI].getNode(), NodeMapping);
 | |
|   assert(OpNum == CI.getNumOperands() && "Varargs calls not handled yet!");
 | |
|   
 | |
|   // Map the return value as well...
 | |
|   CalcNodeMapping(getDSNodeFor(&CI), CG.getRetNode().getNode(), NodeMapping);
 | |
| 
 | |
| 
 | |
|   // Okay, now that we have established our mapping, we can figure out which
 | |
|   // pool descriptors to pass in...
 | |
|   std::vector<Value*> Args;
 | |
| 
 | |
|   // Add an argument for each pool which must be passed in...
 | |
|   for (unsigned i = 0, e = CFI->ArgNodes.size(); i != e; ++i) {
 | |
|     if (NodeMapping.count(CFI->ArgNodes[i])) {
 | |
|       assert(NodeMapping.count(CFI->ArgNodes[i]) && "Node not in mapping!");
 | |
|       DSNode *LocalNode = NodeMapping.find(CFI->ArgNodes[i])->second;
 | |
|       assert(FI.PoolDescriptors.count(LocalNode) && "Node not pool allocated?");
 | |
|       Args.push_back(FI.PoolDescriptors.find(LocalNode)->second);
 | |
|     } else {
 | |
|       Args.push_back(Constant::getNullValue(PoolDescPtr));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Add the rest of the arguments...
 | |
|   Args.insert(Args.end(), CI.op_begin()+1, CI.op_end());
 | |
| 
 | |
|   std::string Name = CI.getName(); CI.setName("");
 | |
|   Value *NewCall = new CallInst(CFI->Clone, Args, Name, &CI);
 | |
|   CI.replaceAllUsesWith(NewCall);
 | |
| 
 | |
|   DEBUG(std::cerr << "  Result Call: " << *NewCall);
 | |
|   CI.getParent()->getInstList().erase(&CI);
 | |
| }
 |