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