Elide copy construction in new expressions. PR11757.
llvm-svn: 150738
This commit is contained in:
parent
a0d3c75015
commit
b971d49765
@ -890,20 +890,6 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
|
||||
return;
|
||||
}
|
||||
|
||||
if (const CXXConstructExpr *CCE = dyn_cast_or_null<CXXConstructExpr>(Init)) {
|
||||
CXXConstructorDecl *Ctor = CCE->getConstructor();
|
||||
// Per C++ [expr.new]p15, if we have an initializer, then we're performing
|
||||
// direct initialization. C++ [dcl.init]p5 requires that we
|
||||
// zero-initialize storage if there are no user-declared constructors.
|
||||
if (!Ctor->getParent()->hasUserDeclaredConstructor() &&
|
||||
!Ctor->getParent()->isEmpty())
|
||||
CGF.EmitNullInitialization(NewPtr, ElementType);
|
||||
|
||||
CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false,
|
||||
NewPtr, CCE->arg_begin(), CCE->arg_end());
|
||||
return;
|
||||
}
|
||||
// We have a POD type.
|
||||
if (!Init)
|
||||
return;
|
||||
|
||||
|
||||
@ -7,8 +7,8 @@ public:
|
||||
int z;
|
||||
};
|
||||
|
||||
A *foo () {
|
||||
A *a = new A();
|
||||
A *foo (A* x) {
|
||||
A *a = new A(*x);
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
@ -194,12 +194,9 @@ namespace test3 {
|
||||
// CHECK: [[SAVED0:%.*]] = alloca i8*
|
||||
// CHECK-NEXT: [[SAVED1:%.*]] = alloca i8*
|
||||
// CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1
|
||||
// CHECK-NEXT: [[TMP:%.*]] = alloca [[A]], align 8
|
||||
// CHECK: [[TMPACTIVE:%.*]] = alloca i1
|
||||
|
||||
// CHECK: [[COND:%.*]] = trunc i8 {{.*}} to i1
|
||||
// CHECK-NEXT: store i1 false, i1* [[CLEANUPACTIVE]]
|
||||
// CHECK-NEXT: store i1 false, i1* [[TMPACTIVE]]
|
||||
// CHECK-NEXT: br i1 [[COND]]
|
||||
return (cond ?
|
||||
|
||||
@ -209,24 +206,18 @@ namespace test3 {
|
||||
// CHECK-NEXT: store i8* [[FOO]], i8** [[SAVED1]]
|
||||
// CHECK-NEXT: store i1 true, i1* [[CLEANUPACTIVE]]
|
||||
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
|
||||
// CHECK-NEXT: invoke void @_ZN5test35makeAEv([[A]]* sret [[TMP]])
|
||||
// CHECK: store i1 true, i1* [[TMPACTIVE]]
|
||||
// CHECK-NEXT: invoke void @_ZN5test31AC1ERKS0_([[A]]* [[CAST]], [[A]]* [[TMP]])
|
||||
// CHECK: store i1 false, i1* [[CLEANUPACTIVE]]
|
||||
// CHECK-NEXT: br label
|
||||
// CHECK-NEXT: invoke void @_ZN5test35makeAEv([[A]]* sret [[CAST]])
|
||||
// CHECK: br label
|
||||
// -> cond.end
|
||||
new(foo(),10.0) A(makeA()) :
|
||||
|
||||
// CHECK: [[MAKE:%.*]] = invoke [[A]]* @_ZN5test38makeAPtrEv()
|
||||
// CHECK: [[MAKE:%.*]] = call [[A]]* @_ZN5test38makeAPtrEv()
|
||||
// CHECK: br label
|
||||
// -> cond.end
|
||||
makeAPtr());
|
||||
|
||||
// cond.end:
|
||||
// CHECK: [[RESULT:%.*]] = phi [[A]]* {{.*}}[[CAST]]{{.*}}[[MAKE]]
|
||||
// CHECK-NEXT: [[ISACTIVE:%.*]] = load i1* [[TMPACTIVE]]
|
||||
// CHECK-NEXT: br i1 [[ISACTIVE]]
|
||||
// CHECK: invoke void @_ZN5test31AD1Ev
|
||||
// CHECK: ret [[A]]* [[RESULT]]
|
||||
|
||||
// in the EH path:
|
||||
|
||||
@ -239,3 +239,14 @@ namespace PR11523 {
|
||||
// CHECK: store i64 -1
|
||||
NewTy* f() { return new NewTy[2](); }
|
||||
}
|
||||
|
||||
namespace PR11757 {
|
||||
// Make sure we elide the copy construction.
|
||||
struct X { X(); X(const X&); };
|
||||
X* a(X* x) { return new X(X()); }
|
||||
// CHECK: define {{.*}} @_ZN7PR117571aEPNS_1XE
|
||||
// CHECK: [[CALL:%.*]] = call noalias i8* @_Znwm
|
||||
// CHECK-NEXT: [[CASTED:%.*]] = bitcast i8* [[CALL]] to
|
||||
// CHECK-NEXT: call void @_ZN7PR117571XC1Ev({{.*}}* [[CASTED]])
|
||||
// CHECK-NEXT: ret {{.*}} [[CASTED]]
|
||||
}
|
||||
|
||||
@ -14,8 +14,6 @@ namespace test0 {
|
||||
// CHECK-NEXT: call noalias i8* @_Znwm(
|
||||
// CHECK-NEXT: bitcast
|
||||
// CHECK-NEXT: bitcast
|
||||
// CHECK-NEXT: call void @llvm.memset.p0i8.i64(
|
||||
// CHECK-NEXT: bitcast
|
||||
// CHECK-NEXT: bitcast
|
||||
// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(
|
||||
// CHECK-NEXT: ret
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user