1ed71ef8375e7f37ed6116dd5b75411f3b179e29
[oota-llvm.git] / test / CodeGen / WinEH / wineh-cloning.ll
1 ; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare  < %s | FileCheck %s
2
3 declare i32 @__CxxFrameHandler3(...)
4
5 declare void @f()
6 declare i32 @g()
7 declare void @h(i32)
8 declare i1 @b()
9
10
11 define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
12 entry:
13   ; %x def colors: {entry} subset of use colors; must spill
14   %x = call i32 @g()
15   invoke void @f()
16     to label %noreturn unwind label %catch
17 catch:
18   catchpad []
19     to label %noreturn unwind label %endcatch
20 noreturn:
21   ; %x use colors: {entry, cleanup}
22   call void @h(i32 %x)
23   unreachable
24 endcatch:
25   catchendpad unwind to caller
26 }
27 ; Need two copies of the call to @h, one under entry and one under catch.
28 ; Currently we generate a load for each, though we shouldn't need one
29 ; for the use in entry's copy.
30 ; CHECK-LABEL: define void @test1(
31 ; CHECK: entry:
32 ; CHECK:   store i32 %x, i32* [[Slot:%[^ ]+]]
33 ; CHECK:   invoke void @f()
34 ; CHECK:     to label %[[EntryCopy:[^ ]+]] unwind label %catch
35 ; CHECK: catch:
36 ; CHECK:   catchpad []
37 ; CHECK-NEXT: to label %[[CatchCopy:[^ ]+]] unwind
38 ; CHECK: [[CatchCopy]]:
39 ; CHECK:   [[LoadX2:%[^ ]+]] = load i32, i32* [[Slot]]
40 ; CHECK:   call void @h(i32 [[LoadX2]]
41 ; CHECK: [[EntryCopy]]:
42 ; CHECK:   [[LoadX1:%[^ ]+]] = load i32, i32* [[Slot]]
43 ; CHECK:   call void @h(i32 [[LoadX1]]
44
45
46 define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
47 entry:
48   invoke void @f()
49     to label %exit unwind label %cleanup
50 cleanup:
51   cleanuppad []
52   br label %exit
53 exit:
54   call void @f()
55   ret void
56 }
57 ; Need two copies of %exit's call to @f -- the subsequent ret is only
58 ; valid when coming from %entry, but on the path from %cleanup, this
59 ; might be a valid call to @f which might dynamically not return.
60 ; CHECK-LABEL: define void @test2(
61 ; CHECK: entry:
62 ; CHECK:   invoke void @f()
63 ; CHECK:     to label %[[exit:[^ ]+]] unwind label %cleanup
64 ; CHECK: cleanup:
65 ; CHECK:   cleanuppad []
66 ; CHECK:   call void @f()
67 ; CHECK-NEXT: unreachable
68 ; CHECK: [[exit]]:
69 ; CHECK:   call void @f()
70 ; CHECK-NEXT: ret void
71
72
73 define void @test3() personality i32 (...)* @__CxxFrameHandler3 {
74 entry:
75   invoke void @f()
76     to label %invoke.cont unwind label %catch
77 invoke.cont:
78   invoke void @f()
79     to label %exit unwind label %cleanup
80 catch:
81   catchpad [] to label %shared unwind label %endcatch
82 endcatch:
83   catchendpad unwind to caller
84 cleanup:
85   cleanuppad []
86   br label %shared
87 shared:
88   call void @f()
89   br label %exit
90 exit:
91   ret void
92 }
93 ; Need two copies of %shared's call to @f (similar to @test2 but
94 ; the two regions here are siblings, not parent-child).
95 ; CHECK-LABEL: define void @test3(
96 ; CHECK:   invoke void @f()
97 ; CHECK:   invoke void @f()
98 ; CHECK:     to label %[[exit:[^ ]+]] unwind
99 ; CHECK: catch:
100 ; CHECK:   catchpad []
101 ; CHECK-NEXT: to label %[[shared:[^ ]+]] unwind
102 ; CHECK: cleanup:
103 ; CHECK:   cleanuppad []
104 ; CHECK:   call void @f()
105 ; CHECK-NEXT: unreachable
106 ; CHECK: [[shared]]:
107 ; CHECK:   call void @f()
108 ; CHECK-NEXT: unreachable
109 ; CHECK: [[exit]]:
110 ; CHECK:   ret void
111
112
113 define void @test4() personality i32 (...)* @__CxxFrameHandler3 {
114 entry:
115   invoke void @f()
116     to label %shared unwind label %catch
117 catch:
118   catchpad []
119     to label %shared unwind label %endcatch
120 endcatch:
121   catchendpad unwind to caller
122 shared:
123   %x = call i32 @g()
124   %i = call i32 @g()
125   %zero.trip = icmp eq i32 %i, 0
126   br i1 %zero.trip, label %exit, label %loop
127 loop:
128   %i.loop = phi i32 [ %i, %shared ], [ %i.dec, %loop.tail ]
129   %b = call i1 @b()
130   br i1 %b, label %left, label %right
131 left:
132   %y = call i32 @g()
133   br label %loop.tail
134 right:
135   call void @h(i32 %x)
136   br label %loop.tail
137 loop.tail:
138   %i.dec = sub i32 %i.loop, 1
139   %done = icmp eq i32 %i.dec, 0
140   br i1 %done, label %exit, label %loop
141 exit:
142   call void @h(i32 %x)
143   unreachable
144 }
145 ; Make sure we can clone regions that have internal control
146 ; flow and SSA values.  Here we need two copies of everything
147 ; from %shared to %exit.
148 ; CHECK-LABEL: define void @test4(
149 ; CHECK:  entry:
150 ; CHECK:    to label %[[shared_E:[^ ]+]] unwind label %catch
151 ; CHECK:  catch:
152 ; CHECK:    to label %[[shared_C:[^ ]+]] unwind label %endcatch
153 ; CHECK:  [[shared_C]]:
154 ; CHECK:    [[x_C:%[^ ]+]] = call i32 @g()
155 ; CHECK:    [[i_C:%[^ ]+]] = call i32 @g()
156 ; CHECK:    [[zt_C:%[^ ]+]] = icmp eq i32 [[i_C]], 0
157 ; CHECK:    br i1 [[zt_C]], label %[[exit_C:[^ ]+]], label %[[loop_C:[^ ]+]]
158 ; CHECK:  [[shared_E]]:
159 ; CHECK:    [[x_E:%[^ ]+]] = call i32 @g()
160 ; CHECK:    [[i_E:%[^ ]+]] = call i32 @g()
161 ; CHECK:    [[zt_E:%[^ ]+]] = icmp eq i32 [[i_E]], 0
162 ; CHECK:    br i1 [[zt_E]], label %[[exit_E:[^ ]+]], label %[[loop_E:[^ ]+]]
163 ; CHECK:  [[loop_C]]:
164 ; CHECK:    [[iloop_C:%[^ ]+]] = phi i32 [ [[i_C]], %[[shared_C]] ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ]
165 ; CHECK:    [[b_C:%[^ ]+]] = call i1 @b()
166 ; CHECK:    br i1 [[b_C]], label %[[left_C:[^ ]+]], label %[[right_C:[^ ]+]]
167 ; CHECK:  [[loop_E]]:
168 ; CHECK:    [[iloop_E:%[^ ]+]] = phi i32 [ [[i_E]], %[[shared_E]] ], [ [[idec_E:%[^ ]+]], %[[looptail_E:[^ ]+]] ]
169 ; CHECK:    [[b_E:%[^ ]+]] = call i1 @b()
170 ; CHECK:    br i1 [[b_E]], label %[[left_E:[^ ]+]], label %[[right_E:[^ ]+]]
171 ; CHECK:  [[left_C]]:
172 ; CHECK:    [[y_C:%[^ ]+]] = call i32 @g()
173 ; CHECK:    br label %[[looptail_C]]
174 ; CHECK:  [[left_E]]:
175 ; CHECK:    [[y_E:%[^ ]+]] = call i32 @g()
176 ; CHECK:    br label %[[looptail_E]]
177 ; CHECK:  [[right_C]]:
178 ; CHECK:    call void @h(i32 [[x_C]])
179 ; CHECK:    br label %[[looptail_C]]
180 ; CHECK:  [[right_E]]:
181 ; CHECK:    call void @h(i32 [[x_E]])
182 ; CHECK:    br label %[[looptail_E]]
183 ; CHECK:  [[looptail_C]]:
184 ; CHECK:    [[idec_C]] = sub i32 [[iloop_C]], 1
185 ; CHECK:    [[done_C:%[^ ]+]] = icmp eq i32 [[idec_C]], 0
186 ; CHECK:    br i1 [[done_C]], label %[[exit_C]], label %[[loop_C]]
187 ; CHECK:  [[looptail_E]]:
188 ; CHECK:    [[idec_E]] = sub i32 [[iloop_E]], 1
189 ; CHECK:    [[done_E:%[^ ]+]] = icmp eq i32 [[idec_E]], 0
190 ; CHECK:    br i1 [[done_E]], label %[[exit_E]], label %[[loop_E]]
191 ; CHECK:  [[exit_C]]:
192 ; CHECK:    call void @h(i32 [[x_C]])
193 ; CHECK:    unreachable
194 ; CHECK:  [[exit_E]]:
195 ; CHECK:    call void @h(i32 [[x_E]])
196 ; CHECK:    unreachable
197
198
199 define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
200 entry:
201   invoke void @f()
202     to label %exit unwind label %outer
203 outer:
204   %o = cleanuppad []
205   %x = call i32 @g()
206   invoke void @f()
207     to label %outer.ret unwind label %inner
208 inner:
209   %i = catchpad []
210     to label %inner.catch unwind label %inner.endcatch
211 inner.catch:
212   catchret %i to label %outer.post-inner
213 inner.endcatch:
214   catchendpad unwind to caller
215 outer.post-inner:
216   call void @h(i32 %x)
217   br label %outer.ret
218 outer.ret:
219   cleanupret %o unwind to caller
220 exit:
221   ret void
222 }
223 ; Simple nested case (catch-inside-cleanup).  Nothing needs
224 ; to be cloned.  The def and use of %x are both in %outer
225 ; and so don't need to be spilled.
226 ; CHECK-LABEL: define void @test5(
227 ; CHECK:      outer:
228 ; CHECK:        %x = call i32 @g()
229 ; CHECK-NEXT:   invoke void @f()
230 ; CHECK-NEXT:     to label %outer.ret unwind label %inner
231 ; CHECK:      inner:
232 ; CHECK:          to label %inner.catch unwind label %inner.endcatch
233 ; CHECK:      inner.catch:
234 ; CHECK-NEXT:   catchret %i to label %outer.post-inner
235 ; CHECK:      outer.post-inner:
236 ; CHECK-NEXT:   call void @h(i32 %x)
237 ; CHECK-NEXT:   br label %outer.ret
238
239
240 define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
241 entry:
242   invoke void @f()
243     to label %invoke.cont unwind label %left
244 invoke.cont:
245   invoke void @f()
246     to label %exit unwind label %right
247 left:
248   cleanuppad []
249   br label %shared
250 right:
251   catchpad []
252     to label %right.catch unwind label %right.end
253 right.catch:
254   br label %shared
255 right.end:
256   catchendpad unwind to caller
257 shared:
258   %x = call i32 @g()
259   invoke void @f()
260     to label %shared.cont unwind label %inner
261 shared.cont:
262   unreachable
263 inner:
264   %i = cleanuppad []
265   call void @h(i32 %x)
266   cleanupret %i unwind label %right.end
267 exit:
268   ret void
269 }
270 ; %inner is a cleanup which appears both as a child of
271 ; %left and as a child of %right.  Since statically we
272 ; need each funclet to have a single parent, we need to
273 ; clone the entire %inner funclet so we can have one
274 ; copy under each parent.  The cleanupret in %inner
275 ; unwinds to the catchendpad for %right, so the copy
276 ; of %inner under %right should include it; the copy
277 ; of %inner under %left should instead have an
278 ; `unreachable` inserted there, but the copy under
279 ; %left still needs to be created because it's possible
280 ; the dynamic path enters %left, then enters %inner,
281 ; then calls @h, and that the call to @h doesn't return.
282 ; CHECK-LABEL: define void @test6(
283 ; TODO: CHECKs
284
285
286 define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
287 entry:
288   invoke void @f()
289     to label %invoke.cont unwind label %left
290 invoke.cont:
291   invoke void @f()
292     to label %unreachable unwind label %right
293 left:
294   cleanuppad []
295   invoke void @f() to label %unreachable unwind label %inner
296 right:
297   catchpad []
298     to label %right.catch unwind label %right.end
299 right.catch:
300   invoke void @f() to label %unreachable unwind label %inner
301 right.end:
302   catchendpad unwind to caller
303 inner:
304   %i = cleanuppad []
305   %x = call i32 @g()
306   call void @h(i32 %x)
307   cleanupret %i unwind label %right.end
308 unreachable:
309   unreachable
310 }
311 ; Another case of a two-parent child (like @test6), this time
312 ; with the join at the entry itself instead of following a
313 ; non-pad join.
314 ; CHECK-LABEL: define void @test7(
315 ; TODO: CHECKs
316
317
318 define void @test8() personality i32 (...)* @__CxxFrameHandler3 {
319 entry:
320   invoke void @f()
321     to label %invoke.cont unwind label %left
322 invoke.cont:
323   invoke void @f()
324     to label %unreachable unwind label %right
325 left:
326   cleanuppad []
327   br label %shared
328 right:
329   catchpad []
330     to label %right.catch unwind label %right.end
331 right.catch:
332   br label %shared
333 right.end:
334   catchendpad unwind to caller
335 shared:
336   invoke void @f()
337     to label %unreachable unwind label %inner
338 inner:
339   cleanuppad []
340   invoke void @f()
341     to label %unreachable unwind label %inner.child
342 inner.child:
343   cleanuppad []
344   %x = call i32 @g()
345   call void @h(i32 %x)
346   unreachable
347 unreachable:
348   unreachable
349 }
350 ; %inner is a two-parent child which itself has a child; need
351 ; to make two copies of both the %inner and %inner.child.
352 ; CHECK-LABEL: define void @test8(
353 ; TODO: CHECKs
354
355
356 define void @test9() personality i32 (...)* @__CxxFrameHandler3 {
357 entry:
358   invoke void @f()
359     to label %invoke.cont unwind label %left
360 invoke.cont:
361   invoke void @f()
362     to label %unreachable unwind label %right
363 left:
364   cleanuppad []
365   call void @h(i32 1)
366   invoke void @f()
367     to label %unreachable unwind label %right
368 right:
369   cleanuppad []
370   call void @h(i32 2)
371   invoke void @f()
372     to label %unreachable unwind label %left
373 unreachable:
374   unreachable
375 }
376 ; This is an irreducible loop with two funclets that enter each other;
377 ; need to make two copies of each funclet (one a child of root, the
378 ; other a child of the opposite funclet), but also make sure not to
379 ; clone self-descendants (if we tried to do that we'd need to make an
380 ; infinite number of them).  Presumably if optimizations ever generated
381 ; such a thing it would mean that one of the two cleanups was originally
382 ; the parent of the other, but that we'd somehow lost track in the CFG
383 ; of which was which along the way; generating each possibility lets
384 ; whichever case was correct execute correctly.
385 ; CHECK-LABEL: define void @test9(
386 ; TODO: CHECKs
387
388 define void @test10() personality i32 (...)* @__CxxFrameHandler3 {
389 entry:
390   invoke void @f()
391     to label %unreachable unwind label %inner
392 inner:
393   %cleanup = cleanuppad []
394   ; make sure we don't overlook this cleanupret and try to process
395   ; successor %outer as a child of inner.
396   cleanupret %cleanup unwind label %outer
397 outer:
398   %catch = catchpad [] to label %catch.body unwind label %endpad
399 catch.body:
400   catchret %catch to label %exit
401 endpad:
402   catchendpad unwind to caller
403 exit:
404   ret void
405 unreachable:
406   unreachable
407 }
408 ; CHECK-LABEL: define void @test10(
409 ; CHECK-NEXT: entry:
410 ; CHECK-NEXT:   invoke
411 ; CHECK-NEXT:     to label %unreachable unwind label %inner
412 ; CHECK:      inner:
413 ; CHECK-NEXT:   %cleanup = cleanuppad
414 ; CHECK-NEXT:   cleanupret %cleanup unwind label %outer
415 ; CHECK:      outer:
416 ; CHECK-NEXT:   %catch = catchpad []
417 ; CHECK-NEXT:         to label %catch.body unwind label %endpad
418 ; CHECK:      catch.body:
419 ; CHECK-NEXT:   catchret %catch to label %exit
420 ; CHECK:      endpad:
421 ; CHECK-NEXT:   catchendpad unwind to caller
422 ; CHECK:      exit:
423 ; CHECK-NEXT:   ret void
424
425 define void @test11() personality i32 (...)* @__CxxFrameHandler3 {
426 entry:
427   invoke void @f()
428     to label %exit unwind label %cleanup.outer
429 cleanup.outer:
430   %outer = cleanuppad []
431   invoke void @f()
432     to label %outer.cont unwind label %cleanup.inner
433 outer.cont:
434   br label %merge
435 cleanup.inner:
436   %inner = cleanuppad []
437   br label %merge
438 merge:
439   invoke void @f()
440     to label %unreachable unwind label %merge.end
441 unreachable:
442   unreachable
443 merge.end:
444   cleanupendpad %outer unwind to caller
445 exit:
446   ret void
447 }
448 ; merge.end will get cloned for outer and inner, but is implausible
449 ; from inner, so the invoke @f() in inner's copy of merge should be
450 ; rewritten to call @f()
451 ; CHECK-LABEL: define void @test11()
452 ; CHECK:      %inner = cleanuppad []
453 ; CHECK-NEXT: call void @f()
454 ; CHECK-NEXT: unreachable