[llvm-commits] [llvm] r82257 - in /llvm/trunk: include/llvm/Analysis/MallocHelper.h include/llvm/Instructions.h lib/Analysis/MallocHelper.cpp lib/Transforms/Utils/LowerAllocations.cpp lib/VMCore/Instruction.cpp lib/VMCore/Instructions.cpp lib/VMCore/Verifier.cpp

Victor Hernandez vhernandez at apple.com
Fri Sep 18 12:20:02 PDT 2009


Author: hernande
Date: Fri Sep 18 14:20:02 2009
New Revision: 82257

URL: http://llvm.org/viewvc/llvm-project?rev=82257&view=rev
Log:
Update malloc call creation code (AllocType is now the element type of the malloc, not the resulting type).

In getMallocArraySize(), fix bug in the case that array size is the product of 2 constants.

Extend isArrayMalloc() and getMallocArraySize() to handle case where malloc is used as char array.

Ensure that ArraySize in LowerAllocations::runOnBasicBlock() is correct type.

Extend Instruction::isSafeToSpeculativelyExecute() to handle malloc calls.

Add verification for malloc calls.

Reviewed by Dan Gohman.


Modified:
    llvm/trunk/include/llvm/Analysis/MallocHelper.h
    llvm/trunk/include/llvm/Instructions.h
    llvm/trunk/lib/Analysis/MallocHelper.cpp
    llvm/trunk/lib/Transforms/Utils/LowerAllocations.cpp
    llvm/trunk/lib/VMCore/Instruction.cpp
    llvm/trunk/lib/VMCore/Instructions.cpp
    llvm/trunk/lib/VMCore/Verifier.cpp

Modified: llvm/trunk/include/llvm/Analysis/MallocHelper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/MallocHelper.h?rev=82257&r1=82256&r2=82257&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Analysis/MallocHelper.h (original)
+++ llvm/trunk/include/llvm/Analysis/MallocHelper.h Fri Sep 18 14:20:02 2009
@@ -16,11 +16,10 @@
 #define LLVM_ANALYSIS_MALLOCHELPER_H
 
 namespace llvm {
-class BitCastInst;
 class CallInst;
-class Instruction;
+class LLVMContext;
 class PointerType;
-class Twine;
+class TargetData;
 class Type;
 class Value;
 
@@ -31,7 +30,6 @@
 /// isMalloc - Returns true if the the value is either a malloc call or a
 /// bitcast of the result of a malloc call
 bool isMalloc(const Value* I);
-bool isMalloc(Value* I);
 
 /// extractMallocCall - Returns the corresponding CallInst if the instruction
 /// is a malloc call.  Since CallInst::CreateMalloc() only creates calls, we
@@ -54,8 +52,9 @@
 /// Otherwise it returns NULL.
 /// The unique bitcast is needed to determine the type/size of the array
 /// allocation.
-CallInst* isArrayMalloc(Value* I);
-const CallInst* isArrayMalloc(const Value* I);
+CallInst* isArrayMalloc(Value* I, LLVMContext &Context, const TargetData* TD);
+const CallInst* isArrayMalloc(const Value* I, LLVMContext &Context,
+                              const TargetData* TD);
 
 /// getMallocType - Returns the PointerType resulting from the malloc call.
 /// This PointerType is the result type of the call's only bitcast use.
@@ -79,7 +78,8 @@
 ///  1. The malloc call's allocated type cannot be determined.
 ///  2. IR wasn't created by a call to CallInst::CreateMalloc() with a non-NULL
 ///     ArraySize.
-Value* getMallocArraySize(CallInst* CI);
+Value* getMallocArraySize(CallInst* CI, LLVMContext &Context,
+                          const TargetData* TD);
 
 } // End llvm namespace
 

Modified: llvm/trunk/include/llvm/Instructions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instructions.h?rev=82257&r1=82256&r2=82257&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Instructions.h (original)
+++ llvm/trunk/include/llvm/Instructions.h Fri Sep 18 14:20:02 2009
@@ -1039,12 +1039,12 @@
   ///    constant 1.
   /// 2. Call malloc with that argument.
   /// 3. Bitcast the result of the malloc call to the specified type.
