summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGenCXX
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-05-03 00:33:28 +0000
committerReid Kleckner <reid@kleckner.net>2014-05-03 00:33:28 +0000
commite39ee215519e6189d56b345e21f2cee2ffeed3ab (patch)
treea36d7025413b85f43118386359aa745ee6088325 /clang/test/CodeGenCXX
parent7d8668288ada75837138375497467172efe10c37 (diff)
downloadbcm5719-llvm-e39ee215519e6189d56b345e21f2cee2ffeed3ab.tar.gz
bcm5719-llvm-e39ee215519e6189d56b345e21f2cee2ffeed3ab.zip
MS ABI x64: Pass small objects with dtors but no copy ctors directly
Passing objects directly (in registers or memory) creates a second copy of the object in the callee. The callee always destroys its copy, but we also have to destroy any temporary created in the caller. In other words, copy elision of these kinds of objects is impossible. Objects larger than 8 bytes with non-trivial dtors and trivial copy ctors are still passed indirectly, and we can still elide copies of them. Fixes PR19640. llvm-svn: 207889
Diffstat (limited to 'clang/test/CodeGenCXX')
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp1
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp36
2 files changed, 36 insertions, 1 deletions
diff --git a/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp b/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
index d26a515c85e..b47508b302d 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
@@ -3,6 +3,7 @@
struct A {
A(int a);
+ A(const A &o);
~A();
int a;
};
diff --git a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index bc937491a57..1e333664c8b 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -47,6 +47,12 @@ struct Big {
int a, b, c, d, e, f;
};
+struct BigWithDtor {
+ BigWithDtor();
+ ~BigWithDtor();
+ int a, b, c, d, e, f;
+};
+
// WIN32: declare void @"{{.*take_bools_and_chars.*}}"
// WIN32: (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
// WIN32: i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
@@ -114,15 +120,43 @@ void small_arg_with_dtor(SmallWithDtor s) {}
// WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} {
// WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
// WIN32: }
-// WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
// WIN64: }
+void call_small_arg_with_dtor() {
+ small_arg_with_dtor(SmallWithDtor());
+}
+// The temporary is copied, so it's destroyed in the caller as well as the
+// callee.
+// WIN64-LABEL: define void @"\01?call_small_arg_with_dtor@@YAXXZ"()
+// WIN64: call %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QEAA@XZ"
+// WIN64: call void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %{{.*}})
+// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
+// WIN64: ret void
+
// Test that references aren't destroyed in the callee.
void ref_small_arg_with_dtor(const SmallWithDtor &s) { }
// WIN32: define void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
// WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
// WIN32: }
+// WIN64-LABEL: define void @"\01?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s)
+
+void big_arg_with_dtor(BigWithDtor s) {}
+// WIN64-LABEL: define void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %s)
+// WIN64: call void @"\01??1BigWithDtor@@QEAA@XZ"
+// WIN64: }
+
+void call_big_arg_with_dtor() {
+ big_arg_with_dtor(BigWithDtor());
+}
+// We can elide the copy of the temporary in the caller, because this object is
+// larger than 8 bytes and is passed indirectly.
+// WIN64-LABEL: define void @"\01?call_big_arg_with_dtor@@YAXXZ"()
+// WIN64: call %struct.BigWithDtor* @"\01??0BigWithDtor@@QEAA@XZ"
+// WIN64: call void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %{{.*}})
+// WIN64-NOT: call void @"\01??1BigWithDtor@@QEAA@XZ"
+// WIN64: ret void
// Test that temporaries passed by reference are destroyed in the caller.
void temporary_ref_with_dtor() {
OpenPOWER on IntegriCloud