HeapAllocSRoA also needs to check if malloc array size can be computed.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84288 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Victor Hernandez
2009-10-16 23:12:25 +00:00
parent 362b8f2786
commit 8db42d2b1c
2 changed files with 63 additions and 33 deletions

View File

@ -1586,6 +1586,8 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV,
<< " BITCAST = " << *BCI << '\n'); << " BITCAST = " << *BCI << '\n');
const Type* MAT = getMallocAllocatedType(CI); const Type* MAT = getMallocAllocatedType(CI);
const StructType *STy = cast<StructType>(MAT); const StructType *STy = cast<StructType>(MAT);
Value* ArraySize = getMallocArraySize(CI, Context, TD);
assert(ArraySize && "not a malloc whose array size can be determined");
// There is guaranteed to be at least one use of the malloc (storing // There is guaranteed to be at least one use of the malloc (storing
// it into GV). If there are other uses, change them to be uses of // it into GV). If there are other uses, change them to be uses of
@ -1610,8 +1612,8 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV,
GV->isThreadLocal()); GV->isThreadLocal());
FieldGlobals.push_back(NGV); FieldGlobals.push_back(NGV);
Value *NMI = CallInst::CreateMalloc(CI, TD->getIntPtrType(Context), FieldTy, Value *NMI = CallInst::CreateMalloc(CI, TD->getIntPtrType(Context),
getMallocArraySize(CI, Context, TD), FieldTy, ArraySize,
BCI->getName() + ".f" + Twine(FieldNo)); BCI->getName() + ".f" + Twine(FieldNo));
FieldMallocs.push_back(NMI); FieldMallocs.push_back(NMI);
new StoreInst(NMI, NGV, BCI); new StoreInst(NMI, NGV, BCI);
@ -1892,6 +1894,7 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,
// This eliminates dynamic allocation, avoids an indirection accessing the // This eliminates dynamic allocation, avoids an indirection accessing the
// data, and exposes the resultant global to further GlobalOpt. // data, and exposes the resultant global to further GlobalOpt.
Value *NElems = getMallocArraySize(CI, Context, TD); Value *NElems = getMallocArraySize(CI, Context, TD);
// We cannot optimize the malloc if we cannot determine malloc array size.
if (NElems) { if (NElems) {
if (ConstantInt *NElements = dyn_cast<ConstantInt>(NElems)) if (ConstantInt *NElements = dyn_cast<ConstantInt>(NElems))
// Restrict this transformation to only working on small allocations // Restrict this transformation to only working on small allocations
@ -1902,42 +1905,43 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,
GVI = OptimizeGlobalAddressOfMalloc(GV, CI, BCI, Context, TD); GVI = OptimizeGlobalAddressOfMalloc(GV, CI, BCI, Context, TD);
return true; return true;
} }
}
// If the allocation is an array of structures, consider transforming this // If the allocation is an array of structures, consider transforming this
// into multiple malloc'd arrays, one for each field. This is basically // into multiple malloc'd arrays, one for each field. This is basically
// SRoA for malloc'd memory. // SRoA for malloc'd memory.
// If this is an allocation of a fixed size array of structs, analyze as a // If this is an allocation of a fixed size array of structs, analyze as a
// variable size array. malloc [100 x struct],1 -> malloc struct, 100 // variable size array. malloc [100 x struct],1 -> malloc struct, 100
if (!isArrayMalloc(CI, Context, TD)) if (!isArrayMalloc(CI, Context, TD))
if (const ArrayType *AT = dyn_cast<ArrayType>(AllocTy)) if (const ArrayType *AT = dyn_cast<ArrayType>(AllocTy))
AllocTy = AT->getElementType(); AllocTy = AT->getElementType();
if (const StructType *AllocSTy = dyn_cast<StructType>(AllocTy)) { if (const StructType *AllocSTy = dyn_cast<StructType>(AllocTy)) {
// This the structure has an unreasonable number of fields, leave it // This the structure has an unreasonable number of fields, leave it
// alone. // alone.
if (AllocSTy->getNumElements() <= 16 && AllocSTy->getNumElements() != 0 && if (AllocSTy->getNumElements() <= 16 && AllocSTy->getNumElements() != 0 &&
AllGlobalLoadUsesSimpleEnoughForHeapSRA(GV, BCI)) { AllGlobalLoadUsesSimpleEnoughForHeapSRA(GV, BCI)) {
// If this is a fixed size array, transform the Malloc to be an alloc of // If this is a fixed size array, transform the Malloc to be an alloc of
// structs. malloc [100 x struct],1 -> malloc struct, 100 // structs. malloc [100 x struct],1 -> malloc struct, 100
if (const ArrayType *AT = dyn_cast<ArrayType>(getMallocAllocatedType(CI))) { if (const ArrayType *AT =
Value* NumElements = ConstantInt::get(Type::getInt32Ty(Context), dyn_cast<ArrayType>(getMallocAllocatedType(CI))) {
AT->getNumElements()); Value* NumElements = ConstantInt::get(Type::getInt32Ty(Context),
Value* NewMI = CallInst::CreateMalloc(CI, TD->getIntPtrType(Context), AT->getNumElements());
AllocSTy, NumElements, Value* NewMI = CallInst::CreateMalloc(CI, TD->getIntPtrType(Context),
BCI->getName()); AllocSTy, NumElements,
Value *Cast = new BitCastInst(NewMI, getMallocType(CI), "tmp", CI); BCI->getName());
BCI->replaceAllUsesWith(Cast); Value *Cast = new BitCastInst(NewMI, getMallocType(CI), "tmp", CI);
BCI->eraseFromParent(); BCI->replaceAllUsesWith(Cast);
CI->eraseFromParent(); BCI->eraseFromParent();
BCI = cast<BitCastInst>(NewMI); CI->eraseFromParent();
CI = extractMallocCallFromBitCast(NewMI); BCI = cast<BitCastInst>(NewMI);
} CI = extractMallocCallFromBitCast(NewMI);
}
GVI = PerformHeapAllocSRoA(GV, CI, BCI, Context, TD); GVI = PerformHeapAllocSRoA(GV, CI, BCI, Context, TD);
return true; return true;
}
} }
} }

