; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s declare void @f() declare void @llvm.foo(i32) nounwind declare void @ProcessCLRException() define void @test1() personality void ()* @ProcessCLRException { ; CHECK-LABEL: @test1( ; CHECK-NEXT: entry: ; CHECK-NEXT: invoke void @f() ; CHECK-NEXT: to label [[EXIT:%.*]] unwind label [[EXN_DISPATCH:%.*]] ; CHECK: exn.dispatch: ; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %pad1] unwind to caller ; CHECK: pad1: ; CHECK-NEXT: [[CP1:%.*]] = catchpad within [[CS]] [i32 1] ; CHECK-NEXT: call void @llvm.foo(i32 1) ; CHECK-NEXT: catchret from [[CP1]] to label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret void ; 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 ; Remove both catchpads and the catchswitch from exn.dispatch define void @test2() personality void ()* @ProcessCLRException { ; CHECK-LABEL: @test2( ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @f() ; CHECK-NEXT: invoke void @f() ; CHECK-NEXT: to label [[VIA_CATCHSWITCH:%.*]] unwind label [[CLEANUP_INNER:%.*]] ; CHECK: cleanup.inner: ; CHECK-NEXT: [[CP_INNER:%.*]] = cleanuppad within none [] ; CHECK-NEXT: call void @llvm.foo(i32 0) ; CHECK-NEXT: cleanupret from [[CP_INNER]] unwind to caller ; CHECK: via.catchswitch: ; CHECK-NEXT: invoke void @f() ; CHECK-NEXT: to label [[EXIT:%.*]] unwind label [[DISPATCH_INNER:%.*]] ; CHECK: dispatch.inner: ; CHECK-NEXT: [[CS_INNER:%.*]] = catchswitch within none [label %pad.inner] unwind to caller ; CHECK: pad.inner: ; CHECK-NEXT: [[CATCH_INNER:%.*]] = catchpad within [[CS_INNER]] [i32 0] ; CHECK-NEXT: call void @llvm.foo(i32 1) ; CHECK-NEXT: catchret from [[CATCH_INNER]] to label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret void ; entry: invoke void @f() to label %via.cleanup unwind label %exn.dispatch 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 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 pad.inner: %catch.inner = catchpad within %cs.inner [i32 0] 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 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 define void @test3() personality void ()* @ProcessCLRException { ; CHECK-LABEL: @test3( ; CHECK-NEXT: entry: ; CHECK-NEXT: invoke void @f() ; CHECK-NEXT: to label [[VIA_CLEANUP:%.*]] unwind label [[CLEANUP:%.*]] ; CHECK: via.cleanup: ; CHECK-NEXT: invoke void @f() ; CHECK-NEXT: to label [[VIA_CATCHSWITCH:%.*]] unwind label [[CLEANUP_INNER:%.*]] ; CHECK: cleanup.inner: ; CHECK-NEXT: [[CP_INNER:%.*]] = cleanuppad within none [] ; CHECK-NEXT: call void @llvm.foo(i32 0) ; CHECK-NEXT: cleanupret from [[CP_INNER]] unwind label [[CLEANUP]] ; CHECK: via.catchswitch: ; CHECK-NEXT: invoke void @f() ; CHECK-NEXT: to label [[EXIT:%.*]] unwind label [[DISPATCH_INNER:%.*]] ; CHECK: dispatch.inner: ; CHECK-NEXT: [[CS_INNER:%.*]] = catchswitch within none [label %pad.inner] unwind label [[CLEANUP]] ; CHECK: pad.inner: ; CHECK-NEXT: [[CATCH_INNER:%.*]] = catchpad within [[CS_INNER]] [i32 0] ; CHECK-NEXT: call void @llvm.foo(i32 1) ; CHECK-NEXT: catchret from [[CATCH_INNER]] to label [[EXIT]] ; CHECK: cleanup: ; CHECK-NEXT: [[CP:%.*]] = cleanuppad within none [] ; CHECK-NEXT: call void @llvm.foo(i32 0) ; CHECK-NEXT: cleanupret from [[CP]] unwind to caller ; CHECK: exit: ; CHECK-NEXT: ret void ; entry: invoke void @f() to label %via.cleanup unwind label %exn.dispatch 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 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 pad.inner: %catch.inner = catchpad within %cs.inner [i32 0] 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 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 }