-  static Value *CreateMalloc(Instruction *I,
-                             const Type *AllocTy, const Type *IntPtrTy,
-                             Value *ArraySize = 0, const Twine &NameStr = "");
-  static Value *CreateMalloc(BasicBlock *InsertAtEnd,
-                             const Type *AllocTy, const Type *IntPtrTy,
-                             Value *ArraySize = 0, const Twine &NameStr = "");
+  static Value *CreateMalloc(Instruction *InsertBefore, const Type *IntPtrTy,
+                             const Type *AllocTy, Value *ArraySize = 0,
+                             const Twine &Name = "");
+  static Value *CreateMalloc(BasicBlock *InsertAtEnd, const Type *IntPtrTy,
+                             const Type *AllocTy, Value *ArraySize = 0,
+                             const Twine &Name = "");
 
   ~CallInst();
 

Modified: llvm/trunk/lib/Analysis/MallocHelper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MallocHelper.cpp?rev=82257&r1=82256&r2=82257&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/MallocHelper.cpp (original)
+++ llvm/trunk/lib/Analysis/MallocHelper.cpp Fri Sep 18 14:20:02 2009
@@ -16,6 +16,7 @@
 #include "llvm/Constants.h"
 #include "llvm/Instructions.h"
 #include "llvm/Module.h"
+#include "llvm/Analysis/ConstantFolding.h"
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
@@ -24,10 +25,6 @@
 
 /// isMalloc - Returns true if the the value is either a malloc call or a
 /// bitcast of the result of a malloc call.
-bool llvm::isMalloc(Value* I) {
-  return extractMallocCall(I) || extractMallocCallFromBitCast(I);
-}
-
 bool llvm::isMalloc(const Value* I) {
   return extractMallocCall(I) || extractMallocCallFromBitCast(I);
 }
@@ -79,40 +76,42 @@
                                       : NULL;
 }
 
