+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+declare void @f()
+declare void @llvm.foo(i32) nounwind
+declare void @ProcessCLRException()
+
+define void @test1() personality void ()* @ProcessCLRException {
+entry:
+ invoke void @f()
+ to label %exit unwind label %exn.dispatch
+exn.dispatch:
+ %cs = catchswitch within none [label %pad1, label %pad2] unwind to caller
+pad1:
+ %cp1 = catchpad within %cs [i32 1]
+ call void @llvm.foo(i32 1)
+ catchret from %cp1 to label %exit
+pad2:
+ %cp2 = catchpad within %cs [i32 2]
+ unreachable
+exit:
+ ret void
+}
+; Remove unreachble catch2, leave catch1 as-is
+; CHECK-LABEL: define void @test1()
+; CHECK: %cs = catchswitch within none [label %pad1] unwind to caller
+; CHECK-NOT: catchpad
+; CHECK: %cp1 = catchpad within %cs [i32 1]
+; CHECK-NOT: catchpad
+
+; Remove both catchpads and the catchswitch from exn.dispatch
+; CHECK-LABEL: define void @test2()
+define void @test2() personality void ()* @ProcessCLRException {
+entry:
+ invoke void @f()
+ to label %via.cleanup unwind label %exn.dispatch
+ ; CHECK-NOT: invoke
+ ; CHECK: call void @f()
+via.cleanup:
+ invoke void @f()
+ to label %via.catchswitch unwind label %cleanup.inner
+cleanup.inner:
+ %cp.inner = cleanuppad within none []
+ call void @llvm.foo(i32 0)
+ cleanupret from %cp.inner unwind label %exn.dispatch
+ ; CHECK: cleanupret from %cp.inner unwind to caller
+via.catchswitch:
+ invoke void @f()
+ to label %exit unwind label %dispatch.inner
+dispatch.inner:
+ %cs.inner = catchswitch within none [label %pad.inner] unwind label %exn.dispatch
+ ; CHECK: %cs.inner = catchswitch within none [label %pad.inner] unwind to caller
+pad.inner:
+ %catch.inner = catchpad within %cs.inner [i32 0]
+ ; CHECK: %catch.inner = catchpad within %cs.inner
+ call void @llvm.foo(i32 1)
+ catchret from %catch.inner to label %exit
+exn.dispatch:
+ %cs = catchswitch within none [label %pad1, label %pad2] unwind to caller
+ ; CHECK-NOT: catchswitch within
+ ; CHECK-NOT: catchpad
+pad1:
+ catchpad within %cs [i32 1]
+ unreachable
+pad2:
+ catchpad within %cs [i32 2]
+ unreachable
+exit:
+ ret void
+}
+
+; Same as @test2, but exn.dispatch catchswitch has an unwind dest that
+; preds need to be reidrected to
+; CHECK-LABEL: define void @test3()
+define void @test3() personality void ()* @ProcessCLRException {
+entry:
+ invoke void @f()
+ to label %via.cleanup unwind label %exn.dispatch
+ ; CHECK: invoke void @f()
+ ; CHECK-NEXT: to label %via.cleanup unwind label %cleanup
+via.cleanup:
+ invoke void @f()
+ to label %via.catchswitch unwind label %cleanup.inner
+cleanup.inner:
+ %cp.inner = cleanuppad within none []
+ call void @llvm.foo(i32 0)
+ cleanupret from %cp.inner unwind label %exn.dispatch
+ ; CHECK: cleanupret from %cp.inner unwind label %cleanup
+via.catchswitch:
+ invoke void @f()
+ to label %exit unwind label %dispatch.inner
+dispatch.inner:
+ %cs.inner = catchswitch within none [label %pad.inner] unwind label %exn.dispatch
+ ; CHECK: %cs.inner = catchswitch within none [label %pad.inner] unwind label %cleanup
+pad.inner:
+ %catch.inner = catchpad within %cs.inner [i32 0]
+ ; CHECK: %catch.inner = catchpad within %cs.inner
+ call void @llvm.foo(i32 1)
+ catchret from %catch.inner to label %exit
+exn.dispatch:
+ %cs = catchswitch within none [label %pad1, label %pad2] unwind label %cleanup
+ ; CHECK-NOT: catchswitch within
+ ; CHECK-NOT: catchpad
+pad1:
+ catchpad within %cs [i32 1]
+ unreachable
+pad2:
+ catchpad within %cs [i32 2]
+ unreachable
+cleanup:
+ %cp = cleanuppad within none []
+ call void @llvm.foo(i32 0)
+ cleanupret from %cp unwind to caller
+exit:
+ ret void
+}