[WinEH] Require token linkage in EH pad/ret signatures
[oota-llvm.git] / test / CodeGen / WinEH / wineh-demotion.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
7 declare i32 @g()
8
9 declare void @h(i32)
10
11 declare i1 @i()
12
13 ; CHECK-LABEL: @test1(
14 define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
15 entry:
16   ; Spill slot should be inserted here
17   ; CHECK: [[Slot:%[^ ]+]] = alloca
18   ; Can't store for %phi at these defs because the lifetimes overlap
19   ; CHECK-NOT: store
20   %x = call i32 @g()
21   %y = call i32 @g()
22   br i1 %B, label %left, label %right
23 left:
24   ; CHECK: left:
25   ; CHECK-NEXT: store i32 %x, i32* [[Slot]]
26   ; CHECK-NEXT: invoke void @f
27   invoke void @f()
28           to label %exit unwind label %merge
29 right:
30   ; CHECK: right:
31   ; CHECK-NEXT: store i32 %y, i32* [[Slot]]
32   ; CHECK-NEXT: invoke void @f
33   invoke void @f()
34           to label %exit unwind label %merge
35 merge:
36   ; CHECK: merge:
37   ; CHECK-NOT: = phi
38   %phi = phi i32 [ %x, %left ], [ %y, %right ]
39   %cp = catchpad [] to label %catch unwind label %catchend
40
41 catch:
42   ; CHECK: catch:
43   ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
44   ; CHECK-NEXT: call void @h(i32 [[Reload]])
45   call void @h(i32 %phi)
46   catchret %cp to label %exit
47
48 catchend:
49   catchendpad unwind to caller
50
51 exit:
52   ret void
53 }
54
55 ; CHECK-LABEL: @test2(
56 define void @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
57 entry:
58   br i1 %B, label %left, label %right
59 left:
60   ; Need two stores here because %x and %y interfere so they need 2 slots
61   ; CHECK: left:
62   ; CHECK:   store i32 1, i32* [[Slot1:%[^ ]+]]
63   ; CHECK:   store i32 1, i32* [[Slot2:%[^ ]+]]
64   ; CHECK-NEXT: invoke void @f
65   invoke void @f()
66           to label %exit unwind label %merge.inner
67 right:
68   ; Need two stores here because %x and %y interfere so they need 2 slots
69   ; CHECK: right:
70   ; CHECK-DAG:   store i32 2, i32* [[Slot1]]
71   ; CHECK-DAG:   store i32 2, i32* [[Slot2]]
72   ; CHECK: invoke void @f
73   invoke void @f()
74           to label %exit unwind label %merge.inner
75 merge.inner:
76   ; CHECK: merge.inner:
77   ; CHECK-NOT: = phi
78   ; CHECK: catchpad []
79   %x = phi i32 [ 1, %left ], [ 2, %right ]
80   %cpinner = catchpad [] to label %catch.inner unwind label %catchend.inner
81
82 catch.inner:
83   ; Need just one store here because only %y is affected
84   ; CHECK: catch.inner:
85   %z = call i32 @g()
86   ; CHECK:   store i32 %z
87   ; CHECK-NEXT: invoke void @f
88   invoke void @f()
89           to label %catchret.inner unwind label %merge.outer
90
91 catchret.inner:
92   catchret %cpinner to label %exit
93 catchend.inner:
94   catchendpad unwind label %merge.outer
95
96 merge.outer:
97   ; CHECK: merge.outer:
98   ; CHECK-NOT: = phi
99   ; CHECK: [[CatchPad:%[^ ]+]] = catchpad []
100   %y = phi i32 [ %x, %catchend.inner ], [ %z, %catch.inner ]
101   %cpouter = catchpad [] to label %catch.outer unwind label %catchend.outer
102
103 catchend.outer:
104   catchendpad unwind to caller
105
106 catch.outer:
107   ; Need to load x and y from two different slots since they're both live
108   ; and can have different values (if we came from catch.inner)
109   ; CHECK: catch.outer:
110   ; CHECK-DAG: load i32, i32* [[Slot1]]
111   ; CHECK-DAG: load i32, i32* [[Slot2]]
112   ; CHECK: catchret [[CatchPad]] to label
113   call void @h(i32 %x)
114   call void @h(i32 %y)
115   catchret %cpouter to label %exit
116
117 exit:
118   ret void
119 }
120
121 ; CHECK-LABEL: @test3(
122 define void @test3(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
123 entry:
124   ; need to spill parameter %B and def %x since they're used in a funclet
125   ; CHECK: entry:
126   ; CHECK-DAG: store i1 %B, i1* [[SlotB:%[^ ]+]]
127   ; CHECK-DAG: store i32 %x, i32* [[SlotX:%[^ ]+]]
128   ; CHECK: invoke void @f
129   %x = call i32 @g()
130   invoke void @f()
131           to label %exit unwind label %catchpad
132
133 catchpad:
134   %cp = catchpad [] to label %catch unwind label %catchend
135
136 catch:
137   ; Need to reload %B here
138   ; CHECK: catch:
139   ; CHECK: [[ReloadB:%[^ ]+]] = load i1, i1* [[SlotB]]
140   ; CHECK: br i1 [[ReloadB]]
141   br i1 %B, label %left, label %right
142 left:
143   ; Use of %x is in a phi, so need reload here in pred
144   ; CHECK: left:
145   ; CHECK: [[ReloadX:%[^ ]+]] = load i32, i32* [[SlotX]]
146   ; CHECK: br label %merge
147   br label %merge
148 right:
149   br label %merge
150 merge:
151   ; CHECK: merge:
152   ; CHECK:   %phi = phi i32 [ [[ReloadX]], %left ]
153   %phi = phi i32 [ %x, %left ], [ 42, %right ]
154   call void @h(i32 %phi)
155   catchret %cp to label %exit
156
157 catchend:
158   catchendpad unwind to caller
159
160 exit:
161   ret void
162 }
163
164 ; test4: don't need stores for %phi.inner, as its only use is to feed %phi.outer
165 ;        %phi.outer needs stores in %left, %right, and %join
166 ; CHECK-LABEL: @test4(
167 define void @test4(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
168 entry:
169   ; CHECK:      entry:
170   ; CHECK:        [[Slot:%[^ ]+]] = alloca
171   ; CHECK-NEXT:   br
172   br i1 %B, label %left, label %right
173 left:
174   ; CHECK: left:
175   ; CHECK-NOT: store
176   ; CHECK: store i32 %l, i32* [[Slot]]
177   ; CHECK-NEXT: invoke void @f
178   %l = call i32 @g()
179   invoke void @f()
180           to label %join unwind label %catchpad.inner
181 right:
182   ; CHECK: right:
183   ; CHECK-NOT: store
184   ; CHECK: store i32 %r, i32* [[Slot]]
185   ; CHECK-NEXT: invoke void @f
186   %r = call i32 @g()
187   invoke void @f()
188           to label %join unwind label %catchpad.inner
189 catchpad.inner:
190    ; CHECK: catchpad.inner:
191    ; CHECK-NEXT: catchpad []
192    %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
193    %cp1 = catchpad [] to label %catch.inner unwind label %catchend.inner
194 catch.inner:
195    catchret %cp1 to label %join
196 catchend.inner:
197    catchendpad unwind label  %catchpad.outer
198 join:
199   ; CHECK: join:
200   ; CHECK-NOT: store
201   ; CHECK: store i32 %j, i32* [[Slot]]
202   ; CHECK-NEXT: invoke void @f
203    %j = call i32 @g()
204    invoke void @f()
205            to label %exit unwind label %catchpad.outer
206 catchpad.outer:
207    ; CHECK: catchpad.outer:
208    ; CHECK-NEXT: catchpad []
209    %phi.outer = phi i32 [ %phi.inner, %catchend.inner ], [ %j, %join ]
210    %cp2 = catchpad [] to label %catch.outer unwind label %catchend.outer
211 catch.outer:
212    ; CHECK: catch.outer:
213    ; CHECK:   [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
214    ; CHECK:   call void @h(i32 [[Reload]])
215    call void @h(i32 %phi.outer)
216    catchret %cp2 to label %exit
217 catchend.outer:
218    catchendpad unwind to caller
219 exit:
220    ret void
221 }
222
223 ; CHECK-LABEL: @test5(
224 define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
225 entry:
226   ; need store for %phi.cleanup
227   ; CHECK:      entry:
228   ; CHECK:        store i32 1, i32* [[CleanupSlot:%[^ ]+]]
229   ; CHECK-NEXT:   invoke void @f
230   invoke void @f()
231           to label %invoke.cont unwind label %cleanup
232
233 invoke.cont:
234   ; need store for %phi.cleanup
235   ; CHECK:      invoke.cont:
236   ; CHECK-NEXT:   store i32 2, i32* [[CleanupSlot]]
237   ; CHECK-NEXT:   invoke void @f
238   invoke void @f()
239           to label %invoke.cont2 unwind label %cleanup
240
241 cleanup:
242   ; cleanup phi can be loaded at cleanup entry
243   ; CHECK: cleanup:
244   ; CHECK-NEXT: cleanuppad []
245   ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
246   %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
247   %cp = cleanuppad []
248   %b = call i1 @i()
249   br i1 %b, label %left, label %right
250
251 left:
252   ; CHECK: left:
253   ; CHECK:   call void @h(i32 [[CleanupReload]]
254   call void @h(i32 %phi.cleanup)
255   br label %merge
256
257 right:
258   ; CHECK: right:
259   ; CHECK:   call void @h(i32 [[CleanupReload]]
260   call void @h(i32 %phi.cleanup)
261   br label %merge
262
263 merge:
264   ; need store for %phi.catch
265   ; CHECK:      merge:
266   ; CHECK-NEXT:   store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
267   ; CHECK-NEXT:   cleanupret
268   cleanupret %cp unwind label %catchpad
269
270 invoke.cont2:
271   ; need store for %phi.catch
272   ; CHECK:      invoke.cont2:
273   ; CHECK-NEXT:   store i32 3, i32* [[CatchSlot]]
274   ; CHECK-NEXT:   invoke void @f
275   invoke void @f()
276           to label %exit unwind label %catchpad
277
278 catchpad:
279   ; CHECK: catchpad:
280   ; CHECK-NEXT: catchpad []
281   %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
282   %cp2 = catchpad [] to label %catch unwind label %catchend
283
284 catch:
285   ; CHECK: catch:
286   ; CHECK:   [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
287   ; CHECK:   call void @h(i32 [[CatchReload]]
288   call void @h(i32 %phi.catch)
289   catchret %cp2 to label %exit
290
291 catchend:
292   catchendpad unwind to caller
293
294 exit:
295   ret void
296 }
297
298 ; CHECK-LABEL: @test6(
299 define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
300 entry:
301   ; Since %x needs to be stored but the edge to loop is critical,
302   ; it needs to be split
303   ; CHECK: entry:
304   ; CHECK: invoke i32 @g
305   ; CHECK-NEXT: to label %[[SplitBlock:[^ ]+]] unwind label %to_caller
306   %x = invoke i32 @g()
307           to label %loop unwind label %to_caller
308   ; The store should be in the split block
309   ; CHECK: [[SplitBlock]]:
310   ; CHECK: store i32 %x, i32* [[SpillSlot:%[^ ]+]]
311   ; CHECK: br label %loop
312 to_caller:
313   %cp1 = cleanuppad []
314   cleanupret %cp1 unwind to caller
315 loop:
316   invoke void @f()
317           to label %loop unwind label %cleanup
318 cleanup:
319   ; CHECK: cleanup:
320   ; CHECK:   [[Load:%[^ ]+]] = load i32, i32* [[SpillSlot]]
321   ; CHECK:   call void @h(i32 [[Load]])
322   %cp2 = cleanuppad []
323   call void @h(i32 %x)
324   cleanupret %cp2 unwind to caller
325 }
326
327 ; CHECK-LABEL: @test7(
328 define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
329 entry:
330   ; %x is an EH pad phi, so gets stored in pred here
331   ; CHECK: entry:
332   ; CHECK:   store i32 1, i32* [[SlotX:%[^ ]+]]
333   ; CHECK:   invoke void @f()
334   invoke void @f()
335      to label %invoke.cont unwind label %catchpad
336 invoke.cont:
337   ; %x is an EH pad phi, so gets stored in pred here
338   ; CHECK: invoke.cont:
339   ; CHECK:   store i32 2, i32* [[SlotX]]
340   ; CHECK:   invoke void @f()
341   invoke void @f()
342     to label %exit unwind label %catchpad
343 catchpad:
344   ; %x phi should be eliminated
345   ; CHECK: catchpad:
346   ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad []
347   %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
348   %cp = catchpad [] to label %catch unwind label %catchend
349 catch:
350   %b = call i1 @i()
351   br i1 %b, label %left, label %right
352 left:
353   ; Edge from %left to %join needs to be split so that
354   ; the load of %x can be inserted *after* the catchret
355   ; CHECK: left:
356   ; CHECK-NEXT: catchret %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
357   catchret %cp to label %join
358   ; CHECK: [[SplitLeft]]:
359   ; CHECK:   [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
360   ; CHECK:   br label %join
361 right:
362   ; Edge from %right to %join needs to be split so that
363   ; the load of %y can be inserted *after* the catchret
364   ; CHECK: right:
365   ; CHECK:   store i32 %y, i32* [[SlotY:%[^ ]+]]
366   ; CHECK:   catchret %[[CatchPad]] to label %[[SplitRight:[^ ]+]]
367   %y = call i32 @g()
368   catchret %cp to label %join
369   ; CHECK: [[SplitRight]]:
370   ; CHECK:   [[LoadY:%[^ ]+]] = load i32, i32* [[SlotY]]
371   ; CHECK:   br label %join
372 catchend:
373   catchendpad unwind to caller
374 join:
375   ; CHECK: join:
376   ; CHECK:   %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ [[LoadY]], %[[SplitRight]] ]
377   %phi = phi i32 [ %x, %left ], [ %y, %right ]
378   call void @h(i32 %phi)
379   br label %exit
380 exit:
381   ret void
382 }
383
384 ; CHECK-LABEL: @test8(
385 define void @test8() personality i32 (...)* @__CxxFrameHandler3 { entry:
386   invoke void @f()
387           to label %done unwind label %cleanup1
388   invoke void @f()
389           to label %done unwind label %cleanup2
390
391 done:
392   ret void
393
394 cleanup1:
395   ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad []
396   ; CHECK-NEXT: call void @f()
397   ; CHECK-NEXT: cleanupret [[CleanupPad1]]
398   %cp0 = cleanuppad []
399   br label %cleanupexit
400
401 cleanup2:
402   ; CHECK: cleanuppad []
403   ; CHECK-NEXT: call void @f()
404   ; CHECK-NEXT: unreachable
405   %cp1 = cleanuppad []
406   br label %cleanupexit
407
408 cleanupexit:
409   call void @f()
410   cleanupret %cp0 unwind label %cleanup2
411 }