1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals 2; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s 3 4declare void @f() 5declare void @llvm.foo(i32) nounwind 6declare void @ProcessCLRException() 7 8define void @test1() personality ptr @ProcessCLRException { 9; CHECK-LABEL: @test1( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: invoke void @f() 12; CHECK-NEXT: to label [[EXIT:%.*]] unwind label [[EXN_DISPATCH:%.*]] 13; CHECK: exn.dispatch: 14; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %pad1] unwind to caller 15; CHECK: pad1: 16; CHECK-NEXT: [[CP1:%.*]] = catchpad within [[CS]] [i32 1] 17; CHECK-NEXT: call void @llvm.foo(i32 1) 18; CHECK-NEXT: catchret from [[CP1]] to label [[EXIT]] 19; CHECK: exit: 20; CHECK-NEXT: ret void 21; 22entry: 23 invoke void @f() 24 to label %exit unwind label %exn.dispatch 25exn.dispatch: 26 %cs = catchswitch within none [label %pad1, label %pad2] unwind to caller 27pad1: 28 %cp1 = catchpad within %cs [i32 1] 29 call void @llvm.foo(i32 1) 30 catchret from %cp1 to label %exit 31pad2: 32 %cp2 = catchpad within %cs [i32 2] 33 unreachable 34exit: 35 ret void 36} 37; Remove unreachble catch2, leave catch1 as-is 38 39; Remove both catchpads and the catchswitch from exn.dispatch 40define void @test2() personality ptr @ProcessCLRException { 41; CHECK-LABEL: @test2( 42; CHECK-NEXT: entry: 43; CHECK-NEXT: call void @f() 44; CHECK-NEXT: invoke void @f() 45; CHECK-NEXT: to label [[VIA_CATCHSWITCH:%.*]] unwind label [[CLEANUP_INNER:%.*]] 46; CHECK: cleanup.inner: 47; CHECK-NEXT: [[CP_INNER:%.*]] = cleanuppad within none [] 48; CHECK-NEXT: call void @llvm.foo(i32 0) 49; CHECK-NEXT: cleanupret from [[CP_INNER]] unwind to caller 50; CHECK: via.catchswitch: 51; CHECK-NEXT: invoke void @f() 52; CHECK-NEXT: to label [[EXIT:%.*]] unwind label [[DISPATCH_INNER:%.*]] 53; CHECK: dispatch.inner: 54; CHECK-NEXT: [[CS_INNER:%.*]] = catchswitch within none [label %pad.inner] unwind to caller 55; CHECK: pad.inner: 56; CHECK-NEXT: [[CATCH_INNER:%.*]] = catchpad within [[CS_INNER]] [i32 0] 57; CHECK-NEXT: call void @llvm.foo(i32 1) 58; CHECK-NEXT: catchret from [[CATCH_INNER]] to label [[EXIT]] 59; CHECK: exit: 60; CHECK-NEXT: ret void 61; 62entry: 63 invoke void @f() 64 to label %via.cleanup unwind label %exn.dispatch 65via.cleanup: 66 invoke void @f() 67 to label %via.catchswitch unwind label %cleanup.inner 68cleanup.inner: 69 %cp.inner = cleanuppad within none [] 70 call void @llvm.foo(i32 0) 71 cleanupret from %cp.inner unwind label %exn.dispatch 72via.catchswitch: 73 invoke void @f() 74 to label %exit unwind label %dispatch.inner 75dispatch.inner: 76 %cs.inner = catchswitch within none [label %pad.inner] unwind label %exn.dispatch 77pad.inner: 78 %catch.inner = catchpad within %cs.inner [i32 0] 79 call void @llvm.foo(i32 1) 80 catchret from %catch.inner to label %exit 81exn.dispatch: 82 %cs = catchswitch within none [label %pad1, label %pad2] unwind to caller 83pad1: 84 catchpad within %cs [i32 1] 85 unreachable 86pad2: 87 catchpad within %cs [i32 2] 88 unreachable 89exit: 90 ret void 91} 92 93; Same as @test2, but exn.dispatch catchswitch has an unwind dest that 94; preds need to be reidrected to 95define void @test3() personality ptr @ProcessCLRException { 96; CHECK-LABEL: @test3( 97; CHECK-NEXT: entry: 98; CHECK-NEXT: invoke void @f() 99; CHECK-NEXT: to label [[VIA_CLEANUP:%.*]] unwind label [[CLEANUP:%.*]] 100; CHECK: via.cleanup: 101; CHECK-NEXT: invoke void @f() 102; CHECK-NEXT: to label [[VIA_CATCHSWITCH:%.*]] unwind label [[CLEANUP_INNER:%.*]] 103; CHECK: cleanup.inner: 104; CHECK-NEXT: [[CP_INNER:%.*]] = cleanuppad within none [] 105; CHECK-NEXT: call void @llvm.foo(i32 0) 106; CHECK-NEXT: cleanupret from [[CP_INNER]] unwind label [[CLEANUP]] 107; CHECK: via.catchswitch: 108; CHECK-NEXT: invoke void @f() 109; CHECK-NEXT: to label [[EXIT:%.*]] unwind label [[DISPATCH_INNER:%.*]] 110; CHECK: dispatch.inner: 111; CHECK-NEXT: [[CS_INNER:%.*]] = catchswitch within none [label %pad.inner] unwind label [[CLEANUP]] 112; CHECK: pad.inner: 113; CHECK-NEXT: [[CATCH_INNER:%.*]] = catchpad within [[CS_INNER]] [i32 0] 114; CHECK-NEXT: call void @llvm.foo(i32 1) 115; CHECK-NEXT: catchret from [[CATCH_INNER]] to label [[EXIT]] 116; CHECK: cleanup: 117; CHECK-NEXT: [[CP:%.*]] = cleanuppad within none [] 118; CHECK-NEXT: call void @llvm.foo(i32 0) 119; CHECK-NEXT: cleanupret from [[CP]] unwind to caller 120; CHECK: exit: 121; CHECK-NEXT: ret void 122; 123entry: 124 invoke void @f() 125 to label %via.cleanup unwind label %exn.dispatch 126via.cleanup: 127 invoke void @f() 128 to label %via.catchswitch unwind label %cleanup.inner 129cleanup.inner: 130 %cp.inner = cleanuppad within none [] 131 call void @llvm.foo(i32 0) 132 cleanupret from %cp.inner unwind label %exn.dispatch 133via.catchswitch: 134 invoke void @f() 135 to label %exit unwind label %dispatch.inner 136dispatch.inner: 137 %cs.inner = catchswitch within none [label %pad.inner] unwind label %exn.dispatch 138pad.inner: 139 %catch.inner = catchpad within %cs.inner [i32 0] 140 call void @llvm.foo(i32 1) 141 catchret from %catch.inner to label %exit 142exn.dispatch: 143 %cs = catchswitch within none [label %pad1, label %pad2] unwind label %cleanup 144pad1: 145 catchpad within %cs [i32 1] 146 unreachable 147pad2: 148 catchpad within %cs [i32 2] 149 unreachable 150cleanup: 151 %cp = cleanuppad within none [] 152 call void @llvm.foo(i32 0) 153 cleanupret from %cp unwind to caller 154exit: 155 ret void 156} 157;. 158; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind } 159;. 160