summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2015-10-28 23:06:42 +0000
committerReid Kleckner <rnk@google.com>2015-10-28 23:06:42 +0000
commita002bd544c52c6033d973123874c1fa57a85f455 (patch)
tree09fa69d77e4d9049b06e5ff2ad74ac984c140bcd /clang/test
parentbdd292ae22739b77abd36b459df2aaf181195ba4 (diff)
downloadbcm5719-llvm-a002bd544c52c6033d973123874c1fa57a85f455.tar.gz
bcm5719-llvm-a002bd544c52c6033d973123874c1fa57a85f455.zip
[WinEH] Mark calls inside cleanups as noinline
This works around PR25162. The MSVC tables make it very difficult to correctly inline a C++ destructor that contains try / catch. We've attempted to address PR25162 in LLVM's backend, but it feels pretty infeasible. MSVC and ICC both appear to avoid inlining such complex destructors. Long term, we want to fix this by making the inliner smart enough to know when it is inlining into a cleanup, so it can inline simple destructors (~unique_ptr and ~vector) while avoiding destructors containing try / catch. llvm-svn: 251576
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp24
1 files changed, 14 insertions, 10 deletions
diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
index 96d8ffe02fe..c4a0d1ce649 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
@@ -26,7 +26,8 @@ void HasEHCleanup() {
// WIN32: ret void
//
// There should be one dtor call for unwinding from the second getA.
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: cleanuppad
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline:[0-9]+]]
// WIN32-NOT: @"\01??1A@@QAE@XZ"
// WIN32: }
@@ -54,14 +55,14 @@ int HasDeactivatedCleanups() {
//
// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])
// Destroy the two const ref temporaries.
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
// WIN32: ret i32
//
// Conditionally destroy arg1.
// WIN32: %[[cond:.*]] = load i1, i1* %[[isactive]]
// WIN32: br i1 %[[cond]]
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) #[[noinline]]
// WIN32: }
// Test putting the cleanups inside a conditional.
@@ -84,7 +85,7 @@ int HasConditionalCleanup(bool cond) {
// WIN32: call i32 @"\01?CouldThrow@@YAHXZ"()
//
// Only one dtor in the invoke for arg1
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline]]
// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
// WIN32: }
@@ -118,14 +119,14 @@ int HasConditionalDeactivatedCleanups(bool cond) {
// False condition.
// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"()
// Two normal cleanups for TakeRef args.
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
// WIN32: ret i32
//
// Somewhere in the landing pad soup, we conditionally destroy arg1.
// WIN32: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
// WIN32: br i1 %[[isactive]]
-// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline]]
// WIN32: }
namespace crash_on_partial_destroy {
@@ -163,7 +164,7 @@ C::C() { foo(); }
// WIN32: getelementptr inbounds i8, i8* %{{.*}}, i32 4
// WIN32-NOT: load
// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
-// WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"
+// WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}}) #[[noinline]]
// WIN32: }
}
@@ -186,7 +187,7 @@ void f() {
//
// WIN32: [[lpad]]
// WIN32-NEXT: cleanuppad
-// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
+// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}}) #[[noinline]]
}
namespace noexcept_false_dtor {
@@ -203,6 +204,9 @@ void f() {
// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"()
// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
// WIN32: cleanuppad
-// WIN32: invoke x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
+// WIN32: invoke x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) #[[invoke_noinline:[0-9]+]]
// WIN32: cleanupret
// WIN32: cleanupendpad
+
+// WIN32: attributes #[[noinline]] = { noinline nounwind }
+// WIN32: attributes #[[invoke_noinline]] = { noinline }
OpenPOWER on IntegriCloud