diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2012-09-30 12:43:37 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2012-09-30 12:43:37 +0000 |
commit | 6cacae8bf9597b8124cd40aedc189c04484e1990 (patch) | |
tree | b20a92a4aa5ad64f3ea61a4d87113972fae44363 /test/CodeGenCXX/assign-construct-memcpy.cpp | |
parent | 615c3dda26323dc1b07333e060a64c2471b74d9e (diff) |
CodeGen: Copy tail padding when we're not dealing with a trivial copy assign or move assign operator.
This fixes a regression from r162254, the optimizer has problems reasoning
about the smaller memcpy as it's often not safe to widen a store but making it
smaller is.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164917 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/assign-construct-memcpy.cpp')
-rw-r--r-- | test/CodeGenCXX/assign-construct-memcpy.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/test/CodeGenCXX/assign-construct-memcpy.cpp b/test/CodeGenCXX/assign-construct-memcpy.cpp new file mode 100644 index 0000000000..3d42051324 --- /dev/null +++ b/test/CodeGenCXX/assign-construct-memcpy.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -o - -std=c++11 %s -DPOD | FileCheck %s -check-prefix=CHECK-POD +// RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -o - -std=c++11 %s | FileCheck %s -check-prefix=CHECK-NONPOD + +// Declare the reserved placement operators. +typedef __typeof__(sizeof(0)) size_t; +void *operator new(size_t, void*) throw(); +void operator delete(void*, void*) throw(); +void *operator new[](size_t, void*) throw(); +void operator delete[](void*, void*) throw(); +template<typename T> T &&move(T&); + +struct foo { +#ifndef POD + foo() {} // non-POD +#endif + void *a, *b; + bool c; +}; + +// It is not legal to copy the tail padding in all cases, but if it is it can +// yield better codegen. + +foo *test1(void *f, const foo &x) { + return new (f) foo(x); +// CHECK-POD: test1 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 + +// CHECK-NONPOD: test1 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +} + +foo *test2(const foo &x) { + return new foo(x); +// CHECK-POD: test2 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 + +// CHECK-NONPOD: test2 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +} + +foo test3(const foo &x) { + foo f = x; + return f; +// CHECK-POD: test3 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 + +// CHECK-NONPOD: test3 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +} + +foo *test4(foo &&x) { + return new foo(x); +// CHECK-POD: test4 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 + +// CHECK-NONPOD: test4 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +} + +void test5(foo &f, const foo &x) { + f = x; +// CHECK-POD: test5 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 + +// CHECK-NONPOD: test5 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 17, i32 8 +} + +extern foo globtest; + +void test6(foo &&x) { + globtest = move(x); +// CHECK-POD: test6 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 + +// CHECK-NONPOD: test6 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 17, i32 8 +} + +void byval(foo f); + +void test7(const foo &x) { + byval(x); +// CHECK-POD: test7 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 + +// CHECK-NONPOD: test7 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +} |