1; RUN: opt < %s -simplifycfg -S | FileCheck %s 2 3declare void @f() 4declare void @llvm.foo(i32) nounwind 5declare void @ProcessCLRException() 6 7define void @test1() personality void ()* @ProcessCLRException { 8entry: 9 invoke void @f() 10 to label %exit unwind label %exn.dispatch 11exn.dispatch: 12 %cs = catchswitch within none [label %pad1, label %pad2] unwind to caller 13pad1: 14 %cp1 = catchpad within %cs [i32 1] 15 call void @llvm.foo(i32 1) 16 catchret from %cp1 to label %exit 17pad2: 18 %cp2 = catchpad within %cs [i32 2] 19 unreachable 20exit: 21 ret void 22} 23; Remove unreachble catch2, leave catch1 as-is 24; CHECK-LABEL: define void @test1() 25; CHECK: %cs = catchswitch within none [label %pad1] unwind to caller 26; CHECK-NOT: catchpad 27; CHECK: %cp1 = catchpad within %cs [i32 1] 28; CHECK-NOT: catchpad 29 30; Remove both catchpads and the catchswitch from exn.dispatch 31; CHECK-LABEL: define void @test2() 32define void @test2() personality void ()* @ProcessCLRException { 33entry: 34 invoke void @f() 35 to label %via.cleanup unwind label %exn.dispatch 36 ; CHECK-NOT: invoke 37 ; CHECK: call void @f() 38via.cleanup: 39 invoke void @f() 40 to label %via.catchswitch unwind label %cleanup.inner 41cleanup.inner: 42 %cp.inner = cleanuppad within none [] 43 call void @llvm.foo(i32 0) 44 cleanupret from %cp.inner unwind label %exn.dispatch 45 ; CHECK: cleanupret from %cp.inner unwind to caller 46via.catchswitch: 47 invoke void @f() 48 to label %exit unwind label %dispatch.inner 49dispatch.inner: 50 %cs.inner = catchswitch within none [label %pad.inner] unwind label %exn.dispatch 51 ; CHECK: %cs.inner = catchswitch within none [label %pad.inner] unwind to caller 52pad.inner: 53 %catch.inner = catchpad within %cs.inner [i32 0] 54 ; CHECK: %catch.inner = catchpad within %cs.inner 55 call void @llvm.foo(i32 1) 56 catchret from %catch.inner to label %exit 57exn.dispatch: 58 %cs = catchswitch within none [label %pad1, label %pad2] unwind to caller 59 ; CHECK-NOT: catchswitch within 60 ; CHECK-NOT: catchpad 61pad1: 62 catchpad within %cs [i32 1] 63 unreachable 64pad2: 65 catchpad within %cs [i32 2] 66 unreachable 67exit: 68 ret void 69} 70 71; Same as @test2, but exn.dispatch catchswitch has an unwind dest that 72; preds need to be reidrected to 73; CHECK-LABEL: define void @test3() 74define void @test3() personality void ()* @ProcessCLRException { 75entry: 76 invoke void @f() 77 to label %via.cleanup unwind label %exn.dispatch 78 ; CHECK: invoke void @f() 79 ; CHECK-NEXT: to label %via.cleanup unwind label %cleanup 80via.cleanup: 81 invoke void @f() 82 to label %via.catchswitch unwind label %cleanup.inner 83cleanup.inner: 84 %cp.inner = cleanuppad within none [] 85 call void @llvm.foo(i32 0) 86 cleanupret from %cp.inner unwind label %exn.dispatch 87 ; CHECK: cleanupret from %cp.inner unwind label %cleanup 88via.catchswitch: 89 invoke void @f() 90 to label %exit unwind label %dispatch.inner 91dispatch.inner: 92 %cs.inner = catchswitch within none [label %pad.inner] unwind label %exn.dispatch 93 ; CHECK: %cs.inner = catchswitch within none [label %pad.inner] unwind label %cleanup 94pad.inner: 95 %catch.inner = catchpad within %cs.inner [i32 0] 96 ; CHECK: %catch.inner = catchpad within %cs.inner 97 call void @llvm.foo(i32 1) 98 catchret from %catch.inner to label %exit 99exn.dispatch: 100 %cs = catchswitch within none [label %pad1, label %pad2] unwind label %cleanup 101 ; CHECK-NOT: catchswitch within 102 ; CHECK-NOT: catchpad 103pad1: 104 catchpad within %cs [i32 1] 105 unreachable 106pad2: 107 catchpad within %cs [i32 2] 108 unreachable 109cleanup: 110 %cp = cleanuppad within none [] 111 call void @llvm.foo(i32 0) 112 cleanupret from %cp unwind to caller 113exit: 114 ret void 115} 116