-static bool isArrayMallocHelper(const CallInst *CI) {
+static bool isArrayMallocHelper(const CallInst *CI, LLVMContext &Context,
+                                const TargetData* TD) {
   if (!CI)
     return false;
 
-  // Only identify array mallocs for mallocs with 1 bitcast use.  The unique 
-  // bitcast is needed to determine the type/size of the array allocation.
-  if (!CI->hasOneUse()) return false;
+  const Type* T = getMallocAllocatedType(CI);
 
-  for (Value::use_const_iterator UI = CI->use_begin(), E = CI->use_end();
-       UI != E; )
-    if (!isa<BitCastInst>(cast<Instruction>(*UI++)))
-      return false;
+  // We can only indentify an array malloc if we know the type of the malloc 
+  // call.
+  if (!T) return false;
 
-  // malloc arg
   Value* MallocArg = CI->getOperand(1);
-  // element size
-  const Type* T = getMallocAllocatedType(CI);
-  if (!T) return false;
   Constant *ElementSize = ConstantExpr::getSizeOf(T);
-  
+  ElementSize = ConstantExpr::getTruncOrBitCast(ElementSize, 
+                                                MallocArg->getType());
+  Constant *FoldedElementSize = ConstantFoldConstantExpression(
+                                       cast<ConstantExpr>(ElementSize), 
+                                       Context, TD);
+
+
   if (isa<ConstantExpr>(MallocArg))
-    return (MallocArg == ElementSize) ? false : true;
+    return (MallocArg != ElementSize);
 
   BinaryOperator *BI = dyn_cast<BinaryOperator>(MallocArg);
   if (!BI)
     return false;
 
-  if (BI->getOpcode() != Instruction::Mul)
-    return false;
-      
-  if (BI->getOperand(1) != ElementSize)
-    return false;
-        
-  return true;
+  if (BI->getOpcode() == Instruction::Mul)
+    // ArraySize * ElementSize
+    if (BI->getOperand(1) == ElementSize ||
+        (FoldedElementSize && BI->getOperand(1) == FoldedElementSize))
+      return true;
+
+  // TODO: Detect case where MallocArg mul has been transformed to shl.
+
+  return false;
 }
 
 /// isArrayMalloc - Returns the corresponding CallInst if the instruction 
@@ -125,14 +124,16 @@
 /// Otherwise it returns NULL.
 /// The unique bitcast is needed to determine the type/size of the array
 /// allocation.
-CallInst* llvm::isArrayMalloc(Value* I) {
+CallInst* llvm::isArrayMalloc(Value* I, LLVMContext &Context,
+                              const TargetData* TD) {
   CallInst *CI = extractMallocCall(I);
-  return (isArrayMallocHelper(CI)) ? CI : NULL;
+  return (isArrayMallocHelper(CI, Context, TD)) ? CI : NULL;
 }
 
-const CallInst* llvm::isArrayMalloc(const Value* I) {
+const CallInst* llvm::isArrayMalloc(const Value* I, LLVMContext &Context,
+                                    const TargetData* TD) {
   const CallInst *CI = extractMallocCall(I);
-  return (isArrayMallocHelper(CI)) ? CI : NULL;
+  return (isArrayMallocHelper(CI, Context, TD)) ? CI : NULL;
 }
 
 /// getMallocType - Returns the PointerType resulting from the malloc call.
@@ -142,14 +143,24 @@
   assert(isMalloc(CI) && "GetMallocType and not malloc call");
   
   const BitCastInst* BCI = NULL;
+  
+  // Determine if CallInst has a bitcast use.
+  for (Value::use_const_iterator UI = CI->use_begin(), E = CI->use_end();
+       UI != E; )
+    if ((BCI = dyn_cast<BitCastInst>(cast<Instruction>(*UI++))))
+      break;
+
+  // Malloc call has 1 bitcast use and no other uses, so type is the bitcast's
+  // destination type.
+  if (BCI && CI->hasOneUse())
+    return cast<PointerType>(BCI->getDestTy());
 
-  // Determine type only if there is only 1 bitcast use of CI.
-  if (CI->hasOneUse())
-    for (Value::use_const_iterator UI = CI->use_begin(), E = CI->use_end();
-         UI != E; )
-      BCI = dyn_cast<BitCastInst>(cast<Instruction>(*UI++));
+  // Malloc call was not bitcast, so the type is the malloc's return type, i8*.
+  if (!BCI)
+    return cast<PointerType>(CI->getType());
 
-  return BCI ? reinterpret_cast<const PointerType*>(BCI->getDestTy()) : NULL;
+  // Type could not be determined.
+  return NULL;
 }
 
 /// getMallocAllocatedType - Returns the Type allocated by malloc call. This
@@ -177,15 +188,16 @@
 ///  1. The malloc call's allocated type cannot be determined.
 ///  2. IR wasn't created by a call to CallInst::CreateMalloc() with a non-NULL
 ///     ArraySize.
-Value* llvm::getMallocArraySize(CallInst* CI) {
+Value* llvm::getMallocArraySize(CallInst* CI, LLVMContext &Context,
+                                const TargetData* TD) {
   // Match CreateMalloc's use of constant 1 array-size for non-array mallocs.
-  if (!isArrayMalloc(CI))
+  if (!isArrayMalloc(CI, Context, TD))
     return ConstantInt::get(CI->getOperand(1)->getType(), 1);
 
   Value* MallocArg = CI->getOperand(1);
   assert(getMallocAllocatedType(CI) && "getMallocArraySize and no type");
   Constant *ElementSize = ConstantExpr::getSizeOf(getMallocAllocatedType(CI));
-  ElementSize = ConstantExpr::getTruncOrBitCast(cast<Constant>(ElementSize), 
+  ElementSize = ConstantExpr::getTruncOrBitCast(ElementSize, 
                                                 MallocArg->getType());
 
   Constant* CO = dyn_cast<Constant>(MallocArg);
@@ -195,10 +207,12 @@
       
   if (isConstantOne(ElementSize))
     return MallocArg;
+    
+  if (CO)
+    return CO->getOperand(0);
+    
+  // TODO: Detect case where MallocArg mul has been transformed to shl.
 
-  if (CO) 
-    return ConstantExpr::getUDiv(CO, ElementSize);
-  
   assert(BO && "getMallocArraySize not constant but not multiplication either");
   return BO->getOperand(0);
 }

Modified: llvm/trunk/lib/Transforms/Utils/LowerAllocations.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LowerAllocations.cpp?rev=82257&r1=82256&r2=82257&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LowerAllocations.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LowerAllocations.cpp Fri Sep 18 14:20:02 2009
@@ -108,8 +108,12 @@
   // Loop over all of the instructions, looking for malloc or free instructions
   for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) {
     if (MallocInst *MI = dyn_cast<MallocInst>(I)) {
-      Value *MCast = CallInst::CreateMalloc(I, MI->getType(), IntPtrTy,
-                                            MI->getOperand(0));
+      Value *ArraySize = MI->getOperand(0);
+      if (ArraySize->getType() != IntPtrTy)
+        ArraySize = CastInst::CreateIntegerCast(ArraySize, IntPtrTy,
+                                                false /*ZExt*/, "", I);
+      Value *MCast = CallInst::CreateMalloc(I, IntPtrTy,
+                                            MI->getAllocatedType(), ArraySize);
 
       // Replace all uses of the old malloc inst with the cast inst
       MI->replaceAllUsesWith(MCast);

Modified: llvm/trunk/lib/VMCore/Instruction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instruction.cpp?rev=82257&r1=82256&r2=82257&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Instruction.cpp (original)
+++ llvm/trunk/lib/VMCore/Instruction.cpp Fri Sep 18 14:20:02 2009
@@ -16,6 +16,7 @@
 #include "llvm/Function.h"
 #include "llvm/Constants.h"
 #include "llvm/GlobalVariable.h"
+#include "llvm/Module.h"
 #include "llvm/Support/CallSite.h"
 #include "llvm/Support/LeakDetector.h"
 using namespace llvm;
@@ -375,6 +376,27 @@
   }
 }
 
+// Code here matches isMalloc from MallocHelper, which is not in VMCore.
+static bool isMalloc(const Value* I) {
+  const CallInst *CI = dyn_cast<CallInst>(I);
+  if (!CI) {
+  	const BitCastInst *BCI = dyn_cast<BitCastInst>(I);
+	if (!BCI) return false;
+
+    CI = dyn_cast<CallInst>(BCI->getOperand(0));
+  }
+
+  if (!CI) return false;
+
+  const Module* M = CI->getParent()->getParent()->getParent();
+  Constant *MallocFunc = M->getFunction("malloc");
+
+  if (CI->getOperand(0) != MallocFunc)
+    return false;
+
+  return true;
+}
+
 bool Instruction::isSafeToSpeculativelyExecute() const {
   for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
     if (Constant *C = dyn_cast<Constant>(getOperand(i)))
@@ -400,7 +422,7 @@
   case Load: {
     if (cast<LoadInst>(this)->isVolatile())
       return false;
-    if (isa<AllocationInst>(getOperand(0)))
+    if (isa<AllocationInst>(getOperand(0)) || isMalloc(getOperand(0)))
       return true;
     if (GlobalVariable *GV = dyn_cast<GlobalVariable>(getOperand(0)))
       return !GV->hasExternalWeakLinkage();

Modified: llvm/trunk/lib/VMCore/Instructions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=82257&r1=82256&r2=82257&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Instructions.cpp (original)
+++ llvm/trunk/lib/VMCore/Instructions.cpp Fri Sep 18 14:20:02 2009
@@ -460,19 +460,20 @@
 }
 
 static Value *createMalloc(Instruction *InsertBefore, BasicBlock *InsertAtEnd,
-                           const Type *AllocTy, const Type *IntPtrTy,
+                           const Type *IntPtrTy, const Type *AllocTy,
                            Value *ArraySize, const Twine &NameStr) {
   assert(((!InsertBefore && InsertAtEnd) || (InsertBefore && !InsertAtEnd)) &&
-         "createMalloc needs only InsertBefore or InsertAtEnd");
-  const PointerType *AllocPtrType = dyn_cast<PointerType>(AllocTy);
-  assert(AllocPtrType && "CreateMalloc passed a non-pointer allocation type");
-  
-  ArraySize = checkArraySize(ArraySize, IntPtrTy);
+         "createMalloc needs either InsertBefore or InsertAtEnd");
 
-  // malloc(type) becomes i8 *malloc(size)
-  Value *AllocSize = ConstantExpr::getSizeOf(AllocPtrType->getElementType());
-  AllocSize = ConstantExpr::getTruncOrBitCast(cast<Constant>(AllocSize), 
+  // malloc(type) becomes: 
+  //       bitcast (i8* malloc(typeSize)) to type*
+  // malloc(type, arraySize) becomes:
+  //       bitcast (i8 *malloc(typeSize*arraySize)) to type*
+  Value *AllocSize = ConstantExpr::getSizeOf(AllocTy);
+  AllocSize = ConstantExpr::getTruncOrBitCast(cast<Constant>(AllocSize),
                                               IntPtrTy);
+  ArraySize = checkArraySize(ArraySize, IntPtrTy);
+
   if (!IsConstantOne(ArraySize)) {
     if (IsConstantOne(AllocSize)) {
       AllocSize = ArraySize;         // Operand * 1 = Operand
@@ -482,47 +483,41 @@
       // Malloc arg is constant product of type size and array size
       AllocSize = ConstantExpr::getMul(Scale, cast<Constant>(AllocSize));
     } else {
-      Value *Scale = ArraySize;
-      if (Scale->getType() != IntPtrTy) {
-        if (InsertBefore)
-          Scale = CastInst::CreateIntegerCast(Scale, IntPtrTy, false /*ZExt*/,
-                                              "", InsertBefore);
-        else
-          Scale = CastInst::CreateIntegerCast(Scale, IntPtrTy, false /*ZExt*/,
-                                              "", InsertAtEnd);
-      }
       // Multiply type size by the array size...
       if (InsertBefore)
-        AllocSize = BinaryOperator::CreateMul(Scale, AllocSize,
-                                              "", InsertBefore);
+        AllocSize = BinaryOperator::CreateMul(ArraySize, AllocSize,
+                                              "mallocsize", InsertBefore);
       else
-        AllocSize = BinaryOperator::CreateMul(Scale, AllocSize,
-                                              "", InsertAtEnd);
+        AllocSize = BinaryOperator::CreateMul(ArraySize, AllocSize,
+                                              "mallocsize", InsertAtEnd);
     }
   }
 
+  assert(AllocSize->getType() == IntPtrTy && "malloc arg is wrong size");
   // Create the call to Malloc.
   BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
   Module* M = BB->getParent()->getParent();
   const Type *BPTy = PointerType::getUnqual(Type::getInt8Ty(BB->getContext()));
   // prototype malloc as "void *malloc(size_t)"
-  Constant *MallocFunc = M->getOrInsertFunction("malloc", BPTy, 
-                                                IntPtrTy, NULL);
+  Constant *MallocF = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, NULL);
+  if (!cast<Function>(MallocF)->doesNotAlias(0))
+    cast<Function>(MallocF)->setDoesNotAlias(0);
+  const PointerType *AllocPtrType = PointerType::getUnqual(AllocTy);
   CallInst *MCall = NULL;
-  if (InsertBefore) 
-    MCall = CallInst::Create(MallocFunc, AllocSize, NameStr, InsertBefore);
-  else
-    MCall = CallInst::Create(MallocFunc, AllocSize, NameStr, InsertAtEnd);
+  Value    *MCast = NULL;
+  if (InsertBefore) {
+    MCall = CallInst::Create(MallocF, AllocSize, "malloccall", InsertBefore);
+    // Create a cast instruction to convert to the right type...
+    MCast = new BitCastInst(MCall, AllocPtrType, NameStr, InsertBefore);
+  } else {
+    MCall = CallInst::Create(MallocF, AllocSize, "malloccall", InsertAtEnd);
+    // Create a cast instruction to convert to the right type...
+    MCast = new BitCastInst(MCall, AllocPtrType, NameStr);
+  }
   MCall->setTailCall();
-
-  // Create a cast instruction to convert to the right type...
   assert(MCall->getType() != Type::getVoidTy(BB->getContext()) &&
          "Malloc has void return type");
-  Value *MCast;
-  if (InsertBefore)
-    MCast = new BitCastInst(MCall, AllocPtrType, NameStr, InsertBefore);
-  else
-    MCast = new BitCastInst(MCall, AllocPtrType, NameStr);
+
   return MCast;
 }
 
@@ -532,11 +527,10 @@
 ///    constant 1.
 /// 2. Call malloc with that argument.
 /// 3. Bitcast the result of the malloc call to the specified type.
-Value *CallInst::CreateMalloc(Instruction *InsertBefore,
-                              const Type *AllocTy, const Type *IntPtrTy,
-                              Value *ArraySize, const Twine &NameStr) {
-  return createMalloc(InsertBefore, NULL, AllocTy,
-                      IntPtrTy, ArraySize, NameStr);
+Value *CallInst::CreateMalloc(Instruction *InsertBefore, const Type *IntPtrTy,
+                              const Type *AllocTy, Value *ArraySize,
+                              const Twine &Name) {
+  return createMalloc(InsertBefore, NULL, IntPtrTy, AllocTy, ArraySize, Name);
 }
 
 /// CreateMalloc - Generate the IR for a call to malloc:
@@ -547,11 +541,10 @@
 /// 3. Bitcast the result of the malloc call to the specified type.
 /// Note: This function does not add the bitcast to the basic block, that is the
 /// responsibility of the caller.
-Value *CallInst::CreateMalloc(BasicBlock *InsertAtEnd,
-                              const Type *AllocTy, const Type *IntPtrTy,
-                              Value *ArraySize, const Twine &NameStr) {
-  return createMalloc(NULL, InsertAtEnd, AllocTy, 
-                      IntPtrTy, ArraySize, NameStr);
+Value *CallInst::CreateMalloc(BasicBlock *InsertAtEnd, const Type *IntPtrTy,
+                              const Type *AllocTy, Value *ArraySize, 
+                              const Twine &Name) {
+  return createMalloc(NULL, InsertAtEnd, IntPtrTy, AllocTy, ArraySize, Name);
 }
 
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/VMCore/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Verifier.cpp?rev=82257&r1=82256&r2=82257&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Verifier.cpp (original)
+++ llvm/trunk/lib/VMCore/Verifier.cpp Fri Sep 18 14:20:02 2009
@@ -1143,6 +1143,16 @@
   if (Function *F = CI.getCalledFunction())
     if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
       visitIntrinsicFunctionCall(ID, CI);
+
+  // Code here matches isMalloc from MallocHelper, which is not in VMCore.
+  const Module* M = CI.getParent()->getParent()->getParent();
+  Constant *MallocFunc = M->getFunction("malloc");
+
+  if (CI.getOperand(0) == MallocFunc) {
+    const PointerType *PTy =
+        PointerType::getUnqual(Type::getInt8Ty(CI.getParent()->getContext()));
+    Assert1(CI.getType() == PTy, "Malloc call must return i8*", &CI);
+  }
 }
 
 void Verifier::visitInvokeInst(InvokeInst &II) {





More information about the llvm-commits mailing list