aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-12-15 21:44:34 +0000
committerChris Lattner <sabre@nondot.org>2008-12-15 21:44:34 +0000
commit101f44e81f3bfae1b8ebefe74bef73883dac78ac (patch)
tree91380076f75ce55ecae3cf339bfc9c3eb4a2dff9 /lib
parent93b3b928d70df956b81ab1bffb7e8bab4b0c8fd7 (diff)
downloadexternal_llvm-101f44e81f3bfae1b8ebefe74bef73883dac78ac.zip
external_llvm-101f44e81f3bfae1b8ebefe74bef73883dac78ac.tar.gz
external_llvm-101f44e81f3bfae1b8ebefe74bef73883dac78ac.tar.bz2
enhance heap-sra to apply to fixed sized array allocations, not just
variable sized array allocations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61051 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp47
1 files changed, 43 insertions, 4 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp
index 41ff3f3..b797a12 100644
--- a/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/lib/Transforms/IPO/GlobalOpt.cpp
@@ -988,8 +988,25 @@ static void ReplaceUsesOfMallocWithGlobal(Instruction *Alloc,
// PHI.
unsigned PredNo = Alloc->use_begin().getOperandNo()/2;
InsertPt = PN->getIncomingBlock(PredNo)->getTerminator();
+ } else if (isa<BitCastInst>(U)) {
+ // Must be bitcast between the malloc and store to initialize the global.
+ ReplaceUsesOfMallocWithGlobal(U, GV);
+ U->eraseFromParent();
+ continue;
+ } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(U)) {
+ // If this is a "GEP bitcast" and the user is a store to the global, then
+ // just process it as a bitcast.
+ if (GEPI->hasAllZeroIndices() && GEPI->hasOneUse())
+ if (StoreInst *SI = dyn_cast<StoreInst>(GEPI->use_back()))
+ if (SI->getOperand(1) == GV) {
+ // Must be bitcast GEP between the malloc and store to initialize
+ // the global.
+ ReplaceUsesOfMallocWithGlobal(GEPI, GV);
+ GEPI->eraseFromParent();
+ continue;
+ }
}
-
+
// Insert a load from the global, and use it instead of the malloc.
Value *NL = new LoadInst(GV, GV->getName()+".val", InsertPt);
U->replaceUsesOfWith(Alloc, NL);
@@ -1339,12 +1356,34 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,
// If the allocation is an array of structures, consider transforming this
// into multiple malloc'd arrays, one for each field. This is basically
// SRoA for malloc'd memory.
- if (const StructType *AllocTy =
- dyn_cast<StructType>(MI->getAllocatedType())) {
+ const Type *AllocTy = MI->getAllocatedType();
+
+ // 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
+ if (!MI->isArrayAllocation())
+ if (const ArrayType *AT = dyn_cast<ArrayType>(AllocTy))
+ AllocTy = AT->getElementType();
+
+ if (const StructType *AllocSTy = dyn_cast<StructType>(AllocTy)) {
// This the structure has an unreasonable number of fields, leave it
// alone.
- if (AllocTy->getNumElements() <= 16 && AllocTy->getNumElements() > 0 &&
+ if (AllocSTy->getNumElements() <= 16 && AllocSTy->getNumElements() != 0 &&
GlobalLoadUsesSimpleEnoughForHeapSRA(GV, MI)) {
+
+ // If this is a fixed size array, transform the Malloc to be an alloc of
+ // structs. malloc [100 x struct],1 -> malloc struct, 100
+ if (const ArrayType *AT = dyn_cast<ArrayType>(MI->getAllocatedType())) {
+ MallocInst *NewMI =
+ new MallocInst(AllocSTy,
+ ConstantInt::get(Type::Int32Ty, AT->getNumElements()),
+ "", MI);
+ NewMI->takeName(MI);
+ Value *Cast = new BitCastInst(NewMI, MI->getType(), "tmp", MI);
+ MI->replaceAllUsesWith(Cast);
+ MI->eraseFromParent();
+ MI = NewMI;
+ }
+
GVI = PerformHeapAllocSRoA(GV, MI);
return true;
}