xref: /aosp_15_r20/external/llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: opt < %s -simplifycfg -S | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker
3*9880d681SAndroid Build Coastguard Worker; ModuleID = 'cppeh-simplify.cpp'
4*9880d681SAndroid Build Coastguard Workertarget datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
5*9880d681SAndroid Build Coastguard Workertarget triple = "x86_64-pc-windows-msvc18.0.0"
6*9880d681SAndroid Build Coastguard Worker
7*9880d681SAndroid Build Coastguard Worker
8*9880d681SAndroid Build Coastguard Worker; This case arises when two objects with empty destructors are cleaned up.
9*9880d681SAndroid Build Coastguard Worker;
10*9880d681SAndroid Build Coastguard Worker; void f1() {
11*9880d681SAndroid Build Coastguard Worker;   S a;
12*9880d681SAndroid Build Coastguard Worker;   S b;
13*9880d681SAndroid Build Coastguard Worker;   g();
14*9880d681SAndroid Build Coastguard Worker; }
15*9880d681SAndroid Build Coastguard Worker;
16*9880d681SAndroid Build Coastguard Worker; In this case, both cleanup pads can be eliminated and the invoke can be
17*9880d681SAndroid Build Coastguard Worker; converted to a call.
18*9880d681SAndroid Build Coastguard Worker;
19*9880d681SAndroid Build Coastguard Worker; CHECK: define void @f1()
20*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
21*9880d681SAndroid Build Coastguard Worker; CHECK:   call void @g()
22*9880d681SAndroid Build Coastguard Worker; CHECK:   ret void
23*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cleanuppad
24*9880d681SAndroid Build Coastguard Worker; CHECK: }
25*9880d681SAndroid Build Coastguard Worker;
26*9880d681SAndroid Build Coastguard Workerdefine void @f1() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
27*9880d681SAndroid Build Coastguard Workerentry:
28*9880d681SAndroid Build Coastguard Worker  invoke void @g() to label %invoke.cont unwind label %ehcleanup
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Workerinvoke.cont:                                      ; preds = %entry
31*9880d681SAndroid Build Coastguard Worker  ret void
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Workerehcleanup:                                        ; preds = %entry
34*9880d681SAndroid Build Coastguard Worker  %0 = cleanuppad within none []
35*9880d681SAndroid Build Coastguard Worker  cleanupret from %0 unwind label %ehcleanup.1
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Workerehcleanup.1:                                      ; preds = %ehcleanup
38*9880d681SAndroid Build Coastguard Worker  %1 = cleanuppad within none []
39*9880d681SAndroid Build Coastguard Worker  cleanupret from %1 unwind to caller
40*9880d681SAndroid Build Coastguard Worker}
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker
43*9880d681SAndroid Build Coastguard Worker; This case arises when an object with an empty destructor must be cleaned up
44*9880d681SAndroid Build Coastguard Worker; outside of a try-block and an object with a non-empty destructor must be
45*9880d681SAndroid Build Coastguard Worker; cleaned up within the try-block.
46*9880d681SAndroid Build Coastguard Worker;
47*9880d681SAndroid Build Coastguard Worker; void f2() {
48*9880d681SAndroid Build Coastguard Worker;   S a;
49*9880d681SAndroid Build Coastguard Worker;   try {
50*9880d681SAndroid Build Coastguard Worker;     S2 b;
51*9880d681SAndroid Build Coastguard Worker;     g();
52*9880d681SAndroid Build Coastguard Worker;   } catch (...) {}
53*9880d681SAndroid Build Coastguard Worker; }
54*9880d681SAndroid Build Coastguard Worker;
55*9880d681SAndroid Build Coastguard Worker; In this case, the outermost cleanup pad can be eliminated and the catch block
56*9880d681SAndroid Build Coastguard Worker; should unwind to the caller (that is, exception handling continues with the
57*9880d681SAndroid Build Coastguard Worker; parent frame of the caller).
58*9880d681SAndroid Build Coastguard Worker;
59*9880d681SAndroid Build Coastguard Worker; CHECK: define void @f2()
60*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
61*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @g()
62*9880d681SAndroid Build Coastguard Worker; CHECK: ehcleanup:
63*9880d681SAndroid Build Coastguard Worker; CHECK:   cleanuppad within none
64*9880d681SAndroid Build Coastguard Worker; CHECK:   call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %b)
65*9880d681SAndroid Build Coastguard Worker; CHECK:   cleanupret from %0 unwind label %catch.dispatch
66*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch:
67*9880d681SAndroid Build Coastguard Worker; CHECK:   catchswitch within none [label %catch] unwind to caller
68*9880d681SAndroid Build Coastguard Worker; CHECK: catch:
69*9880d681SAndroid Build Coastguard Worker; CHECK:   catchpad
70*9880d681SAndroid Build Coastguard Worker; CHECK:   catchret
71*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cleanuppad
72*9880d681SAndroid Build Coastguard Worker; CHECK: }
73*9880d681SAndroid Build Coastguard Worker;
74*9880d681SAndroid Build Coastguard Workerdefine void @f2() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
75*9880d681SAndroid Build Coastguard Workerentry:
76*9880d681SAndroid Build Coastguard Worker  %b = alloca %struct.S2, align 1
77*9880d681SAndroid Build Coastguard Worker  invoke void @g() to label %invoke.cont unwind label %ehcleanup
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Workerinvoke.cont:                                      ; preds = %entry
80*9880d681SAndroid Build Coastguard Worker  br label %try.cont
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Workerehcleanup:                                        ; preds = %entry
83*9880d681SAndroid Build Coastguard Worker  %0 = cleanuppad within none []
84*9880d681SAndroid Build Coastguard Worker  call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %b)
85*9880d681SAndroid Build Coastguard Worker  cleanupret from %0 unwind label %catch.dispatch
86*9880d681SAndroid Build Coastguard Worker
87*9880d681SAndroid Build Coastguard Workercatch.dispatch:                                   ; preds = %ehcleanup
88*9880d681SAndroid Build Coastguard Worker  %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Workercatch:                                            ; preds = %catch.dispatch
91*9880d681SAndroid Build Coastguard Worker  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
92*9880d681SAndroid Build Coastguard Worker  catchret from %1 to label %catchret.dest
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Workercatchret.dest:                                    ; preds = %catch
95*9880d681SAndroid Build Coastguard Worker  br label %try.cont
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Workertry.cont:                                         ; preds = %catchret.dest, %invoke.cont
98*9880d681SAndroid Build Coastguard Worker  ret void
99*9880d681SAndroid Build Coastguard Worker
100*9880d681SAndroid Build Coastguard Workerehcleanup.1:
101*9880d681SAndroid Build Coastguard Worker  %2 = cleanuppad within none []
102*9880d681SAndroid Build Coastguard Worker  cleanupret from %2 unwind to caller
103*9880d681SAndroid Build Coastguard Worker}
104*9880d681SAndroid Build Coastguard Worker
105*9880d681SAndroid Build Coastguard Worker
106*9880d681SAndroid Build Coastguard Worker; This case arises when an object with a non-empty destructor must be cleaned up
107*9880d681SAndroid Build Coastguard Worker; outside of a try-block and an object with an empty destructor must be cleaned
108*9880d681SAndroid Build Coastguard Worker; within the try-block.
109*9880d681SAndroid Build Coastguard Worker;
110*9880d681SAndroid Build Coastguard Worker; void f3() {
111*9880d681SAndroid Build Coastguard Worker;   S2 a;
112*9880d681SAndroid Build Coastguard Worker;   try {
113*9880d681SAndroid Build Coastguard Worker;     S b;
114*9880d681SAndroid Build Coastguard Worker;     g();
115*9880d681SAndroid Build Coastguard Worker;   } catch (...) {}
116*9880d681SAndroid Build Coastguard Worker; }
117*9880d681SAndroid Build Coastguard Worker;
118*9880d681SAndroid Build Coastguard Worker; In this case the inner cleanup pad should be eliminated and the invoke of g()
119*9880d681SAndroid Build Coastguard Worker; should unwind directly to the catchpad.
120*9880d681SAndroid Build Coastguard Worker;
121*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @f3()
122*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
123*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @g()
124*9880d681SAndroid Build Coastguard Worker; CHECK:           to label %try.cont unwind label %catch.dispatch
125*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch:
126*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: catchswitch within none [label %catch] unwind label %ehcleanup.1
127*9880d681SAndroid Build Coastguard Worker; CHECK: catch:
128*9880d681SAndroid Build Coastguard Worker; CHECK:   catchpad within %cs1 [i8* null, i32 64, i8* null]
129*9880d681SAndroid Build Coastguard Worker; CHECK:   catchret
130*9880d681SAndroid Build Coastguard Worker; CHECK: ehcleanup.1:
131*9880d681SAndroid Build Coastguard Worker; CHECK:   cleanuppad
132*9880d681SAndroid Build Coastguard Worker; CHECK:   call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a)
133*9880d681SAndroid Build Coastguard Worker; CHECK:   cleanupret from %cp3 unwind to caller
134*9880d681SAndroid Build Coastguard Worker; CHECK: }
135*9880d681SAndroid Build Coastguard Worker;
136*9880d681SAndroid Build Coastguard Workerdefine void @f3() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
137*9880d681SAndroid Build Coastguard Workerentry:
138*9880d681SAndroid Build Coastguard Worker  %a = alloca %struct.S2, align 1
139*9880d681SAndroid Build Coastguard Worker  invoke void @g() to label %invoke.cont unwind label %ehcleanup
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Workerinvoke.cont:                                      ; preds = %entry
142*9880d681SAndroid Build Coastguard Worker  br label %try.cont
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Workerehcleanup:                                        ; preds = %entry
145*9880d681SAndroid Build Coastguard Worker  %0 = cleanuppad within none []
146*9880d681SAndroid Build Coastguard Worker  cleanupret from %0 unwind label %catch.dispatch
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Workercatch.dispatch:                                   ; preds = %ehcleanup
149*9880d681SAndroid Build Coastguard Worker  %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1
150*9880d681SAndroid Build Coastguard Worker
151*9880d681SAndroid Build Coastguard Workercatch:                                            ; preds = %catch.dispatch
152*9880d681SAndroid Build Coastguard Worker  %cp2 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
153*9880d681SAndroid Build Coastguard Worker  catchret from %cp2 to label %catchret.dest
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Workercatchret.dest:                                    ; preds = %catch
156*9880d681SAndroid Build Coastguard Worker  br label %try.cont
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Workertry.cont:                                         ; preds = %catchret.dest, %invoke.cont
159*9880d681SAndroid Build Coastguard Worker  ret void
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Workerehcleanup.1:
162*9880d681SAndroid Build Coastguard Worker  %cp3 = cleanuppad within none []
163*9880d681SAndroid Build Coastguard Worker  call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a)
164*9880d681SAndroid Build Coastguard Worker  cleanupret from %cp3 unwind to caller
165*9880d681SAndroid Build Coastguard Worker}
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Worker
168*9880d681SAndroid Build Coastguard Worker; This case arises when an object with an empty destructor may require cleanup
169*9880d681SAndroid Build Coastguard Worker; from either inside or outside of a try-block.
170*9880d681SAndroid Build Coastguard Worker;
171*9880d681SAndroid Build Coastguard Worker; void f4() {
172*9880d681SAndroid Build Coastguard Worker;   S a;
173*9880d681SAndroid Build Coastguard Worker;   g();
174*9880d681SAndroid Build Coastguard Worker;   try {
175*9880d681SAndroid Build Coastguard Worker;     g();
176*9880d681SAndroid Build Coastguard Worker;   } catch (...) {}
177*9880d681SAndroid Build Coastguard Worker; }
178*9880d681SAndroid Build Coastguard Worker;
179*9880d681SAndroid Build Coastguard Worker; In this case, the cleanuppad should be eliminated, the invoke outside of the
180*9880d681SAndroid Build Coastguard Worker; catch block should be converted to a call (that is, that is, exception
181*9880d681SAndroid Build Coastguard Worker; handling continues with the parent frame of the caller).)
182*9880d681SAndroid Build Coastguard Worker;
183*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @f4()
184*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
185*9880d681SAndroid Build Coastguard Worker; CHECK:   call void @g
186*9880d681SAndroid Build Coastguard Worker; Note: The cleanuppad simplification will insert an unconditional branch here
187*9880d681SAndroid Build Coastguard Worker;       but it will be eliminated, placing the following invoke in the entry BB.
188*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @g()
189*9880d681SAndroid Build Coastguard Worker; CHECK:           to label %try.cont unwind label %catch.dispatch
190*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch:
191*9880d681SAndroid Build Coastguard Worker; CHECK:   catchswitch within none [label %catch] unwind to caller
192*9880d681SAndroid Build Coastguard Worker; CHECK: catch:
193*9880d681SAndroid Build Coastguard Worker; CHECK:   catchpad
194*9880d681SAndroid Build Coastguard Worker; CHECK:   catchret
195*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cleanuppad
196*9880d681SAndroid Build Coastguard Worker; CHECK: }
197*9880d681SAndroid Build Coastguard Worker;
198*9880d681SAndroid Build Coastguard Workerdefine void @f4() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
199*9880d681SAndroid Build Coastguard Workerentry:
200*9880d681SAndroid Build Coastguard Worker  invoke void @g()
201*9880d681SAndroid Build Coastguard Worker          to label %invoke.cont unwind label %ehcleanup
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Workerinvoke.cont:                                      ; preds = %entry
204*9880d681SAndroid Build Coastguard Worker  invoke void @g()
205*9880d681SAndroid Build Coastguard Worker          to label %try.cont unwind label %catch.dispatch
206*9880d681SAndroid Build Coastguard Worker
207*9880d681SAndroid Build Coastguard Workercatch.dispatch:                                   ; preds = %invoke.cont
208*9880d681SAndroid Build Coastguard Worker  %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Workercatch:                                            ; preds = %catch.dispatch
211*9880d681SAndroid Build Coastguard Worker  %0 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
212*9880d681SAndroid Build Coastguard Worker  catchret from %0 to label %try.cont
213*9880d681SAndroid Build Coastguard Worker
214*9880d681SAndroid Build Coastguard Workertry.cont:                                         ; preds = %catch, %invoke.cont
215*9880d681SAndroid Build Coastguard Worker  ret void
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Workerehcleanup:
218*9880d681SAndroid Build Coastguard Worker  %cp2 = cleanuppad within none []
219*9880d681SAndroid Build Coastguard Worker  cleanupret from %cp2 unwind to caller
220*9880d681SAndroid Build Coastguard Worker}
221*9880d681SAndroid Build Coastguard Worker
222*9880d681SAndroid Build Coastguard Worker; This case tests simplification of an otherwise empty cleanup pad that contains
223*9880d681SAndroid Build Coastguard Worker; a PHI node.
224*9880d681SAndroid Build Coastguard Worker;
225*9880d681SAndroid Build Coastguard Worker; int f6() {
226*9880d681SAndroid Build Coastguard Worker;   int state = 1;
227*9880d681SAndroid Build Coastguard Worker;   try {
228*9880d681SAndroid Build Coastguard Worker;     S a;
229*9880d681SAndroid Build Coastguard Worker;     g();
230*9880d681SAndroid Build Coastguard Worker;     state = 2;
231*9880d681SAndroid Build Coastguard Worker;     g();
232*9880d681SAndroid Build Coastguard Worker;   } catch (...) {
233*9880d681SAndroid Build Coastguard Worker;     return state;
234*9880d681SAndroid Build Coastguard Worker;   }
235*9880d681SAndroid Build Coastguard Worker;   return 0;
236*9880d681SAndroid Build Coastguard Worker; }
237*9880d681SAndroid Build Coastguard Worker;
238*9880d681SAndroid Build Coastguard Worker; In this case, the cleanup pad should be eliminated and the PHI node in the
239*9880d681SAndroid Build Coastguard Worker; cleanup pad should be sunk into the catch dispatch block.
240*9880d681SAndroid Build Coastguard Worker;
241*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i32 @f6()
242*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
243*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @g()
244*9880d681SAndroid Build Coastguard Worker; CHECK: invoke.cont:
245*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @g()
246*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ehcleanup:
247*9880d681SAndroid Build Coastguard Worker; CHECK-NOT:   cleanuppad
248*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch:
249*9880d681SAndroid Build Coastguard Worker; CHECK:   %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
250*9880d681SAndroid Build Coastguard Worker; CHECK: }
251*9880d681SAndroid Build Coastguard Workerdefine i32 @f6() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
252*9880d681SAndroid Build Coastguard Workerentry:
253*9880d681SAndroid Build Coastguard Worker  invoke void @g()
254*9880d681SAndroid Build Coastguard Worker          to label %invoke.cont unwind label %ehcleanup
255*9880d681SAndroid Build Coastguard Worker
256*9880d681SAndroid Build Coastguard Workerinvoke.cont:                                      ; preds = %entry
257*9880d681SAndroid Build Coastguard Worker  invoke void @g()
258*9880d681SAndroid Build Coastguard Worker          to label %return unwind label %ehcleanup
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Workerehcleanup:                                        ; preds = %invoke.cont, %entry
261*9880d681SAndroid Build Coastguard Worker  %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
262*9880d681SAndroid Build Coastguard Worker  %0 = cleanuppad within none []
263*9880d681SAndroid Build Coastguard Worker  cleanupret from %0 unwind label %catch.dispatch
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Workercatch.dispatch:                                   ; preds = %ehcleanup
266*9880d681SAndroid Build Coastguard Worker  %cs1 = catchswitch within none [label %catch] unwind to caller
267*9880d681SAndroid Build Coastguard Worker
268*9880d681SAndroid Build Coastguard Workercatch:                                            ; preds = %catch.dispatch
269*9880d681SAndroid Build Coastguard Worker  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
270*9880d681SAndroid Build Coastguard Worker  catchret from %1 to label %return
271*9880d681SAndroid Build Coastguard Worker
272*9880d681SAndroid Build Coastguard Workerreturn:                                           ; preds = %invoke.cont, %catch
273*9880d681SAndroid Build Coastguard Worker  %retval.0 = phi i32 [ %state.0, %catch ], [ 0, %invoke.cont ]
274*9880d681SAndroid Build Coastguard Worker  ret i32 %retval.0
275*9880d681SAndroid Build Coastguard Worker}
276*9880d681SAndroid Build Coastguard Worker
277*9880d681SAndroid Build Coastguard Worker; This case tests another variation of simplification of an otherwise empty
278*9880d681SAndroid Build Coastguard Worker; cleanup pad that contains a PHI node.
279*9880d681SAndroid Build Coastguard Worker;
280*9880d681SAndroid Build Coastguard Worker; int f7() {
281*9880d681SAndroid Build Coastguard Worker;   int state = 1;
282*9880d681SAndroid Build Coastguard Worker;   try {
283*9880d681SAndroid Build Coastguard Worker;     g();
284*9880d681SAndroid Build Coastguard Worker;     state = 2;
285*9880d681SAndroid Build Coastguard Worker;     S a;
286*9880d681SAndroid Build Coastguard Worker;     g();
287*9880d681SAndroid Build Coastguard Worker;     state = 3;
288*9880d681SAndroid Build Coastguard Worker;     g();
289*9880d681SAndroid Build Coastguard Worker;   } catch (...) {
290*9880d681SAndroid Build Coastguard Worker;     return state;
291*9880d681SAndroid Build Coastguard Worker;   }
292*9880d681SAndroid Build Coastguard Worker;   return 0;
293*9880d681SAndroid Build Coastguard Worker; }
294*9880d681SAndroid Build Coastguard Worker;
295*9880d681SAndroid Build Coastguard Worker; In this case, the cleanup pad should be eliminated and the PHI node in the
296*9880d681SAndroid Build Coastguard Worker; cleanup pad should be merged with the PHI node in the catch dispatch block.
297*9880d681SAndroid Build Coastguard Worker;
298*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i32 @f7()
299*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
300*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @g()
301*9880d681SAndroid Build Coastguard Worker; CHECK: invoke.cont:
302*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @g()
303*9880d681SAndroid Build Coastguard Worker; CHECK: invoke.cont.1:
304*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @g()
305*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ehcleanup:
306*9880d681SAndroid Build Coastguard Worker; CHECK-NOT:   cleanuppad
307*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch:
308*9880d681SAndroid Build Coastguard Worker; CHECK:   %state.1 = phi i32 [ 1, %entry ], [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ]
309*9880d681SAndroid Build Coastguard Worker; CHECK: }
310*9880d681SAndroid Build Coastguard Workerdefine i32 @f7() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
311*9880d681SAndroid Build Coastguard Workerentry:
312*9880d681SAndroid Build Coastguard Worker  invoke void @g()
313*9880d681SAndroid Build Coastguard Worker          to label %invoke.cont unwind label %catch.dispatch
314*9880d681SAndroid Build Coastguard Worker
315*9880d681SAndroid Build Coastguard Workerinvoke.cont:                                      ; preds = %entry
316*9880d681SAndroid Build Coastguard Worker  invoke void @g()
317*9880d681SAndroid Build Coastguard Worker          to label %invoke.cont.1 unwind label %ehcleanup
318*9880d681SAndroid Build Coastguard Worker
319*9880d681SAndroid Build Coastguard Workerinvoke.cont.1:                                    ; preds = %invoke.cont
320*9880d681SAndroid Build Coastguard Worker  invoke void @g()
321*9880d681SAndroid Build Coastguard Worker          to label %return unwind label %ehcleanup
322*9880d681SAndroid Build Coastguard Worker
323*9880d681SAndroid Build Coastguard Workerehcleanup:                                        ; preds = %invoke.cont.1, %invoke.cont
324*9880d681SAndroid Build Coastguard Worker  %state.0 = phi i32 [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ]
325*9880d681SAndroid Build Coastguard Worker  %0 = cleanuppad within none []
326*9880d681SAndroid Build Coastguard Worker  cleanupret from %0 unwind label %catch.dispatch
327*9880d681SAndroid Build Coastguard Worker
328*9880d681SAndroid Build Coastguard Workercatch.dispatch:                                   ; preds = %ehcleanup, %entry
329*9880d681SAndroid Build Coastguard Worker  %state.1 = phi i32 [ %state.0, %ehcleanup ], [ 1, %entry ]
330*9880d681SAndroid Build Coastguard Worker  %cs1 = catchswitch within none [label %catch] unwind to caller
331*9880d681SAndroid Build Coastguard Worker
332*9880d681SAndroid Build Coastguard Workercatch:                                            ; preds = %catch.dispatch
333*9880d681SAndroid Build Coastguard Worker  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
334*9880d681SAndroid Build Coastguard Worker  catchret from %1 to label %return
335*9880d681SAndroid Build Coastguard Worker
336*9880d681SAndroid Build Coastguard Workerreturn:                                           ; preds = %invoke.cont.1, %catch
337*9880d681SAndroid Build Coastguard Worker  %retval.0 = phi i32 [ %state.1, %catch ], [ 0, %invoke.cont.1 ]
338*9880d681SAndroid Build Coastguard Worker  ret i32 %retval.0
339*9880d681SAndroid Build Coastguard Worker}
340*9880d681SAndroid Build Coastguard Worker
341*9880d681SAndroid Build Coastguard Worker; This case tests a scenario where an empty cleanup pad is not dominated by all
342*9880d681SAndroid Build Coastguard Worker; of the predecessors of its successor, but the successor references a PHI node
343*9880d681SAndroid Build Coastguard Worker; in the empty cleanup pad.
344*9880d681SAndroid Build Coastguard Worker;
345*9880d681SAndroid Build Coastguard Worker; Conceptually, the case being modeled is something like this:
346*9880d681SAndroid Build Coastguard Worker;
347*9880d681SAndroid Build Coastguard Worker; int f8() {
348*9880d681SAndroid Build Coastguard Worker;   int x = 1;
349*9880d681SAndroid Build Coastguard Worker;   try {
350*9880d681SAndroid Build Coastguard Worker;     S a;
351*9880d681SAndroid Build Coastguard Worker;     g();
352*9880d681SAndroid Build Coastguard Worker;     x = 2;
353*9880d681SAndroid Build Coastguard Worker; retry:
354*9880d681SAndroid Build Coastguard Worker;     g();
355*9880d681SAndroid Build Coastguard Worker;     return
356*9880d681SAndroid Build Coastguard Worker;   } catch (...) {
357*9880d681SAndroid Build Coastguard Worker;     use_x(x);
358*9880d681SAndroid Build Coastguard Worker;   }
359*9880d681SAndroid Build Coastguard Worker;   goto retry;
360*9880d681SAndroid Build Coastguard Worker; }
361*9880d681SAndroid Build Coastguard Worker;
362*9880d681SAndroid Build Coastguard Worker; While that C++ syntax isn't legal, the IR below is.
363*9880d681SAndroid Build Coastguard Worker;
364*9880d681SAndroid Build Coastguard Worker; In this case, the PHI node that is sunk from ehcleanup to catch.dispatch
365*9880d681SAndroid Build Coastguard Worker; should have an incoming value entry for path from 'foo' that references the
366*9880d681SAndroid Build Coastguard Worker; PHI node itself.
367*9880d681SAndroid Build Coastguard Worker;
368*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @f8()
369*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
370*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @g()
371*9880d681SAndroid Build Coastguard Worker; CHECK: invoke.cont:
372*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @g()
373*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ehcleanup:
374*9880d681SAndroid Build Coastguard Worker; CHECK-NOT:   cleanuppad
375*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch:
376*9880d681SAndroid Build Coastguard Worker; CHECK:   %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ], [ %x, %catch.cont ]
377*9880d681SAndroid Build Coastguard Worker; CHECK: }
378*9880d681SAndroid Build Coastguard Workerdefine void @f8() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
379*9880d681SAndroid Build Coastguard Workerentry:
380*9880d681SAndroid Build Coastguard Worker  invoke void @g()
381*9880d681SAndroid Build Coastguard Worker          to label %invoke.cont unwind label %ehcleanup
382*9880d681SAndroid Build Coastguard Worker
383*9880d681SAndroid Build Coastguard Workerinvoke.cont:                                      ; preds = %entry
384*9880d681SAndroid Build Coastguard Worker  invoke void @g()
385*9880d681SAndroid Build Coastguard Worker          to label %return unwind label %ehcleanup
386*9880d681SAndroid Build Coastguard Worker
387*9880d681SAndroid Build Coastguard Workerehcleanup:                                        ; preds = %invoke.cont, %entry
388*9880d681SAndroid Build Coastguard Worker  %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
389*9880d681SAndroid Build Coastguard Worker  %0 = cleanuppad within none []
390*9880d681SAndroid Build Coastguard Worker  cleanupret from %0 unwind label %catch.dispatch
391*9880d681SAndroid Build Coastguard Worker
392*9880d681SAndroid Build Coastguard Workercatch.dispatch:                                   ; preds = %ehcleanup, %catch.cont
393*9880d681SAndroid Build Coastguard Worker  %cs1 = catchswitch within none [label %catch] unwind to caller
394*9880d681SAndroid Build Coastguard Worker
395*9880d681SAndroid Build Coastguard Workercatch:                                            ; preds = %catch.dispatch
396*9880d681SAndroid Build Coastguard Worker  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
397*9880d681SAndroid Build Coastguard Worker  call void @use_x(i32 %x)
398*9880d681SAndroid Build Coastguard Worker  catchret from %1 to label %catch.cont
399*9880d681SAndroid Build Coastguard Worker
400*9880d681SAndroid Build Coastguard Workercatch.cont:                                       ; preds = %catch
401*9880d681SAndroid Build Coastguard Worker  invoke void @g()
402*9880d681SAndroid Build Coastguard Worker          to label %return unwind label %catch.dispatch
403*9880d681SAndroid Build Coastguard Worker
404*9880d681SAndroid Build Coastguard Workerreturn:                                           ; preds = %invoke.cont, %catch.cont
405*9880d681SAndroid Build Coastguard Worker  ret void
406*9880d681SAndroid Build Coastguard Worker}
407*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i32 @f9()
408*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
409*9880d681SAndroid Build Coastguard Worker; CHECK:   invoke void @"\01??1S2@@QEAA@XZ"(
410*9880d681SAndroid Build Coastguard Worker; CHECK-NOT:   cleanuppad
411*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch:
412*9880d681SAndroid Build Coastguard Worker; CHECK: }
413*9880d681SAndroid Build Coastguard Workerdefine i32 @f9() personality i32 (...)* @__CxxFrameHandler3 {
414*9880d681SAndroid Build Coastguard Workerentry:
415*9880d681SAndroid Build Coastguard Worker  %s = alloca i8, align 1
416*9880d681SAndroid Build Coastguard Worker  call void @llvm.lifetime.start(i64 1, i8* nonnull %s)
417*9880d681SAndroid Build Coastguard Worker  %bc = bitcast i8* %s to %struct.S2*
418*9880d681SAndroid Build Coastguard Worker  invoke void @"\01??1S2@@QEAA@XZ"(%struct.S2* %bc)
419*9880d681SAndroid Build Coastguard Worker          to label %try.cont unwind label %ehcleanup
420*9880d681SAndroid Build Coastguard Worker
421*9880d681SAndroid Build Coastguard Workerehcleanup:
422*9880d681SAndroid Build Coastguard Worker  %cleanup.pad = cleanuppad within none []
423*9880d681SAndroid Build Coastguard Worker  call void @llvm.lifetime.end(i64 1, i8* nonnull %s)
424*9880d681SAndroid Build Coastguard Worker  cleanupret from %cleanup.pad unwind label %catch.dispatch
425*9880d681SAndroid Build Coastguard Worker
426*9880d681SAndroid Build Coastguard Workercatch.dispatch:
427*9880d681SAndroid Build Coastguard Worker  %catch.switch = catchswitch within none [label %catch] unwind to caller
428*9880d681SAndroid Build Coastguard Worker
429*9880d681SAndroid Build Coastguard Workercatch:
430*9880d681SAndroid Build Coastguard Worker  %catch.pad = catchpad within %catch.switch [i8* null, i32 0, i8* null]
431*9880d681SAndroid Build Coastguard Worker  catchret from %catch.pad to label %try.cont
432*9880d681SAndroid Build Coastguard Worker
433*9880d681SAndroid Build Coastguard Workertry.cont:
434*9880d681SAndroid Build Coastguard Worker  ret i32 0
435*9880d681SAndroid Build Coastguard Worker}
436*9880d681SAndroid Build Coastguard Worker
437*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @f10(
438*9880d681SAndroid Build Coastguard Workerdefine void @f10(i32 %V) personality i32 (...)* @__CxxFrameHandler3 {
439*9880d681SAndroid Build Coastguard Workerentry:
440*9880d681SAndroid Build Coastguard Worker  invoke void @g()
441*9880d681SAndroid Build Coastguard Worker          to label %unreachable unwind label %cleanup
442*9880d681SAndroid Build Coastguard Worker; CHECK:       call void @g()
443*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  unreachable
444*9880d681SAndroid Build Coastguard Worker
445*9880d681SAndroid Build Coastguard Workerunreachable:
446*9880d681SAndroid Build Coastguard Worker  unreachable
447*9880d681SAndroid Build Coastguard Worker
448*9880d681SAndroid Build Coastguard Workercleanup:
449*9880d681SAndroid Build Coastguard Worker  %cp = cleanuppad within none []
450*9880d681SAndroid Build Coastguard Worker  switch i32 %V, label %cleanupret1 [
451*9880d681SAndroid Build Coastguard Worker    i32 0, label %cleanupret2
452*9880d681SAndroid Build Coastguard Worker  ]
453*9880d681SAndroid Build Coastguard Worker
454*9880d681SAndroid Build Coastguard Workercleanupret1:
455*9880d681SAndroid Build Coastguard Worker  cleanupret from %cp unwind to caller
456*9880d681SAndroid Build Coastguard Worker
457*9880d681SAndroid Build Coastguard Workercleanupret2:
458*9880d681SAndroid Build Coastguard Worker  cleanupret from %cp unwind to caller
459*9880d681SAndroid Build Coastguard Worker}
460*9880d681SAndroid Build Coastguard Worker
461*9880d681SAndroid Build Coastguard Worker%struct.S = type { i8 }
462*9880d681SAndroid Build Coastguard Worker%struct.S2 = type { i8 }
463*9880d681SAndroid Build Coastguard Workerdeclare void @"\01??1S2@@QEAA@XZ"(%struct.S2*)
464*9880d681SAndroid Build Coastguard Workerdeclare void @g()
465*9880d681SAndroid Build Coastguard Workerdeclare void @use_x(i32 %x)
466*9880d681SAndroid Build Coastguard Worker
467*9880d681SAndroid Build Coastguard Workerdeclare i32 @__CxxFrameHandler3(...)
468*9880d681SAndroid Build Coastguard Worker
469*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.lifetime.start(i64, i8* nocapture)
470*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.lifetime.end(i64, i8* nocapture)
471