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