xref: /llvm-project/llvm/test/Transforms/Inline/invoke-combine-clauses.ll (revision 151602c7a9935558ca671b35359989b261045db0)
1; RUN: opt %s -passes='cgscc(inline)' -S | FileCheck %s
2; RUN: opt %s -passes='module-inline' -S | FileCheck %s
3
4declare void @external_func()
5declare void @abort()
6
7@exception_inner = external global i8
8@exception_outer = external global i8
9@condition = external global i1
10
11
12; Check for a bug in which multiple "resume" instructions in the
13; inlined function caused "catch ptr @exception_outer" to appear
14; multiple times in the resulting landingpad.
15
16define internal void @inner_multiple_resume() personality ptr null {
17  invoke void @external_func()
18      to label %cont unwind label %lpad
19cont:
20  ret void
21lpad:
22  %lp = landingpad i32
23      catch ptr @exception_inner
24  %cond = load i1, ptr @condition
25  br i1 %cond, label %resume1, label %resume2
26resume1:
27  resume i32 1
28resume2:
29  resume i32 2
30}
31
32define void @outer_multiple_resume() personality ptr null {
33  invoke void @inner_multiple_resume()
34      to label %cont unwind label %lpad
35cont:
36  ret void
37lpad:
38  %lp = landingpad i32
39      catch ptr @exception_outer
40  resume i32 %lp
41}
42; CHECK: define void @outer_multiple_resume()
43; CHECK: %lp.i = landingpad
44; CHECK-NEXT: catch ptr @exception_inner
45; CHECK-NEXT: catch ptr @exception_outer
46; Check that there isn't another "catch" clause:
47; CHECK-NEXT: load
48
49
50; Check for a bug in which having a "resume" and a "call" in the
51; inlined function caused "catch ptr @exception_outer" to appear
52; multiple times in the resulting landingpad.
53
54define internal void @inner_resume_and_call() personality ptr null {
55  call void @external_func()
56  invoke void @external_func()
57      to label %cont unwind label %lpad
58cont:
59  ret void
60lpad:
61  %lp = landingpad i32
62      catch ptr @exception_inner
63  resume i32 %lp
64}
65
66define void @outer_resume_and_call() personality ptr null {
67  invoke void @inner_resume_and_call()
68      to label %cont unwind label %lpad
69cont:
70  ret void
71lpad:
72  %lp = landingpad i32
73      catch ptr @exception_outer
74  resume i32 %lp
75}
76; CHECK: define void @outer_resume_and_call()
77; CHECK: %lp.i = landingpad
78; CHECK-NEXT: catch ptr @exception_inner
79; CHECK-NEXT: catch ptr @exception_outer
80; Check that there isn't another "catch" clause:
81; CHECK-NEXT: br
82
83
84; Check what happens if the inlined function contains an "invoke" but
85; no "resume".  In this case, the inlined landingpad does not need to
86; include the "catch ptr @exception_outer" clause from the outer
87; function (since the outer function's landingpad will not be
88; reachable), but it's OK to include this clause.
89
90define internal void @inner_no_resume_or_call() personality ptr null {
91  invoke void @external_func()
92      to label %cont unwind label %lpad
93cont:
94  ret void
95lpad:
96  %lp = landingpad i32
97      catch ptr @exception_inner
98  ; A landingpad might have no "resume" if a C++ destructor aborts.
99  call void @abort() noreturn nounwind
100  unreachable
101}
102
103define void @outer_no_resume_or_call() personality ptr null {
104  invoke void @inner_no_resume_or_call()
105      to label %cont unwind label %lpad
106cont:
107  ret void
108lpad:
109  %lp = landingpad i32
110      catch ptr @exception_outer
111  resume i32 %lp
112}
113; CHECK: define void @outer_no_resume_or_call()
114; CHECK: %lp.i = landingpad
115; CHECK-NEXT: catch ptr @exception_inner
116; CHECK-NEXT: catch ptr @exception_outer
117; Check that there isn't another "catch" clause:
118; CHECK-NEXT: call void @abort()
119