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

Chris Lattner lattner at cs.uiuc.edu
Thu Feb 19 16:47:01 PST 2004


Changes in directory poolalloc/lib/PoolAllocate:

TransformFunctionBody.cpp updated: 1.17 -> 1.18

---
Log message:

Implement pool allocator support for calloc and realloc, turning them into 
the appropriate combination poolallocator calls and memset/memcpy calls.


---
Diffs of the changes:  (+155 -45)

Index: poolalloc/lib/PoolAllocate/TransformFunctionBody.cpp
diff -u poolalloc/lib/PoolAllocate/TransformFunctionBody.cpp:1.17 poolalloc/lib/PoolAllocate/TransformFunctionBody.cpp:1.18
--- poolalloc/lib/PoolAllocate/TransformFunctionBody.cpp:1.17	Thu Feb 19 15:28:11 2004
+++ poolalloc/lib/PoolAllocate/TransformFunctionBody.cpp	Thu Feb 19 16:46:18 2004
@@ -8,7 +8,7 @@
 #include "poolalloc/PoolAllocate.h"
 #include "llvm/Analysis/DataStructure.h"
 #include "llvm/Analysis/DSGraph.h"
-#include "llvm/Function.h"
+#include "llvm/Module.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Constants.h"
 #include "llvm/Instructions.h"
@@ -52,6 +52,8 @@
 
     void visitInstruction(Instruction &I);
     void visitMallocInst(MallocInst &MI);
+    void visitCallocCall(CallSite CS);
+    void visitReallocCall(CallSite CS);
     void visitFreeInst(FreeInst &FI);
     void visitCallSite(CallSite CS);
     void visitCallInst(CallInst &CI) { visitCallSite(&CI); }
@@ -60,6 +62,9 @@
     void visitStoreInst (StoreInst &I);
 
   private:
+    Instruction *TransformAllocationInstr(Instruction *I, Value *Size);
+    Instruction *InsertPoolFreeInstr(Value *V, Instruction *Where);
+
     void UpdateNewToOldValueMap(Value *OldVal, Value *NewV1, Value *NewV2) {
       std::map<Value*, const Value*>::iterator I =
         FI.NewToOldValueMap.find(OldVal);
@@ -125,79 +130,167 @@
   visitInstruction(SI);
 }
 
-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("");
+Instruction *FuncTransform::TransformAllocationInstr(Instruction *I,
+                                                     Value *Size) {
+  std::string Name = I->getName(); I->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);
-
-  Instruction *V = new CallInst(PAInfo.PoolAlloc, make_vector(PH, AllocSize, 0),
-                                Name, &MI);
+  Value *PH = getPoolHandle(I);
+  Instruction *V = new CallInst(PAInfo.PoolAlloc, make_vector(PH, Size, 0),
+                                Name, I);
 
   AddPoolUse(*V, PH, PoolUses);
 
   // Cast to the appropriate type if necessary
-  Value *Casted = V;
-  if (V->getType() != MI.getType())
-    Casted = new CastInst(V, MI.getType(), V->getName(), &MI);
+  Instruction *Casted = V;
+  if (V->getType() != I->getType())
+    Casted = new CastInst(V, I->getType(), V->getName(), I);
     
   // Update def-use info
-  MI.replaceAllUsesWith(Casted);
+  I->replaceAllUsesWith(Casted);
 
-  // If we are modifying the original function, update the DSGraph... 
+  // If we are modifying the original function, update the DSGraph.
   if (!FI.Clone) {
-    G.getScalarMap().replaceScalar(&MI, V);
+    // V and Casted now point to whatever the original allocation did.
+    G.getScalarMap().replaceScalar(I, V);
     if (V != Casted)
       G.getScalarMap()[Casted] = G.getScalarMap()[V];
   } else {             // Otherwise, update the NewToOldValueMap
-    UpdateNewToOldValueMap(&MI, V, V != Casted ? Casted : 0);
+    UpdateNewToOldValueMap(I, V, V != Casted ? Casted : 0);
   }
 
-  // Remove old malloc instruction
-  MI.getParent()->getInstList().erase(&MI);
+  // Remove old allocation instruction.
+  I->getParent()->getInstList().erase(I);
+  return Casted;
 }
 
-void FuncTransform::visitFreeInst(FreeInst &FrI) {
-  Value *Arg = FrI.getOperand(0);
-  Value *PH = getPoolHandle(Arg);  // Get the pool handle for this DSNode...
+
+void FuncTransform::visitMallocInst(MallocInst &MI) {
+  // Get the pool handle for the node that this contributes to...
+  Value *PH = getPoolHandle(&MI);
   if (PH == 0) return;
 
+  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);
+
+  TransformAllocationInstr(&MI, AllocSize);
+}
+
+
+Instruction *FuncTransform::InsertPoolFreeInstr(Value *Arg, Instruction *Where){
+  Value *PH = getPoolHandle(Arg);  // Get the pool handle for this DSNode...
+  if (PH == 0) return 0;
+
   // 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);
+				 Arg->getName()+".casted", Where);
 
   CallInst *FreeI = new CallInst(PAInfo.PoolFree, make_vector(PH, Casted, 0), 
-				 "", &FrI);
-  // Delete the now obsolete free instruction...
-  FrI.getParent()->getInstList().erase(&FrI);
-
+				 "", Where);
   AddPoolUse(*FreeI, PH, PoolFrees);
