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