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