aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenCXX/assign-construct-memcpy.cpp
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2012-09-30 12:43:37 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2012-09-30 12:43:37 +0000
commit6cacae8bf9597b8124cd40aedc189c04484e1990 (patch)
treeb20a92a4aa5ad64f3ea61a4d87113972fae44363 /test/CodeGenCXX/assign-construct-memcpy.cpp
parent615c3dda26323dc1b07333e060a64c2471b74d9e (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.cpp89
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
+}