[llvm-commits] CVS: llvm/lib/Transforms/IPO/PoolAllocate.cpp

Sumant Kowshik kowshik at cs.uiuc.edu
Tue Aug 5 12:03:01 PDT 2003


Changes in directory llvm/lib/Transforms/IPO:

PoolAllocate.cpp updated: 1.12 -> 1.13

---
Log message:

Major bug fixes including a memory leak and tracking some exceptional conditions. Also added support for including global and indirect call information in the DS graphs used by the pool allocation

---
Diffs of the changes:

Index: llvm/lib/Transforms/IPO/PoolAllocate.cpp
diff -u llvm/lib/Transforms/IPO/PoolAllocate.cpp:1.12 llvm/lib/Transforms/IPO/PoolAllocate.cpp:1.13
--- llvm/lib/Transforms/IPO/PoolAllocate.cpp:1.12	Fri Aug  1 17:15:01 2003
+++ llvm/lib/Transforms/IPO/PoolAllocate.cpp	Tue Aug  5 12:01:54 2003
@@ -19,6 +19,8 @@
 #include "Support/VectorExtras.h"
 using namespace PA;
 
+#define DEBUG_TYPE "PoolAllocation"
+
 namespace {
   const Type *VoidPtrTy = PointerType::get(Type::SByteTy);
 
@@ -55,6 +57,15 @@
   }
 }
 
+static void printNTOMap(std::map<Value*, const Value*> &NTOM) {
+  std::cerr << "NTOM MAP\n";
+  for (std::map<Value*, const Value *>::iterator I = NTOM.begin(), 
+	 E = NTOM.end(); I != E; ++I) {
+    if (!isa<Function>(I->first) && !isa<BasicBlock>(I->first))
+      std::cerr << *I->first << " to " << *I->second << "\n";
+  }
+}
+
 void PoolAllocate::buildIndirectFunctionSets(Module &M) {
   // Iterate over the module looking for indirect calls to functions
 
@@ -121,7 +132,7 @@
 
   std::map<Function*, Function*> FuncMap;
 
-   // Loop over the functions in the original program finding the pool desc.
+  // Loop over the functions in the original program finding the pool desc.
   // arguments necessary for each function that is indirectly callable.
   // For each equivalence class, make a list of pool arguments and update
   // the PoolArgFirst and PoolArgLast values for each function.
@@ -195,8 +206,65 @@
   
 }
 
+// Inline the DSGraphs of functions corresponding to the potential targets at
+// indirect call sites into the DS Graph of the callee.
+// This is required to know what pools to create/pass at the call site in the 
+// caller
+//
+void PoolAllocate::InlineIndirectCalls(Function &F, DSGraph &G, 
+				       hash_set<Function*> &visited) {
+  std::vector<DSCallSite> callSites = G.getFunctionCalls();
+  
+  visited.insert(&F);
+
+  // For each indirect call site in the function, inline all the potential
+  // targets
+  for (std::vector<DSCallSite>::iterator CSI = callSites.begin(),
+	 CSE = callSites.end(); CSI != CSE; ++CSI) {
+    if (CSI->isIndirectCall()) {
+      CallInst &CI = CSI->getCallInst();
+      std::pair<std::multimap<CallInst*, Function*>::iterator,
+	std::multimap<CallInst*, Function*>::iterator> Targets =
+	CallInstTargets.equal_range(&CI);
+      for (std::multimap<CallInst*, Function*>::iterator TFI = Targets.first,
+	     TFE = Targets.second; TFI != TFE; ++TFI) {
+	DSGraph &TargetG = BU->getDSGraph(*TFI->second);
+	// Call the function recursively if the callee is not yet inlined
+	// and if it hasn't been visited in this sequence of calls
+	// The latter is dependent on the fact that the graphs of all functions
+	// in an SCC are actually the same
+	if (InlinedFuncs.find(TFI->second) == InlinedFuncs.end() && 
+	    visited.find(TFI->second) == visited.end()) {
+	  InlineIndirectCalls(*TFI->second, TargetG, visited);
+	}
+	G.mergeInGraph(*CSI, *TFI->second, TargetG, DSGraph::KeepModRefBits | 
+		       DSGraph::KeepAllocaBit | DSGraph::DontCloneCallNodes |
+		       DSGraph::DontCloneAuxCallNodes); 
+      }
+    }
+  }
+  
+  // Mark this function as one whose graph is inlined with its indirect 
+  // function targets' DS Graphs.  This ensures that every function is inlined
+  // exactly once
+  InlinedFuncs.insert(&F);
+
+  
+}
+
 void PoolAllocate::FindFunctionPoolArgs(Function &F) {
+
+  // The DSGraph is merged with the globals graph. 
   DSGraph &G = BU->getDSGraph(F);
+  G.mergeInGlobalsGraph();
+
+  // Inline the potential targets of indirect calls
+  hash_set<Function*> visitedFuncs;
+  InlineIndirectCalls(F, G, visitedFuncs);
+
+  // At this point the DS Graphs have been modified in place including
+  // information about globals as well as indirect calls, making it useful
+  // for pool allocation
   std::vector<DSNode*> &Nodes = G.getNodes();
   if (Nodes.empty()) return ;  // No memory activity, nothing is required
 
@@ -225,10 +293,13 @@
   
   // 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]->isGlobalNode() || Nodes[i]->isIncomplete()) &&
-          Nodes[i]->isHeapNode())
+    for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
+      if (Nodes[i]->isGlobalNode() && !Nodes[i]->isIncomplete())
+	DEBUG(std::cerr << "Global node is not Incomplete\n");
+      if ((Nodes[i]->isIncomplete() || Nodes[i]->isGlobalNode()) && 
+	  Nodes[i]->isHeapNode())
         Nodes[i]->markReachableNodes(MarkedNodes);
