aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGDecl.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-12-01 02:05:19 +0000
committerChris Lattner <sabre@nondot.org>2010-12-01 02:05:19 +0000
commit94cd011edcffdabd3cbc520830ccf8e793e08b62 (patch)
tree4562dcdf8b3029956bfabfbe830fd037929e0b36 /lib/CodeGen/CGDecl.cpp
parent49c64fdcf354c7998b8b301402fb6140c24df36a (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.cpp73
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);