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