-  
-  // 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);
+  return FreeI;
+}
+
+
+void FuncTransform::visitFreeInst(FreeInst &FrI) {
+  if (Instruction *I = InsertPoolFreeInstr(FrI.getOperand(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(I, II->second));
+      FI.NewToOldValueMap.erase(II);
+    }
+  }
+}
+
+
+void FuncTransform::visitCallocCall(CallSite CS) {
+  Module *M = CS.getInstruction()->getParent()->getParent()->getParent();
+  assert(CS.arg_end()-CS.arg_begin() == 2 && "calloc takes two arguments!");
+  Value *V1 = *CS.arg_begin();
+  Value *V2 = *(CS.arg_begin()+1);
+  if (V1->getType() != V2->getType()) {
+    V1 = new CastInst(V1, Type::UIntTy, V1->getName(), CS.getInstruction());
+    V2 = new CastInst(V2, Type::UIntTy, V2->getName(), CS.getInstruction());
   }
+
+  V2 = BinaryOperator::create(Instruction::Mul, V1, V2, "size",
+                              CS.getInstruction());
+  if (V2->getType() != Type::UByteTy)
+    V2 = new CastInst(V2, Type::UIntTy, V2->getName(), CS.getInstruction());
+
+  BasicBlock::iterator BBI =
+    TransformAllocationInstr(CS.getInstruction(), V2);
+  Value *Ptr = BBI++;
+
+  // We just turned the call of 'calloc' into the equivalent of malloc.  To
+  // finish calloc, we need to zero out the memory.
+  Function *MemSet = M->getOrInsertFunction("llvm.memset",
+                                            Type::VoidTy,
+                                            PointerType::get(Type::SByteTy),
+                                            Type::UByteTy, Type::UIntTy,
+                                            Type::UIntTy, 0);
+
+  if (Ptr->getType() != PointerType::get(Type::SByteTy))
+    Ptr = new CastInst(Ptr, PointerType::get(Type::SByteTy), Ptr->getName(),
+                       BBI);
+  
+  // We know that the memory returned by poolalloc is at least 4 byte aligned.
+  new CallInst(MemSet, make_vector(Ptr, ConstantUInt::get(Type::UByteTy, 0),
+                                   V2,  ConstantUInt::get(Type::UIntTy, 4), 0),
+               "", BBI);
+}
+
+
+void FuncTransform::visitReallocCall(CallSite CS) {
+  Module *M = CS.getInstruction()->getParent()->getParent()->getParent();
+  assert(CS.arg_end()-CS.arg_begin() == 2 && "realloc takes two arguments!");
+  Value *OldPtr = *CS.arg_begin();
+  Value *Size = *(CS.arg_begin()+1);
+
+  BasicBlock::iterator BBI =
+    TransformAllocationInstr(CS.getInstruction(), Size);
+  Value *NewPtr = BBI++;
+
+  // We just turned the call of 'realloc' into the equivalent of malloc.  To
+  // finish realloc, we need to copy the memory from the old block to the new,
+  // then free the old block.
+  const Type *SBPtr = PointerType::get(Type::SByteTy);
+  Function *MemCpy = M->getOrInsertFunction("llvm.memcpy",
+                                            Type::VoidTy, SBPtr, SBPtr,
+                                            Type::UIntTy, Type::UIntTy, 0);
+
+  if (NewPtr->getType() != SBPtr)
+    NewPtr = new CastInst(NewPtr, SBPtr, NewPtr->getName(), BBI);
+  if (OldPtr->getType() != SBPtr)
+    OldPtr = new CastInst(OldPtr, SBPtr, OldPtr->getName(), BBI);
+  if (Size->getType() != Type::UIntTy)
+    Size = new CastInst(Size, Type::UIntTy, Size->getName(), BBI);
+  
+  // We know that the memory returned by poolalloc is at least 4 byte aligned.
+  new CallInst(MemCpy, make_vector(NewPtr, OldPtr, Size, 
+                                   ConstantUInt::get(Type::UIntTy, 4), 0),
+               "", BBI);
+
+  // Free the old memory now.
+  InsertPoolFreeInstr(OldPtr, BBI);
 }
 
+
+
 void FuncTransform::visitCallSite(CallSite CS) {
   Function *CF = CS.getCalledFunction();
   Instruction *TheCall = CS.getInstruction();
@@ -217,6 +310,23 @@
           CF = dyn_cast<Function>(CPR->getValue());
     }
   }
+
+  // If this function is one of the memory manipulating functions built into
+  // libc, emulate it with pool calls as appropriate.
+  if (CF && CF->isExternal())
+    if (CF->getName() == "calloc") {
+      visitCallocCall(CS);
+      return;
+    } else if (CF->getName() == "realloc") {
+      visitReallocCall(CS);
+      return;
+    } else if (CF->getName() == "strdup") {
+      assert(0 && "strdup should have been linked into the program!");
+    } else if (CF->getName() == "memalign" ||
+               CF->getName() == "posix_memalign") {
+      std::cerr << "MEMALIGN USED BUT NOT HANDLED!\n";
+      abort();
+    }
 
   // We need to figure out which local pool descriptors correspond to the pool
   // descriptor arguments passed into the function call.  Calculate a mapping





More information about the llvm-commits mailing list