blob: 113d95015a0385fabb0162217ebccb2446ef4a1b [file] [log] [blame]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +00001; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s
2
3declare i32 @__CxxFrameHandler3(...)
4
5declare void @f()
6
7declare i32 @g()
8
9declare void @h(i32)
10
11declare i1 @i()
12
13; CHECK-LABEL: @test1(
14define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
15entry:
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
23left:
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
29right:
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
35merge:
36 ; CHECK: merge:
37 ; CHECK-NOT: = phi
38 %phi = phi i32 [ %x, %left ], [ %y, %right ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +000039 %cp = catchpad [] to label %catch unwind label %catchend
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000040
41catch:
42 ; CHECK: catch:
43 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
44 ; CHECK-NEXT: call void @h(i32 [[Reload]])
45 call void @h(i32 %phi)
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +000046 catchret %cp to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000047
48catchend:
49 catchendpad unwind to caller
50
51exit:
52 ret void
53}
54
55; CHECK-LABEL: @test2(
56define void @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
57entry:
58 br i1 %B, label %left, label %right
59left:
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
67right:
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
75merge.inner:
76 ; CHECK: merge.inner:
77 ; CHECK-NOT: = phi
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +000078 ; CHECK: catchpad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000079 %x = phi i32 [ 1, %left ], [ 2, %right ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +000080 %cpinner = catchpad [] to label %catch.inner unwind label %catchend.inner
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000081
82catch.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
91catchret.inner:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +000092 catchret %cpinner to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000093catchend.inner:
94 catchendpad unwind label %merge.outer
95
96merge.outer:
97 ; CHECK: merge.outer:
98 ; CHECK-NOT: = phi
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +000099 ; CHECK: [[CatchPad:%[^ ]+]] = catchpad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000100 %y = phi i32 [ %x, %catchend.inner ], [ %z, %catch.inner ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000101 %cpouter = catchpad [] to label %catch.outer unwind label %catchend.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000102
103catchend.outer:
104 catchendpad unwind to caller
105
106catch.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]]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000112 ; CHECK: catchret [[CatchPad]] to label
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000113 call void @h(i32 %x)
114 call void @h(i32 %y)
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000115 catchret %cpouter to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000116
117exit:
118 ret void
119}
120
121; CHECK-LABEL: @test3(
122define void @test3(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
123entry:
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
133catchpad:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000134 %cp = catchpad [] to label %catch unwind label %catchend
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000135
136catch:
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
142left:
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
148right:
149 br label %merge
150merge:
151 ; CHECK: merge:
152 ; CHECK: %phi = phi i32 [ [[ReloadX]], %left ]
153 %phi = phi i32 [ %x, %left ], [ 42, %right ]
154 call void @h(i32 %phi)
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000155 catchret %cp to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000156
157catchend:
158 catchendpad unwind to caller
159
160exit:
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(
167define void @test4(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
168entry:
169 ; CHECK: entry:
170 ; CHECK: [[Slot:%[^ ]+]] = alloca
171 ; CHECK-NEXT: br
172 br i1 %B, label %left, label %right
173left:
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
181right:
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
189catchpad.inner:
190 ; CHECK: catchpad.inner:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000191 ; CHECK-NEXT: catchpad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000192 %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000193 %cp1 = catchpad [] to label %catch.inner unwind label %catchend.inner
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000194catch.inner:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000195 catchret %cp1 to label %join
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000196catchend.inner:
197 catchendpad unwind label %catchpad.outer
198join:
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
206catchpad.outer:
207 ; CHECK: catchpad.outer:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000208 ; CHECK-NEXT: catchpad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000209 %phi.outer = phi i32 [ %phi.inner, %catchend.inner ], [ %j, %join ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000210 %cp2 = catchpad [] to label %catch.outer unwind label %catchend.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000211catch.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)
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000216 catchret %cp2 to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000217catchend.outer:
218 catchendpad unwind to caller
219exit:
220 ret void
221}
222
223; CHECK-LABEL: @test5(
224define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
225entry:
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
233invoke.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
241cleanup:
242 ; cleanup phi can be loaded at cleanup entry
243 ; CHECK: cleanup:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000244 ; CHECK-NEXT: cleanuppad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000245 ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
246 %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000247 %cp = cleanuppad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000248 %b = call i1 @i()
249 br i1 %b, label %left, label %right
250
251left:
252 ; CHECK: left:
253 ; CHECK: call void @h(i32 [[CleanupReload]]
254 call void @h(i32 %phi.cleanup)
255 br label %merge
256
257right:
258 ; CHECK: right:
259 ; CHECK: call void @h(i32 [[CleanupReload]]
260 call void @h(i32 %phi.cleanup)
261 br label %merge
262
263merge:
264 ; need store for %phi.catch
265 ; CHECK: merge:
266 ; CHECK-NEXT: store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000267 ; CHECK-NEXT: cleanupret
268 cleanupret %cp unwind label %catchpad
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000269
270invoke.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
278catchpad:
279 ; CHECK: catchpad:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000280 ; CHECK-NEXT: catchpad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000281 %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000282 %cp2 = catchpad [] to label %catch unwind label %catchend
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000283
284catch:
285 ; CHECK: catch:
286 ; CHECK: [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
287 ; CHECK: call void @h(i32 [[CatchReload]]
288 call void @h(i32 %phi.catch)
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000289 catchret %cp2 to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000290
291catchend:
292 catchendpad unwind to caller
293
294exit:
295 ret void
296}
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000297
298; CHECK-LABEL: @test6(
299define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
300entry:
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
312to_caller:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000313 %cp1 = cleanuppad []
314 cleanupret %cp1 unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000315loop:
316 invoke void @f()
317 to label %loop unwind label %cleanup
318cleanup:
319 ; CHECK: cleanup:
320 ; CHECK: [[Load:%[^ ]+]] = load i32, i32* [[SpillSlot]]
321 ; CHECK: call void @h(i32 [[Load]])
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000322 %cp2 = cleanuppad []
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000323 call void @h(i32 %x)
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000324 cleanupret %cp2 unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000325}
326
327; CHECK-LABEL: @test7(
328define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
329entry:
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
336invoke.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
343catchpad:
344 ; %x phi should be eliminated
345 ; CHECK: catchpad:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000346 ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad []
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000347 %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000348 %cp = catchpad [] to label %catch unwind label %catchend
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000349catch:
350 %b = call i1 @i()
351 br i1 %b, label %left, label %right
352left:
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:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000356 ; CHECK-NEXT: catchret %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
357 catchret %cp to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000358 ; CHECK: [[SplitLeft]]:
359 ; CHECK: [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
360 ; CHECK: br label %join
361right:
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:%[^ ]+]]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000366 ; CHECK: catchret %[[CatchPad]] to label %[[SplitRight:[^ ]+]]
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000367 %y = call i32 @g()
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000368 catchret %cp to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000369 ; CHECK: [[SplitRight]]:
370 ; CHECK: [[LoadY:%[^ ]+]] = load i32, i32* [[SlotY]]
371 ; CHECK: br label %join
372catchend:
373 catchendpad unwind to caller
374join:
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
380exit:
381 ret void
382}
David Majnemer83f4bb22015-08-17 20:56:39 +0000383
384; CHECK-LABEL: @test8(
385define 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
391done:
392 ret void
393
394cleanup1:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000395 ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad []
David Majnemer83f4bb22015-08-17 20:56:39 +0000396 ; CHECK-NEXT: call void @f()
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000397 ; CHECK-NEXT: cleanupret [[CleanupPad1]]
398 %cp0 = cleanuppad []
David Majnemer83f4bb22015-08-17 20:56:39 +0000399 br label %cleanupexit
400
401cleanup2:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000402 ; CHECK: cleanuppad []
David Majnemer83f4bb22015-08-17 20:56:39 +0000403 ; CHECK-NEXT: call void @f()
404 ; CHECK-NEXT: unreachable
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000405 %cp1 = cleanuppad []
David Majnemer83f4bb22015-08-17 20:56:39 +0000406 br label %cleanupexit
407
408cleanupexit:
409 call void @f()
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000410 cleanupret %cp0 unwind label %cleanup2
David Majnemer83f4bb22015-08-17 20:56:39 +0000411}