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