+    }
 
   // Marked the returned node as alive...
   if (DSNode *RetNode = G.getReturnNodeFor(F).getNode())
@@ -238,9 +309,20 @@
   if (MarkedNodes.empty())   // We don't need to clone the function if there
     return;                  // are no incoming arguments to be added.
 
+  // Erase any marked node that is not a heap node
+
   for (hash_set<DSNode*>::iterator I = MarkedNodes.begin(),
-	 E = MarkedNodes.end(); I != E; ++I)
-    FI.PoolArgLast++;
+	 E = MarkedNodes.end(); I != E; ) {
+    // erase invalidates hash_set iterators if the iterator points to the
+    // element being erased
+    if (!(*I)->isHeapNode())
+      MarkedNodes.erase(I++);
+    else
+      ++I;
+  }
+
+  FI.PoolArgLast += MarkedNodes.size();
+
 
   if (FuncECs.findClass(&F)) {
     // Update the equivalence class last pool argument information
@@ -260,6 +342,7 @@
 Function *PoolAllocate::MakeFunctionClone(Function &F) {
   
   DSGraph &G = BU->getDSGraph(F);
+
   std::vector<DSNode*> &Nodes = G.getNodes();
   if (Nodes.empty())
     return 0;
@@ -270,7 +353,6 @@
   
   if (!FuncECs.findClass(&F)) {
     // Not in any equivalence class
-
     if (MarkedNodes.empty())
       return 0;
   } else {
@@ -396,6 +478,7 @@
 //
 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...
   
@@ -455,8 +538,10 @@
     // Void types in DS graph are never used
     if (Node->getType() != Type::VoidTy)
       ElSize = ConstantUInt::get(Type::UIntTy, TD.getTypeSize(Node->getType()));
-    else
+    else {
+      std::cerr << "Potential node collapsing in " << F.getName() << "\n";
       ElSize = ConstantUInt::get(Type::UIntTy, 0);
+    }
 	
     // Insert the call to initialize the pool...
     new CallInst(PoolInit, make_vector(AI, ElSize, 0), "", InsertPoint);
@@ -477,8 +562,8 @@
   /// allocated functions.
   struct FuncTransform : public InstVisitor<FuncTransform> {
     PoolAllocate &PAInfo;
-    DSGraph &G;
-    DSGraph &TDG;
+    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)
@@ -509,9 +594,9 @@
     }
 
   private:
-    DSNode *getDSNodeFor(Value *V) {
-      if (isa<Constant>(V))
-	return 0;
+    DSNodeHandle& getDSNodeHFor(Value *V) {
+      //      if (isa<Constant>(V))
+      //	return DSNodeHandle();
 
       if (!FI.NewToOldValueMap.empty()) {
         // If the NewToOldValueMap is in effect, use it.
@@ -520,10 +605,11 @@
           V = (Value*)I->second;
       }
 
-      return G.getScalarMap()[V].getNode();
+      return G.getScalarMap()[V];
     }
+    
     Value *getPoolHandle(Value *V) {
-      DSNode *Node = getDSNodeFor(V);
+      DSNode *Node = getDSNodeHFor(V).getNode();
       // 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;
@@ -595,51 +681,87 @@
   return 0;
 }
 
-void FuncTransform::visitReturnInst (ReturnInst &I) {
-  if (I.getNumOperands())
-    if (Value *clonedFunc = retCloneIfFunc(I.getOperand(0))) {
-      // Cast the clone of I.getOperand(0) to the non-pool-allocated type
-      CastInst *CastI = new CastInst(clonedFunc, I.getOperand(0)->getType(), 
-				     "tmp", &I);
+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
-      new ReturnInst(CastI, &I);
+      ReturnInst *RetI = new ReturnInst(CastI, &RI);
 
       // Remove original return instruction
-      I.getParent()->getInstList().erase(&I);
+      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 &I) {
+void FuncTransform::visitStoreInst (StoreInst &SI) {
   // Check if a constant function is being stored
-  if (Value *clonedFunc = retCloneIfFunc(I.getOperand(0))) {
-    CastInst *CastI = new CastInst(clonedFunc, I.getOperand(0)->getType(), 
-				   "tmp", &I);
-    new StoreInst(CastI, I.getOperand(1), &I);
-    I.getParent()->getInstList().erase(&I);
+  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 &I) {
+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(&I)) {
-    PHINode *V = new PHINode(I.getType(), I.getName(), &I);
-    for (unsigned i = 0 ; i < I.getNumIncomingValues(); ++i) {
-      if (Value *clonedFunc = retCloneIfFunc(I.getIncomingValue(i))) {
-	// Insert CastInst at the end of  I.getIncomingBlock(i)
-	BasicBlock::iterator BBI = --I.getIncomingBlock(i)->end();
+  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, I.getType(), "tmp", BBI);
-	V->addIncoming(CastI, I.getIncomingBlock(i));
+	CastInst *CastI = new CastInst(clonedFunc, PI.getType(), "tmp", BBI);
+	V->addIncoming(CastI, PI.getIncomingBlock(i));
       } else {
-	V->addIncoming(I.getIncomingValue(i), I.getIncomingBlock(i));
+	V->addIncoming(PI.getIncomingValue(i), PI.getIncomingBlock(i));
       }
       
     }
-    I.replaceAllUsesWith(V);
-    I.getParent()->getInstList().erase(&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);
+    }
   }
 }
 
@@ -660,12 +782,16 @@
   
   MI.setName("");  // Nuke MIs name
   
-  // Cast to the appropriate type...
-  Value *Casted = new CastInst(V, MI.getType(), V->getName(), &MI);
-  
+  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);
   
@@ -676,56 +802,96 @@
   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));
