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 9declare void @might_throw() 10declare void @cleanup() 11 12define i32 @simple_cleanup_catch() { 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 19cont: 20 ret i32 0 21 22; CHECK: ret i32 0 23 24lpad: 25 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 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 } personality i32 (...)* @__gxx_personality_v0 37; CHECK: call void @cleanup() 38; CHECK: call i32 @llvm.eh.typeid.for 39; CHECK: br i1 40 41catch_int: 42 ret i32 1 43 44; CHECK: catch_int: 45; CHECK: ret i32 1 46 47eh.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 57define i32 @catch_no_resume() { 58 invoke void @might_throw() 59 to label %cont unwind label %lpad 60 61cont: 62 ret i32 0 63 64lpad: 65 %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 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 73catch_int: 74 ret i32 1 75 76eh.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() { 85; CHECK: invoke void @might_throw() 86; CHECK: ret i32 0 87; CHECK: lpad: 88; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 89; CHECK-NOT: br i1 90; CHECK: ret i32 1 91; CHECK-NOT: call void @_Unwind_Resume 92; CHECK: {{^[}]}} 93 94 95define i32 @catch_cleanup_merge() { 96 invoke void @might_throw() 97 to label %inner_invoke unwind label %outer_lpad 98inner_invoke: 99 invoke void @might_throw() 100 to label %cont unwind label %inner_lpad 101cont: 102 ret i32 0 103 104outer_lpad: 105 %ehvals1 = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 106 catch i8* @int_typeinfo 107 br label %catch.dispatch 108 109inner_lpad: 110 %ehvals2 = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 111 cleanup 112 catch i8* @int_typeinfo 113 call void @cleanup() 114 br label %catch.dispatch 115 116catch.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 124catch_int: 125 ret i32 1 126 127eh.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 } personality i32 (...)* @__gxx_personality_v0 142; CHECK: br label %catch.dispatch 143; 144; CHECK: inner_lpad: 145; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 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 157declare i32 @__gxx_personality_v0(...) 158declare i32 @llvm.eh.typeid.for(i8*) 159