View File

@ -0,0 +1,26 @@
; RUN: opt < %s -globalopt -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
target triple = "x86_64-apple-darwin10.0"
%struct.hashheader = type { i16, i16, i16, i16, i16, i16, i32, i32, i32, i32, i32, i32, i32, i32, i32, [5 x i8], [13 x i8], i8, i8, i8, [228 x i16], [228 x i8], [228 x i8], [228 x i8], [228 x i8], [228 x i8], [228 x i8], [128 x i8], [100 x [11 x i8]], [100 x i32], [100 x i32], i16 }
%struct.strchartype = type { i8*, i8*, i8* }
@hashheader = internal global %struct.hashheader zeroinitializer, align 32 ; <%struct.hashheader*> [#uses=1]
@chartypes = internal global %struct.strchartype* null ; <%struct.strchartype**> [#uses=1]
; CHECK-NOT: @hashheader
; CHECK-NOT: @chartypes
; based on linit in office-ispell
define void @test() nounwind ssp {
%1 = load i32* getelementptr inbounds (%struct.hashheader* @hashheader, i64 0, i32 13), align 8 ; <i32> [#uses=1]
%2 = sext i32 %1 to i64 ; <i64> [#uses=1]
%3 = mul i64 %2, ptrtoint (%struct.strchartype* getelementptr (%struct.strchartype* null, i64 1) to i64) ; <i64> [#uses=1]
%4 = tail call i8* @malloc(i64 %3) ; <i8*> [#uses=1]
; CHECK: call i8* @malloc(i64
%5 = bitcast i8* %4 to %struct.strchartype* ; <%struct.strchartype*> [#uses=1]
store %struct.strchartype* %5, %struct.strchartype** @chartypes, align 8
ret void
}
declare noalias i8* @malloc(i64)