+    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));
-    FI.NewToOldValueMap.insert(std::make_pair(Casted, MII->second));
+    if (V != Casted)
+      FI.NewToOldValueMap.insert(std::make_pair(Casted, MII->second));
     FI.NewToOldValueMap.erase(MII);
   }
 }
 
-void FuncTransform::visitFreeInst(FreeInst &FI) {
-  Value *Arg = FI.getOperand(0);
+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;
   // 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);
-  
+  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...
-  FI.getParent()->getInstList().erase(&FI);
+  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(DSNode *Caller, DSNode *Callee,
+static void CalcNodeMapping(DSNodeHandle& Caller, DSNodeHandle& Callee,
                             std::map<DSNode*, DSNode*> &NodeMapping) {
-  if (Callee == 0) return;
-  // assert(Caller && "Callee has node but caller doesn't??");
+  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 (Caller == 0) {
-    NodeMapping.insert(NodeMapping.end(), std::make_pair(Callee, (DSNode*) 0));
+  if (CallerNode == 0) {
+    NodeMapping.insert(NodeMapping.end(), std::make_pair(CalleeNode, 
+							 (DSNode *) 0));
   }
 
-  std::map<DSNode*, DSNode*>::iterator I = NodeMapping.find(Callee);
+  // 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 == Caller && "Node maps to different nodes on paths?");
+    assert(I->second == CallerNode && 
+	   "Node maps to different nodes on paths?");
   } else {
-    NodeMapping.insert(I, std::make_pair(Callee, Caller));
+    NodeMapping.insert(I, std::make_pair(CalleeNode, CallerNode));
     
-    // Recursively add pointed to nodes...
-    unsigned numCallerLinks = Caller->getNumLinks();
-    unsigned numCalleeLinks = Callee->getNumLinks();
+    if (CalleeNode->getType() != CallerNode->getType() && CallerOffset == 0) 
+      DEBUG(std::cerr << "NB: Mapping of nodes between different types\n");
 
-    assert (numCallerLinks <= numCalleeLinks || numCalleeLinks == 0);
-    
-    for (unsigned i = 0, e = numCalleeLinks; i != e; ++i)
-      CalcNodeMapping(Caller->getLink((i%numCallerLinks) << DS::PointerShift).getNode(), Callee->getLink(i << DS::PointerShift).getNode(), NodeMapping);
+    // 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) {
+	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) {
+      std::cerr << 
+	"Caller has unexpanded node, due to indirect call perhaps!\n";
+    }
   }
 }
 
@@ -750,6 +916,8 @@
 
   }
 
