diff options
author | Chris Lattner <sabre@nondot.org> | 2010-12-01 02:05:19 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-12-01 02:05:19 +0000 |
commit | 94cd011edcffdabd3cbc520830ccf8e793e08b62 (patch) | |
tree | 4562dcdf8b3029956bfabfbe830fd037929e0b36 /lib/CodeGen/CGDecl.cpp | |
parent | 49c64fdcf354c7998b8b301402fb6140c24df36a (diff) |
add some infrastructure that will let us codegen
http://llvm.org/bugs/show_bug.cgi?id=279#c3 better.
No functionality change yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120530 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGDecl.cpp')
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 73 |
1 files changed, 67 insertions, 6 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index de02febccc..53cc205cd0 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -507,6 +507,54 @@ namespace { }; } + +/// canEmitInitWithFewStoresAfterMemset - Decide whether we can emit the +/// non-zero parts of the specified initializer with equal or fewer than +/// NumStores scalar stores. +static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init, + unsigned &NumStores) { + // Zero never requires any extra stores. + if (isa<llvm::ConstantAggregateZero>(Init)) return true; + + // Anything else is hard and scary. + return false; +} + +/// emitStoresForInitAfterMemset - For inits that +/// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar +/// stores that would be required. +static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc, + CGBuilderTy &Builder) { + // Zero doesn't require any stores. + if (isa<llvm::ConstantAggregateZero>(Init)) return; + + + assert(0 && "Unknown value type!"); +} + + +/// shouldUseMemSetPlusStoresToInitialize - Decide whether we should use memset +/// plus some stores to initialize a local variable instead of using a memcpy +/// from a constant global. It is beneficial to use memset if the global is all +/// zeros, or mostly zeros and large. +static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init, + uint64_t GlobalSize) { + // If a global is all zeros, always use a memset. + if (isa<llvm::ConstantAggregateZero>(Init)) return true; + + + // If a non-zero global is <= 32 bytes, always use a memcpy. If it is large, + // do it if it will require 6 or fewer scalar stores. + // TODO: Should budget depends on the size? Avoiding a large global warrants + // plopping in more stores. + unsigned StoreBudget = 6; + uint64_t SizeLimit = 32; + + return GlobalSize > SizeLimit && + canEmitInitWithFewStoresAfterMemset(Init, StoreBudget); +} + + /// EmitLocalVarDecl - Emit code and set up an entry in LocalDeclMap for a /// variable declaration with auto, register, or no storage class specifier. /// These turn into simple stack objects, or GlobalValues depending on target. @@ -680,7 +728,7 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, flag |= BLOCK_FIELD_IS_WEAK; int isa = 0; - if (flag&BLOCK_FIELD_IS_WEAK) + if (flag & BLOCK_FIELD_IS_WEAK) isa = 1; V = Builder.CreateIntToPtr(Builder.getInt32(isa), PtrToInt8Ty, "isa"); Builder.CreateStore(V, isa_field); @@ -735,11 +783,20 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, llvm::Value *NotVolatile = Builder.getFalse(); - // If the initializer is all zeros, codegen with memset. - if (isa<llvm::ConstantAggregateZero>(Init)) { - llvm::Value *Zero = Builder.getInt8(0); - Builder.CreateCall5(CGM.getMemSetFn(Loc->getType(), SizeVal->getType()), - Loc, Zero, SizeVal, AlignVal, NotVolatile); + // If the initializer is all or mostly zeros, codegen with memset then do + // a few stores afterward. + if (shouldUseMemSetPlusStoresToInitialize(Init, + CGM.getTargetData().getTypeAllocSize(Init->getType()))) { + const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext); + llvm::Value *MemSetDest = Loc; + if (MemSetDest->getType() != BP) + MemSetDest = Builder.CreateBitCast(MemSetDest, BP, "tmp"); + + Builder.CreateCall5(CGM.getMemSetFn(BP, SizeVal->getType()), + MemSetDest, Builder.getInt8(0), SizeVal, AlignVal, + NotVolatile); + emitStoresForInitAfterMemset(Init, Loc, Builder); + } else { // Otherwise, create a temporary global with the initializer then // memcpy from the global to the alloca. @@ -754,6 +811,10 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, if (SrcPtr->getType() != BP) SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); + const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext); + if (Loc->getType() != BP) + Loc = Builder.CreateBitCast(Loc, BP, "tmp"); + Builder.CreateCall5(CGM.getMemCpyFn(Loc->getType(), SrcPtr->getType(), SizeVal->getType()), Loc, SrcPtr, SizeVal, AlignVal, NotVolatile); |