bd239133ea878388c8f64858fd06b70089298cf4
[oota-llvm.git] / test / CodeGen / WinEH / wineh-demotion.ll
1 ; RUN: opt -mtriple=x86_64-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   %cs1 = catchswitch within none [label %catch] unwind to caller
40
41 catch:
42   %cp = catchpad within %cs1 []
43   ; CHECK: catch:
44   ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
45   ; CHECK-NEXT: call void @h(i32 [[Reload]])
46   call void @h(i32 %phi)
47   catchret from %cp to label %exit
48
49 exit:
50   ret void
51 }
52
53 ; CHECK-LABEL: @test2(
54 define void @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
55 entry:
56   br i1 %B, label %left, label %right
57 left:
58   ; Need two stores here because %x and %y interfere so they need 2 slots
59   ; CHECK: left:
60   ; CHECK:   store i32 1, i32* [[Slot1:%[^ ]+]]
61   ; CHECK:   store i32 1, i32* [[Slot2:%[^ ]+]]
62   ; CHECK-NEXT: invoke void @f
63   invoke void @f()
64           to label %exit unwind label %merge.inner
65 right:
66   ; Need two stores here because %x and %y interfere so they need 2 slots
67   ; CHECK: right:
68   ; CHECK-DAG:   store i32 2, i32* [[Slot1]]
69   ; CHECK-DAG:   store i32 2, i32* [[Slot2]]
70   ; CHECK: invoke void @f
71   invoke void @f()
72           to label %exit unwind label %merge.inner
73 merge.inner:
74   ; CHECK: merge.inner:
75   ; CHECK-NOT: = phi
76   ; CHECK: catchswitch within none
77   %x = phi i32 [ 1, %left ], [ 2, %right ]
78   %cs1 = catchswitch within none [label %catch.inner] unwind label %merge.outer
79
80 catch.inner:
81   %cpinner = catchpad within %cs1 []
82   ; Need just one store here because only %y is affected
83   ; CHECK: catch.inner:
84   %z = call i32 @g()
85   ; CHECK:   store i32 %z
86   ; CHECK-NEXT: invoke void @f
87   invoke void @f()
88           to label %catchret.inner unwind label %merge.outer
89
90 catchret.inner:
91   catchret from %cpinner to label %exit
92
93 merge.outer:
94   %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ]
95   ; CHECK: merge.outer:
96   ; CHECK-NOT: = phi
97   ; CHECK: catchswitch within none
98   %cs2 = catchswitch within none [label %catch.outer] unwind to caller
99
100 catch.outer:
101   %cpouter = catchpad within %cs2 []
102   ; CHECK: catch.outer:
103   ; CHECK: [[CatchPad:%[^ ]+]] = catchpad within %cs2 []
104   ; Need to load x and y from two different slots since they're both live
105   ; and can have different values (if we came from catch.inner)
106   ; CHECK-DAG: load i32, i32* [[Slot1]]
107   ; CHECK-DAG: load i32, i32* [[Slot2]]
108   ; CHECK: catchret from [[CatchPad]] to label
109   call void @h(i32 %x)
110   call void @h(i32 %y)
111   catchret from %cpouter to label %exit
112
113 exit:
114   ret void
115 }
116
117 ; test4: don't need stores for %phi.inner, as its only use is to feed %phi.outer
118 ;        %phi.outer needs stores in %left, %right, and %join
119 ; CHECK-LABEL: @test4(
120 define void @test4(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
121 entry:
122   ; CHECK:      entry:
123   ; CHECK:        [[Slot:%[^ ]+]] = alloca
124   ; CHECK-NEXT:   br
125   br i1 %B, label %left, label %right
126 left:
127   ; CHECK: left:
128   ; CHECK-NOT: store
129   ; CHECK: store i32 %l, i32* [[Slot]]
130   ; CHECK-NEXT: invoke void @f
131   %l = call i32 @g()
132   invoke void @f()
133           to label %join unwind label %catchpad.inner
134 right:
135   ; CHECK: right:
136   ; CHECK-NOT: store
137   ; CHECK: store i32 %r, i32* [[Slot]]
138   ; CHECK-NEXT: invoke void @f
139   %r = call i32 @g()
140   invoke void @f()
141           to label %join unwind label %catchpad.inner
142 catchpad.inner:
143    ; CHECK: catchpad.inner:
144    ; CHECK-NEXT: catchswitch within none
145    %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
146    %cs1 = catchswitch within none [label %catch.inner] unwind label %catchpad.outer
147 catch.inner:
148    %cp1 = catchpad within %cs1 []
149    catchret from %cp1 to label %join
150 join:
151   ; CHECK: join:
152   ; CHECK-NOT: store
153   ; CHECK: store i32 %j, i32* [[Slot]]
154   ; CHECK-NEXT: invoke void @f
155    %j = call i32 @g()
156    invoke void @f()
157            to label %exit unwind label %catchpad.outer
158
159 catchpad.outer:
160    ; CHECK: catchpad.outer:
161    ; CHECK-NEXT: catchswitch within none
162    %phi.outer = phi i32 [ %phi.inner, %catchpad.inner ], [ %j, %join ]
163    %cs2 = catchswitch within none [label %catch.outer] unwind to caller
164 catch.outer:
165    ; CHECK: catch.outer:
166    ; CHECK:   [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
167    ; CHECK:   call void @h(i32 [[Reload]])
168    %cp2 = catchpad within %cs2 []
169    call void @h(i32 %phi.outer)
170    catchret from %cp2 to label %exit
171 exit:
172    ret void
173 }
174
175 ; CHECK-LABEL: @test5(
176 define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
177 entry:
178   ; need store for %phi.cleanup
179   ; CHECK:      entry:
180   ; CHECK:        store i32 1, i32* [[CleanupSlot:%[^ ]+]]
181   ; CHECK-NEXT:   invoke void @f
182   invoke void @f()
183           to label %invoke.cont unwind label %cleanup
184
185 invoke.cont:
186   ; need store for %phi.cleanup
187   ; CHECK:      invoke.cont:
188   ; CHECK-NEXT:   store i32 2, i32* [[CleanupSlot]]
189   ; CHECK-NEXT:   invoke void @f
190   invoke void @f()
191           to label %invoke.cont2 unwind label %cleanup
192
193 cleanup:
194   ; cleanup phi can be loaded at cleanup entry
195   ; CHECK: cleanup:
196   ; CHECK-NEXT: cleanuppad within none []
197   ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
198   %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
199   %cp = cleanuppad within none []
200   %b = call i1 @i()
201   br i1 %b, label %left, label %right
202
203 left:
204   ; CHECK: left:
205   ; CHECK:   call void @h(i32 [[CleanupReload]]
206   call void @h(i32 %phi.cleanup)
207   br label %merge
208
209 right:
210   ; CHECK: right:
211   ; CHECK:   call void @h(i32 [[CleanupReload]]
212   call void @h(i32 %phi.cleanup)
213   br label %merge
214
215 merge:
216   ; need store for %phi.catch
217   ; CHECK:      merge:
218   ; CHECK-NEXT:   store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
219   ; CHECK-NEXT:   cleanupret
220   cleanupret from %cp unwind label %catchswitch
221
222 invoke.cont2:
223   ; need store for %phi.catch
224   ; CHECK:      invoke.cont2:
225   ; CHECK-NEXT:   store i32 3, i32* [[CatchSlot]]
226   ; CHECK-NEXT:   invoke void @f
227   invoke void @f()
228           to label %exit unwind label %catchswitch
229
230 catchswitch:
231   ; CHECK: catchswitch:
232   ; CHECK-NEXT: catchswitch within none
233   %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
234   %cs1 = catchswitch within none [label %catch] unwind to caller
235
236 catch:
237   ; CHECK: catch:
238   ; CHECK:   catchpad within %cs1
239   ; CHECK:   [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
240   ; CHECK:   call void @h(i32 [[CatchReload]]
241   %cp2 = catchpad within %cs1 []
242   call void @h(i32 %phi.catch)
243   catchret from %cp2 to label %exit
244
245 exit:
246   ret void
247 }
248
249 ; We used to demote %x, but we don't need to anymore.
250 ; CHECK-LABEL: @test6(
251 define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
252 entry:
253   ; CHECK: entry:
254   ; CHECK: %x = invoke i32 @g()
255   ; CHECK-NEXT: to label %loop unwind label %to_caller
256   %x = invoke i32 @g()
257           to label %loop unwind label %to_caller
258 to_caller:
259   %cp1 = cleanuppad within none []
260   cleanupret from %cp1 unwind to caller
261 loop:
262   invoke void @f()
263           to label %loop unwind label %cleanup
264 cleanup:
265   ; CHECK: cleanup:
266   ; CHECK:   call void @h(i32 %x)
267   %cp2 = cleanuppad within none []
268   call void @h(i32 %x)
269   cleanupret from %cp2 unwind to caller
270 }
271
272 ; CHECK-LABEL: @test7(
273 define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
274 entry:
275   ; %x is an EH pad phi, so gets stored in pred here
276   ; CHECK: entry:
277   ; CHECK:   store i32 1, i32* [[SlotX:%[^ ]+]]
278   ; CHECK:   invoke void @f()
279   invoke void @f()
280      to label %invoke.cont unwind label %catchpad
281 invoke.cont:
282   ; %x is an EH pad phi, so gets stored in pred here
283   ; CHECK: invoke.cont:
284   ; CHECK:   store i32 2, i32* [[SlotX]]
285   ; CHECK:   invoke void @f()
286   invoke void @f()
287     to label %exit unwind label %catchpad
288 catchpad:
289   ; %x phi should be eliminated
290   ; CHECK: catchpad:
291   ; CHECK-NEXT: catchswitch within none
292   %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
293   %cs1 = catchswitch within none [label %catch] unwind to caller
294 catch:
295   ; CHECK: catch:
296   ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []
297   %cp = catchpad within %cs1 []
298   %b = call i1 @i()
299   br i1 %b, label %left, label %right
300 left:
301   ; Edge from %left to %join needs to be split so that
302   ; the load of %x can be inserted *after* the catchret
303   ; CHECK: left:
304   ; CHECK-NEXT: catchret from %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
305   catchret from %cp to label %join
306   ; CHECK: [[SplitLeft]]:
307   ; CHECK:   [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
308   ; CHECK:   br label %join
309 right:
310   ; Edge from %right to %join needs to be split so that
311   ; the load of %y can be inserted *after* the catchret
312   ; CHECK: right:
313   ; CHECK:   %y = call i32 @g()
314   ; CHECK:   catchret from %[[CatchPad]] to label %join
315   %y = call i32 @g()
316   catchret from %cp to label %join
317 join:
318   ; CHECK: join:
319   ; CHECK:   %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ]
320   %phi = phi i32 [ %x, %left ], [ %y, %right ]
321   call void @h(i32 %phi)
322   br label %exit
323 exit:
324   ret void
325 }
326
327 ; CHECK-LABEL: @test8(
328 define void @test8() personality i32 (...)* @__CxxFrameHandler3 { entry:
329   invoke void @f()
330           to label %done unwind label %cleanup1
331   invoke void @f()
332           to label %done unwind label %cleanup2
333
334 done:
335   ret void
336
337 cleanup1:
338   ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []
339   ; CHECK-NEXT: call void @f()
340   ; CHECK-NEXT: cleanupret from [[CleanupPad1]]
341   %cp0 = cleanuppad within none []
342   br label %cleanupexit
343
344 cleanup2:
345   ; CHECK: cleanuppad within none []
346   ; CHECK-NEXT: call void @f()
347   ; CHECK-NEXT: unreachable
348   %cp1 = cleanuppad within none []
349   br label %cleanupexit
350
351 cleanupexit:
352   call void @f()
353   cleanupret from %cp0 unwind label %cleanup2
354 }