diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/Analysis/MallocHelper.h | 17 | ||||
| -rw-r--r-- | llvm/lib/Analysis/MallocHelper.cpp | 53 | ||||
| -rw-r--r-- | llvm/lib/Analysis/PointerTracking.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Transforms/IPO/GlobalOpt.cpp | 34 | 
4 files changed, 72 insertions, 37 deletions
diff --git a/llvm/include/llvm/Analysis/MallocHelper.h b/llvm/include/llvm/Analysis/MallocHelper.h index 0588dff08a6..e0c4d2c9e4a 100644 --- a/llvm/include/llvm/Analysis/MallocHelper.h +++ b/llvm/include/llvm/Analysis/MallocHelper.h @@ -46,9 +46,9 @@ CallInst* extractMallocCallFromBitCast(Value* I);  /// matches the malloc call IR generated by CallInst::CreateMalloc().  This   /// means that it is a malloc call with one bitcast use AND the malloc call's   /// size argument is: -///  1. a constant not equal to the malloc's allocated type +///  1. a constant not equal to the size of the malloced type  /// or -///  2. the result of a multiplication by the malloc's allocated type +///  2. the result of a multiplication by the size of the malloced type  /// Otherwise it returns NULL.  /// The unique bitcast is needed to determine the type/size of the array  /// allocation. @@ -66,18 +66,17 @@ const PointerType* getMallocType(const CallInst* CI);  /// unique bitcast use, then return NULL.  const Type* getMallocAllocatedType(const CallInst* CI); -/// getMallocArraySize - Returns the array size of a malloc call.  The array -/// size is computated in 1 of 3 ways: -///  1. If the element type if of size 1, then array size is the argument to  +/// getMallocArraySize - Returns the array size of a malloc call.  For array +/// mallocs, the size is computated in 1 of 3 ways: +///  1. If the element type is of size 1, then array size is the argument to   ///     malloc.  ///  2. Else if the malloc's argument is a constant, the array size is that  ///     argument divided by the element type's size.  ///  3. Else the malloc argument must be a multiplication and the array size is  ///     the first operand of the multiplication. -/// This function returns constant 1 if: -///  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. +/// For non-array mallocs, the computed size is constant 1.  +/// This function returns NULL for all mallocs whose array size cannot be +/// determined.  Value* getMallocArraySize(CallInst* CI, LLVMContext &Context,                            const TargetData* TD); diff --git a/llvm/lib/Analysis/MallocHelper.cpp b/llvm/lib/Analysis/MallocHelper.cpp index 89051d17883..41fdab9012f 100644 --- a/llvm/lib/Analysis/MallocHelper.cpp +++ b/llvm/lib/Analysis/MallocHelper.cpp @@ -130,9 +130,9 @@ static bool isArrayMallocHelper(const CallInst *CI, LLVMContext &Context,  /// matches the malloc call IR generated by CallInst::CreateMalloc().  This   /// means that it is a malloc call with one bitcast use AND the malloc call's   /// size argument is: -///  1. a constant not equal to the malloc's allocated type +///  1. a constant not equal to the size of the malloced type  /// or -///  2. the result of a multiplication by the malloc's allocated type +///  2. the result of a multiplication by the size of the malloced type  /// Otherwise it returns NULL.  /// The unique bitcast is needed to determine the type/size of the array  /// allocation. @@ -183,25 +183,60 @@ const Type* llvm::getMallocAllocatedType(const CallInst* CI) {    return PT ? PT->getElementType() : NULL;  } +/// isSafeToGetMallocArraySize - Returns true if the array size of a malloc can +/// be determined.  It can be determined in these 3 cases of malloc codegen: +/// 1. non-array malloc: The malloc's size argument is a constant and equals the ///    size of the type being malloced. +/// 2. array malloc: This is a malloc call with one bitcast use AND the malloc +///    call's size argument is a constant multiple of the size of the malloced +///    type. +/// 3. array malloc: This is a malloc call with one bitcast use AND the malloc +///    call's size argument is the result of a multiplication by the size of the +///    malloced type. +/// Otherwise returns false. +static bool isSafeToGetMallocArraySize(const CallInst *CI, +                                       LLVMContext &Context, +                                       const TargetData* TD) { +  if (!CI) +    return false; + +  // Type must be known to determine array size. +  const Type* T = getMallocAllocatedType(CI); +  if (!T) return false; + +  Value* MallocArg = CI->getOperand(1); +  Constant *ElementSize = ConstantExpr::getSizeOf(T); +  ElementSize = ConstantExpr::getTruncOrBitCast(ElementSize,  +                                                MallocArg->getType()); + +  // First, check if it is a non-array malloc. +  if (isa<ConstantExpr>(MallocArg) && (MallocArg == ElementSize)) +    return true; + +  // Second, check if it can be determined that this is an array malloc. +  return isArrayMallocHelper(CI, Context, TD); +} +  /// isConstantOne - Return true only if val is constant int 1.  static bool isConstantOne(Value *val) {    return isa<ConstantInt>(val) && cast<ConstantInt>(val)->isOne();  } -/// getMallocArraySize - Returns the array size of a malloc call.  The array -/// size is computated in 1 of 3 ways: -///  1. If the element type if of size 1, then array size is the argument to  +/// getMallocArraySize - Returns the array size of a malloc call.  For array +/// mallocs, the size is computated in 1 of 3 ways: +///  1. If the element type is of size 1, then array size is the argument to   ///     malloc.  ///  2. Else if the malloc's argument is a constant, the array size is that  ///     argument divided by the element type's size.  ///  3. Else the malloc argument must be a multiplication and the array size is  ///     the first operand of the multiplication. -/// This function returns constant 1 if: -///  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. +/// For non-array mallocs, the computed size is constant 1.  +/// This function returns NULL for all mallocs whose array size cannot be +/// determined.  Value* llvm::getMallocArraySize(CallInst* CI, LLVMContext &Context,                                  const TargetData* TD) { +  if (isSafeToGetMallocArraySize(CI, Context, TD)) +    return NULL; +    // Match CreateMalloc's use of constant 1 array-size for non-array mallocs.    if (!isArrayMalloc(CI, Context, TD))      return ConstantInt::get(CI->getOperand(1)->getType(), 1); diff --git a/llvm/lib/Analysis/PointerTracking.cpp b/llvm/lib/Analysis/PointerTracking.cpp index 43f4af36d81..2309fbc952c 100644 --- a/llvm/lib/Analysis/PointerTracking.cpp +++ b/llvm/lib/Analysis/PointerTracking.cpp @@ -102,8 +102,9 @@ const SCEV *PointerTracking::computeAllocationCount(Value *P,    if (CallInst *CI = extractMallocCall(V)) {      Value *arraySize = getMallocArraySize(CI, P->getContext(), TD); -    Ty = getMallocAllocatedType(CI); -    if (!Ty || !arraySize) return SE->getCouldNotCompute(); +    const Type* AllocTy = getMallocAllocatedType(CI); +    if (!AllocTy || !arraySize) return SE->getCouldNotCompute(); +    Ty = AllocTy;      // arraySize elements of type Ty.      return SE->getSCEV(arraySize);    } diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index a44386e6c15..0d9818fdfa7 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -950,12 +950,14 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV,                                                       BitCastInst *BCI,                                                       LLVMContext &Context,                                                       TargetData* TD) { +  DEBUG(errs() << "PROMOTING MALLOC GLOBAL: " << *GV +               << "  CALL = " << *CI << "  BCI = " << *BCI << '\n'); +    const Type *IntPtrTy = TD->getIntPtrType(Context); -  DEBUG(errs() << "PROMOTING MALLOC GLOBAL: " << *GV << "  MALLOC = " << *CI); - -  ConstantInt *NElements = cast<ConstantInt>(getMallocArraySize(CI, -                                                                Context, TD)); +  Value* ArraySize = getMallocArraySize(CI, Context, TD); +  assert(ArraySize && "not a malloc whose array size can be determined"); +  ConstantInt *NElements = cast<ConstantInt>(ArraySize);    if (NElements->getZExtValue() != 1) {      // If we have an array allocation, transform it to a single element      // allocation to make the code below simpler. @@ -976,9 +978,6 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV,    // Create the new global variable.  The contents of the malloc'd memory is    // undefined, so initialize with an undef value. -  // FIXME: This new global should have the alignment returned by malloc.  Code -  // could depend on malloc returning large alignment (on the mac, 16 bytes) but -  // this would only guarantee some lower alignment.    const Type *MAT = getMallocAllocatedType(CI);    Constant *Init = UndefValue::get(MAT);    GlobalVariable *NewGV = new GlobalVariable(*GV->getParent(),  @@ -1892,16 +1891,17 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,    // transform the program to use global memory instead of malloc'd memory.    // This eliminates dynamic allocation, avoids an indirection accessing the    // data, and exposes the resultant global to further GlobalOpt. -  if (ConstantInt *NElements = -              dyn_cast<ConstantInt>(getMallocArraySize(CI, Context, TD))) { -    // Restrict this transformation to only working on small allocations -    // (2048 bytes currently), as we don't want to introduce a 16M global or -    // something. -    if (TD &&  -        NElements->getZExtValue() * TD->getTypeAllocSize(AllocTy) < 2048) { -      GVI = OptimizeGlobalAddressOfMalloc(GV, CI, BCI, Context, TD); -      return true; -    } +  Value *NElems = getMallocArraySize(CI, Context, TD); +  if (NElems) { +    if (ConstantInt *NElements = dyn_cast<ConstantInt>(NElems)) +      // Restrict this transformation to only working on small allocations +      // (2048 bytes currently), as we don't want to introduce a 16M global or +      // something. +      if (TD &&  +          NElements->getZExtValue() * TD->getTypeAllocSize(AllocTy) < 2048) { +        GVI = OptimizeGlobalAddressOfMalloc(GV, CI, BCI, Context, TD); +        return true; +      }    }    // If the allocation is an array of structures, consider transforming this  | 