+  DSGraph &CallerG = G;
+
   std::vector<Value*> Args;  
   if (!CF) {   // Indirect call
     DEBUG(std::cerr << "  Handling call: " << CI);
@@ -781,17 +949,27 @@
       unsigned OpNum = 1;
       for ( ; AI != AE; ++AI, ++OpNum) {
 	if (!isa<Constant>(CI.getOperand(OpNum)))
-	  CalcNodeMapping(getDSNodeFor(CI.getOperand(OpNum)), 
-			  CG.getScalarMap()[AI].getNode(),
+	  CalcNodeMapping(getDSNodeHFor(CI.getOperand(OpNum)), 
+			  CG.getScalarMap()[AI],
 			  NodeMapping);
       }
       assert(OpNum == CI.getNumOperands() && "Varargs calls not handled yet!");
       
       if (CI.getType() != Type::VoidTy)
-	CalcNodeMapping(getDSNodeFor(&CI),
-                        CG.getReturnNodeFor(*TFI->second).getNode(), 
+	CalcNodeMapping(getDSNodeHFor(&CI),
+                        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 
@@ -845,6 +1023,30 @@
 
     CI.replaceAllUsesWith(NewCall);
     DEBUG(std::cerr << "  Result Call: " << *NewCall);
+      
+    if (CI.getType() != Type::VoidTy) {
+      // If we are modifying the original function, update the DSGraph... 
+      DSGraph::ScalarMapTy &SM = G.getScalarMap();
+      DSGraph::ScalarMapTy::iterator CII = SM.find(&CI); 
+      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(&CI);
+	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(&CI);
+      assert(II != FI.NewToOldValueMap.end() && 
+	     "CI not found in clone?");
+      FI.NewToOldValueMap.insert(std::make_pair(NewCall, II->second));
+      FI.NewToOldValueMap.erase(II);
+    }
   }
   else {
 
@@ -855,7 +1057,7 @@
     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
@@ -867,21 +1069,27 @@
     Function::aiterator AI = CF->abegin(), AE = CF->aend();
     unsigned OpNum = 1;
     for (; AI != AE; ++AI, ++OpNum) {
-      // Check if the operand of the call is a return of another call
-      // for the operand will be transformed in which case.
-      // Look up the OldToNewRetValMap to see if the operand is a new value.
       Value *callOp = CI.getOperand(OpNum);
       if (!isa<Constant>(callOp))
-	CalcNodeMapping(getDSNodeFor(callOp),CG.getScalarMap()[AI].getNode(), 
+	CalcNodeMapping(getDSNodeHFor(callOp), CG.getScalarMap()[AI], 
 			NodeMapping);
     }
     assert(OpNum == CI.getNumOperands() && "Varargs calls not handled yet!");
     
     // Map the return value as well...
     if (CI.getType() != Type::VoidTy)
-      CalcNodeMapping(getDSNodeFor(&CI), CG.getReturnNodeFor(*CF).getNode(),
+      CalcNodeMapping(getDSNodeHFor(&CI), 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...
 
@@ -893,13 +1101,12 @@
 
     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;
 	if (LocalNode) {
 	  assert(FI.PoolDescriptors.count(LocalNode) && "Node not pool allocated?");
 	  Args.push_back(FI.PoolDescriptors.find(LocalNode)->second);
-	}
-	else
+	} else
 	  Args.push_back(Constant::getNullValue(PoolDescPtr));
       } else {
 	Args.push_back(Constant::getNullValue(PoolDescPtr));
@@ -917,11 +1124,38 @@
     Args.insert(Args.end(), CI.op_begin()+1, CI.op_end());
     
     std::string Name = CI.getName(); 
+
+    std::map<Value*,const Value*>::iterator CNewII; 
+    
     Value *NewCall = new CallInst(CFI->Clone, Args, Name, &CI);
+
     CI.replaceAllUsesWith(NewCall);
     DEBUG(std::cerr << "  Result Call: " << *NewCall);
 
+    if (CI.getType() != Type::VoidTy) {
+      // If we are modifying the original function, update the DSGraph... 
+      DSGraph::ScalarMapTy &SM = G.getScalarMap();
+      DSGraph::ScalarMapTy::iterator CII = SM.find(&CI); 
+      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(&CI);
+	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(&CI);
+      assert(II != FI.NewToOldValueMap.end() && "CI not found in clone?");
+      FI.NewToOldValueMap.insert(std::make_pair(NewCall, II->second));
+      FI.NewToOldValueMap.erase(II);
+    }
   }
-  
+
   CI.getParent()->getInstList().erase(&CI);
 }





More information about the llvm-commits mailing list