summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExprCXX.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-07-21 01:10:17 +0000
committerDouglas Gregor <dgregor@apple.com>2010-07-21 01:10:17 +0000
commit05fc5be32f8de7e947971f1dee94fb491fd534dd (patch)
tree09ffba514a52fe3cbc04880dc9505f862a9ac6c0 /clang/lib/CodeGen/CGExprCXX.cpp
parenta0e7f0c1b1155b630b7753cd7a78cbfe88c78b01 (diff)
downloadbcm5719-llvm-05fc5be32f8de7e947971f1dee94fb491fd534dd.tar.gz
bcm5719-llvm-05fc5be32f8de7e947971f1dee94fb491fd534dd.zip
Implement zero-initialization for array new when there is an
initializer of (). Make sure to use a simple memset() when we can, or fall back to generating a loop when a simple memset will not suffice. Fixes <rdar://problem/8212208>, a regression due to my work in r107857. llvm-svn: 108977
Diffstat (limited to 'clang/lib/CodeGen/CGExprCXX.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp74
1 files changed, 61 insertions, 13 deletions
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index f419382989e..eb984d3cbb3 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -423,13 +423,16 @@ static CharUnits CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) {
static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context,
CodeGenFunction &CGF,
const CXXNewExpr *E,
- llvm::Value *&NumElements) {
+ llvm::Value *&NumElements,
+ llvm::Value *&SizeWithoutCookie) {
QualType Type = E->getAllocatedType();
CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(Type);
const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
- if (!E->isArray())
- return llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity());
+ if (!E->isArray()) {
+ SizeWithoutCookie = llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity());
+ return SizeWithoutCookie;
+ }
// Emit the array size expression.
NumElements = CGF.EmitScalarExpr(E->getArraySize());
@@ -488,6 +491,7 @@ static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context,
PN->addIncoming(llvm::Constant::getAllOnesValue(V->getType()), OverflowBB);
Size = PN;
}
+ SizeWithoutCookie = Size;
// Add the cookie padding if necessary.
CharUnits CookiePadding = CalculateCookiePadding(CGF.getContext(), E);
@@ -571,18 +575,60 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
EmitBlock(AfterFor, true);
}
+static void EmitZeroMemSet(CodeGenFunction &CGF, QualType T,
+ llvm::Value *NewPtr, llvm::Value *Size) {
+ llvm::LLVMContext &VMContext = CGF.CGM.getLLVMContext();
+ const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
+ if (NewPtr->getType() != BP)
+ NewPtr = CGF.Builder.CreateBitCast(NewPtr, BP, "tmp");
+
+ CGF.Builder.CreateCall5(CGF.CGM.getMemSetFn(BP, CGF.IntPtrTy), NewPtr,
+ llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)),
+ Size,
+ llvm::ConstantInt::get(CGF.Int32Ty,
+ CGF.getContext().getTypeAlign(T)/8),
+ llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext),
+ 0));
+}
+
static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
llvm::Value *NewPtr,
- llvm::Value *NumElements) {
+ llvm::Value *NumElements,
+ llvm::Value *AllocSizeWithoutCookie) {
if (E->isArray()) {
if (CXXConstructorDecl *Ctor = E->getConstructor()) {
- if (!Ctor->getParent()->hasTrivialConstructor())
- CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
- E->constructor_arg_begin(),
- E->constructor_arg_end());
+ bool RequiresZeroInitialization = false;
+ if (Ctor->getParent()->hasTrivialConstructor()) {
+ // If new expression did not specify value-initialization, then there
+ // is no initialization.
+ if (!E->hasInitializer() || Ctor->getParent()->isEmpty())
+ return;
+
+ if (!CGF.CGM.getTypes().ContainsPointerToDataMember(
+ E->getAllocatedType())) {
+ // Optimization: since zero initialization will just set the memory
+ // to all zeroes, generate a single memset to do it in one shot.
+ EmitZeroMemSet(CGF, E->getAllocatedType(), NewPtr,
+ AllocSizeWithoutCookie);
+ return;
+ }
+
+ RequiresZeroInitialization = true;
+ }
+
+ CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
+ E->constructor_arg_begin(),
+ E->constructor_arg_end(),
+ RequiresZeroInitialization);
return;
- }
- else {
+ } else if (E->getNumConstructorArgs() == 1 &&
+ isa<ImplicitValueInitExpr>(E->getConstructorArg(0))) {
+ // Optimization: since zero initialization will just set the memory
+ // to all zeroes, generate a single memset to do it in one shot.
+ EmitZeroMemSet(CGF, E->getAllocatedType(), NewPtr,
+ AllocSizeWithoutCookie);
+ return;
+ } else {
CGF.EmitNewArrayInitializer(E, NewPtr, NumElements);
return;
}
@@ -621,8 +667,10 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
QualType SizeTy = getContext().getSizeType();
llvm::Value *NumElements = 0;
+ llvm::Value *AllocSizeWithoutCookie = 0;
llvm::Value *AllocSize = EmitCXXNewAllocSize(getContext(),
- *this, E, NumElements);
+ *this, E, NumElements,
+ AllocSizeWithoutCookie);
NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy));
@@ -714,12 +762,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
NewPtr =
Builder.CreateBitCast(NewPtr,
ConvertType(getContext().getPointerType(AllocType)));
- EmitNewInitializer(*this, E, NewPtr, NumElements);
+ EmitNewInitializer(*this, E, NewPtr, NumElements, AllocSizeWithoutCookie);
NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));
}
else {
NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));
- EmitNewInitializer(*this, E, NewPtr, NumElements);
+ EmitNewInitializer(*this, E, NewPtr, NumElements, AllocSizeWithoutCookie);
}
if (NullCheckResult) {
OpenPOWER on IntegriCloud