1 ; RUN: opt -mtriple=x86_64-linux-gnu -dwarfehprepare < %s -S | FileCheck %s 2 3 ; Check basic functionality of IR-to-IR DWARF EH preparation. This should 4 ; eliminate resumes. This pass requires a TargetMachine, so we put it under X86 5 ; and provide an x86 triple. 6 7 @int_typeinfo = global i8 0 8 9 declare void @might_throw() 10 declare void @cleanup() 11 12 define i32 @simple_cleanup_catch() personality i32 (...)* @__gxx_personality_v0 { 13 invoke void @might_throw() 14 to label %cont unwind label %lpad 15 16 ; CHECK-LABEL: define i32 @simple_cleanup_catch() 17 ; CHECK: invoke void @might_throw() 18 19 cont: 20 ret i32 0 21 22 ; CHECK: ret i32 0 23 24 lpad: 25 %ehvals = landingpad { i8*, i32 } 26 cleanup 27 catch i8* @int_typeinfo 28 %ehptr = extractvalue { i8*, i32 } %ehvals, 0 29 %ehsel = extractvalue { i8*, i32 } %ehvals, 1 30 call void @cleanup() 31 %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo) 32 %int_match = icmp eq i32 %ehsel, %int_sel 33 br i1 %int_match, label %catch_int, label %eh.resume 34 35 ; CHECK: lpad: 36 ; CHECK: landingpad { i8*, i32 } 37 ; CHECK: call void @cleanup() 38 ; CHECK: call i32 @llvm.eh.typeid.for 39 ; CHECK: br i1 40 41 catch_int: 42 ret i32 1 43 44 ; CHECK: catch_int: 45 ; CHECK: ret i32 1 46 47 eh.resume: 48 %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0 49 %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1 50 resume { i8*, i32 } %new_ehvals 51 52 ; CHECK: eh.resume: 53 ; CHECK-NEXT: call void @_Unwind_Resume(i8* %ehptr) 54 } 55 56 57 define i32 @catch_no_resume() personality i32 (...)* @__gxx_personality_v0 { 58 invoke void @might_throw() 59 to label %cont unwind label %lpad 60 61 cont: 62 ret i32 0 63 64 lpad: 65 %ehvals = landingpad { i8*, i32 } 66 catch i8* @int_typeinfo 67 %ehptr = extractvalue { i8*, i32 } %ehvals, 0 68 %ehsel = extractvalue { i8*, i32 } %ehvals, 1 69 %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo) 70 %int_match = icmp eq i32 %ehsel, %int_sel 71 br i1 %int_match, label %catch_int, label %eh.resume 72 73 catch_int: 74 ret i32 1 75 76 eh.resume: 77 %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0 78 %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1 79 resume { i8*, i32 } %new_ehvals 80 } 81 82 ; Check that we can prune the unreachable resume instruction. 83 84 ; CHECK-LABEL: define i32 @catch_no_resume() personality i32 (...)* @__gxx_personality_v0 { 85 ; CHECK: invoke void @might_throw() 86 ; CHECK: ret i32 0 87 ; CHECK: lpad: 88 ; CHECK: landingpad { i8*, i32 } 89 ; CHECK-NOT: br i1 90 ; CHECK: ret i32 1 91 ; CHECK-NOT: call void @_Unwind_Resume 92 ; CHECK: {{^[}]}} 93 94 95 define i32 @catch_cleanup_merge() personality i32 (...)* @__gxx_personality_v0 { 96 invoke void @might_throw() 97 to label %inner_invoke unwind label %outer_lpad 98 inner_invoke: 99 invoke void @might_throw() 100 to label %cont unwind label %inner_lpad 101 cont: 102 ret i32 0 103 104 outer_lpad: 105 %ehvals1 = landingpad { i8*, i32 } 106 catch i8* @int_typeinfo 107 br label %catch.dispatch 108 109 inner_lpad: 110 %ehvals2 = landingpad { i8*, i32 } 111 cleanup 112 catch i8* @int_typeinfo 113 call void @cleanup() 114 br label %catch.dispatch 115 116 catch.dispatch: 117 %ehvals = phi { i8*, i32 } [ %ehvals1, %outer_lpad ], [ %ehvals2, %inner_lpad ] 118 %ehptr = extractvalue { i8*, i32 } %ehvals, 0 119 %ehsel = extractvalue { i8*, i32 } %ehvals, 1 120 %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo) 121 %int_match = icmp eq i32 %ehsel, %int_sel 122 br i1 %int_match, label %catch_int, label %eh.resume 123 124 catch_int: 125 ret i32 1 126 127 eh.resume: 128 %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0 129 %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1 130 resume { i8*, i32 } %new_ehvals 131 } 132 133 ; We can't prune this merge because one landingpad is a cleanup pad. 134 135 ; CHECK-LABEL: define i32 @catch_cleanup_merge() 136 ; CHECK: invoke void @might_throw() 137 ; CHECK: invoke void @might_throw() 138 ; CHECK: ret i32 0 139 ; 140 ; CHECK: outer_lpad: 141 ; CHECK: landingpad { i8*, i32 } 142 ; CHECK: br label %catch.dispatch 143 ; 144 ; CHECK: inner_lpad: 145 ; CHECK: landingpad { i8*, i32 } 146 ; CHECK: call void @cleanup() 147 ; CHECK: br label %catch.dispatch 148 ; 149 ; CHECK: catch.dispatch: 150 ; CHECK: call i32 @llvm.eh.typeid.for 151 ; CHECK: br i1 152 ; CHECK: catch_int: 153 ; CHECK: ret i32 1 154 ; CHECK: eh.resume: 155 ; CHECK-NEXT: call void @_Unwind_Resume(i8* %ehptr) 156 157 declare i32 @__gxx_personality_v0(...) 158 declare i32 @llvm.eh.typeid.for(i8*) 159