summaryrefslogtreecommitdiffstats
path: root/llvm/test
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2015-02-20 01:00:19 +0000
committerReid Kleckner <reid@kleckner.net>2015-02-20 01:00:19 +0000
commit0b647e6cca16a55cce3d7e4dcc86b75273a5598b (patch)
treee3931a7fe2595e085ca754f1df46c16ae67330b9 /llvm/test
parent0d94fa98e53c851f7646666a49bc1a01fa7d9782 (diff)
downloadbcm5719-llvm-0b647e6cca16a55cce3d7e4dcc86b75273a5598b.tar.gz
bcm5719-llvm-0b647e6cca16a55cce3d7e4dcc86b75273a5598b.zip
EH: Prune unreachable resume instructions during Dwarf EH preparation
Today a simple function that only catches exceptions and doesn't run destructor cleanups ends up containing a dead call to _Unwind_Resume (PR20300). We can't remove these dead resume instructions during normal optimization because inlining might introduce additional landingpads that do have cleanups to run. Instead we can do this during EH preparation, which is guaranteed to run after inlining. Fixes PR20300. Reviewers: majnemer Differential Revision: http://reviews.llvm.org/D7744 llvm-svn: 229944
Diffstat (limited to 'llvm/test')
-rw-r--r--llvm/test/CodeGen/Mips/eh.ll1
-rw-r--r--llvm/test/CodeGen/X86/dwarf-eh-prepare.ll115
-rw-r--r--llvm/test/CodeGen/X86/gcc_except_table.ll1
-rw-r--r--llvm/test/CodeGen/X86/gcc_except_table_functions.ll1
-rw-r--r--llvm/test/CodeGen/XCore/exception.ll6
5 files changed, 118 insertions, 6 deletions
diff --git a/llvm/test/CodeGen/Mips/eh.ll b/llvm/test/CodeGen/Mips/eh.ll
index fc9e2ef21a8..3e7f64aa227 100644
--- a/llvm/test/CodeGen/Mips/eh.ll
+++ b/llvm/test/CodeGen/Mips/eh.ll
@@ -27,6 +27,7 @@ lpad: ; preds = %entry
; CHECK-EL: bne $5
%exn.val = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ cleanup
catch i8* bitcast (i8** @_ZTId to i8*)
%exn = extractvalue { i8*, i32 } %exn.val, 0
%sel = extractvalue { i8*, i32 } %exn.val, 1
diff --git a/llvm/test/CodeGen/X86/dwarf-eh-prepare.ll b/llvm/test/CodeGen/X86/dwarf-eh-prepare.ll
index a3a70da866c..25572d868da 100644
--- a/llvm/test/CodeGen/X86/dwarf-eh-prepare.ll
+++ b/llvm/test/CodeGen/X86/dwarf-eh-prepare.ll
@@ -7,12 +7,13 @@
@int_typeinfo = global i8 0
declare void @might_throw()
+declare void @cleanup()
-define i32 @simple_catch() {
+define i32 @simple_cleanup_catch() {
invoke void @might_throw()
to label %cont unwind label %lpad
-; CHECK: define i32 @simple_catch()
+; CHECK-LABEL: define i32 @simple_cleanup_catch()
; CHECK: invoke void @might_throw()
cont:
@@ -22,15 +23,18 @@ cont:
lpad:
%ehvals = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ cleanup
catch i8* @int_typeinfo
%ehptr = extractvalue { i8*, i32 } %ehvals, 0
%ehsel = extractvalue { i8*, i32 } %ehvals, 1
+ call void @cleanup()
%int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo)
%int_match = icmp eq i32 %ehsel, %int_sel
br i1 %int_match, label %catch_int, label %eh.resume
; CHECK: lpad:
; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK: call void @cleanup()
; CHECK: call i32 @llvm.eh.typeid.for
; CHECK: br i1
@@ -41,11 +45,114 @@ catch_int:
; CHECK: ret i32 1
eh.resume:
- resume { i8*, i32 } %ehvals
+ %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0
+ %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1
+ resume { i8*, i32 } %new_ehvals
; CHECK: eh.resume:
-; CHECK: call void @_Unwind_Resume(i8* %{{.*}})
+; CHECK-NEXT: call void @_Unwind_Resume(i8* %ehptr)
}
+
+define i32 @catch_no_resume() {
+ invoke void @might_throw()
+ to label %cont unwind label %lpad
+
+cont:
+ ret i32 0
+
+lpad:
+ %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8* @int_typeinfo
+ %ehptr = extractvalue { i8*, i32 } %ehvals, 0
+ %ehsel = extractvalue { i8*, i32 } %ehvals, 1
+ %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo)
+ %int_match = icmp eq i32 %ehsel, %int_sel
+ br i1 %int_match, label %catch_int, label %eh.resume
+
+catch_int:
+ ret i32 1
+
+eh.resume:
+ %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0
+ %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1
+ resume { i8*, i32 } %new_ehvals
+}
+
+; Check that we can prune the unreachable resume instruction.
+
+; CHECK-LABEL: define i32 @catch_no_resume() {
+; CHECK: invoke void @might_throw()
+; CHECK: ret i32 0
+; CHECK: lpad:
+; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NOT: br i1
+; CHECK: ret i32 1
+; CHECK-NOT: call void @_Unwind_Resume
+; CHECK: {{^[}]}}
+
+
+define i32 @catch_cleanup_merge() {
+ invoke void @might_throw()
+ to label %inner_invoke unwind label %outer_lpad
+inner_invoke:
+ invoke void @might_throw()
+ to label %cont unwind label %inner_lpad
+cont:
+ ret i32 0
+
+outer_lpad:
+ %ehvals1 = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8* @int_typeinfo
+ br label %catch.dispatch
+
+inner_lpad:
+ %ehvals2 = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ catch i8* @int_typeinfo
+ call void @cleanup()
+ br label %catch.dispatch
+
+catch.dispatch:
+ %ehvals = phi { i8*, i32 } [ %ehvals1, %outer_lpad ], [ %ehvals2, %inner_lpad ]
+ %ehptr = extractvalue { i8*, i32 } %ehvals, 0
+ %ehsel = extractvalue { i8*, i32 } %ehvals, 1
+ %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo)
+ %int_match = icmp eq i32 %ehsel, %int_sel
+ br i1 %int_match, label %catch_int, label %eh.resume
+
+catch_int:
+ ret i32 1
+
+eh.resume:
+ %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0
+ %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1
+ resume { i8*, i32 } %new_ehvals
+}
+
+; We can't prune this merge because one landingpad is a cleanup pad.
+
+; CHECK-LABEL: define i32 @catch_cleanup_merge()
+; CHECK: invoke void @might_throw()
+; CHECK: invoke void @might_throw()
+; CHECK: ret i32 0
+;
+; CHECK: outer_lpad:
+; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK: br label %catch.dispatch
+;
+; CHECK: inner_lpad:
+; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK: call void @cleanup()
+; CHECK: br label %catch.dispatch
+;
+; CHECK: catch.dispatch:
+; CHECK: call i32 @llvm.eh.typeid.for
+; CHECK: br i1
+; CHECK: catch_int:
+; CHECK: ret i32 1
+; CHECK: eh.resume:
+; CHECK-NEXT: call void @_Unwind_Resume(i8* %ehptr)
+
declare i32 @__gxx_personality_v0(...)
declare i32 @llvm.eh.typeid.for(i8*)
diff --git a/llvm/test/CodeGen/X86/gcc_except_table.ll b/llvm/test/CodeGen/X86/gcc_except_table.ll
index abce13002db..b656dc9d68e 100644
--- a/llvm/test/CodeGen/X86/gcc_except_table.ll
+++ b/llvm/test/CodeGen/X86/gcc_except_table.ll
@@ -37,6 +37,7 @@ entry:
lpad:
%0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
catch i8* bitcast (i8** @_ZTIi to i8*)
br label %eh.resume
diff --git a/llvm/test/CodeGen/X86/gcc_except_table_functions.ll b/llvm/test/CodeGen/X86/gcc_except_table_functions.ll
index 4a8168050e5..7a64a01fa38 100644
--- a/llvm/test/CodeGen/X86/gcc_except_table_functions.ll
+++ b/llvm/test/CodeGen/X86/gcc_except_table_functions.ll
@@ -20,6 +20,7 @@ try.cont:
lpad:
%0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
catch i8* bitcast (void ()* @filt0 to i8*)
catch i8* bitcast (void ()* @filt1 to i8*)
%sel = extractvalue { i8*, i32 } %0, 1
diff --git a/llvm/test/CodeGen/XCore/exception.ll b/llvm/test/CodeGen/XCore/exception.ll
index fec83eb15ea..cd9771d6401 100644
--- a/llvm/test/CodeGen/XCore/exception.ll
+++ b/llvm/test/CodeGen/XCore/exception.ll
@@ -78,6 +78,7 @@ cont:
; CHECK: bl __cxa_end_catch
lpad:
%0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
catch i8* bitcast (i8** @_ZTIi to i8*)
catch i8* bitcast (i8** @_ZTId to i8*)
%1 = extractvalue { i8*, i32 } %0, 0
@@ -110,13 +111,14 @@ Exit:
; CHECK: .long [[PRE_G]]-[[START]]
; CHECK: .long [[POST_G]]-[[PRE_G]]
; CHECK: .long [[LANDING]]-[[START]]
-; CHECK: .byte 3
+; CHECK: .byte 5
; CHECK: .long [[POST_G]]-[[START]]
; CHECK: .long [[END]]-[[POST_G]]
; CHECK: .long 0
; CHECK: .byte 0
-; CHECK: .byte 1
; CHECK: .byte 0
+; CHECK: .byte 1
+; CHECK: .byte 125
; CHECK: .byte 2
; CHECK: .byte 125
; CHECK: .long _ZTIi
OpenPOWER on IntegriCloud