blob: 96f33b0ed1a539c958325e0dd5aa28cb6ad49b5e [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()
Andrew Kaylorfdd48fa2015-11-09 19:59:02 +000089 to label %catchret.inner unwind label %catchend.inner
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000090
91catchret.inner:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +000092 catchret %cpinner to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000093catchend.inner:
Andrew Kaylorfdd48fa2015-11-09 19:59:02 +000094 ; CHECK-NOT: = phi
95 %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000096 catchendpad unwind label %merge.outer
97
98merge.outer:
99 ; CHECK: merge.outer:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000100 ; CHECK: [[CatchPad:%[^ ]+]] = catchpad []
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
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000121; test4: don't need stores for %phi.inner, as its only use is to feed %phi.outer
122; %phi.outer needs stores in %left, %right, and %join
123; CHECK-LABEL: @test4(
124define void @test4(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
125entry:
126 ; CHECK: entry:
127 ; CHECK: [[Slot:%[^ ]+]] = alloca
128 ; CHECK-NEXT: br
129 br i1 %B, label %left, label %right
130left:
131 ; CHECK: left:
132 ; CHECK-NOT: store
133 ; CHECK: store i32 %l, i32* [[Slot]]
134 ; CHECK-NEXT: invoke void @f
135 %l = call i32 @g()
136 invoke void @f()
137 to label %join unwind label %catchpad.inner
138right:
139 ; CHECK: right:
140 ; CHECK-NOT: store
141 ; CHECK: store i32 %r, i32* [[Slot]]
142 ; CHECK-NEXT: invoke void @f
143 %r = call i32 @g()
144 invoke void @f()
145 to label %join unwind label %catchpad.inner
146catchpad.inner:
147 ; CHECK: catchpad.inner:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000148 ; CHECK-NEXT: catchpad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000149 %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000150 %cp1 = catchpad [] to label %catch.inner unwind label %catchend.inner
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000151catch.inner:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000152 catchret %cp1 to label %join
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000153catchend.inner:
154 catchendpad unwind label %catchpad.outer
155join:
156 ; CHECK: join:
157 ; CHECK-NOT: store
158 ; CHECK: store i32 %j, i32* [[Slot]]
159 ; CHECK-NEXT: invoke void @f
160 %j = call i32 @g()
161 invoke void @f()
162 to label %exit unwind label %catchpad.outer
163catchpad.outer:
164 ; CHECK: catchpad.outer:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000165 ; CHECK-NEXT: catchpad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000166 %phi.outer = phi i32 [ %phi.inner, %catchend.inner ], [ %j, %join ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000167 %cp2 = catchpad [] to label %catch.outer unwind label %catchend.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000168catch.outer:
169 ; CHECK: catch.outer:
170 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
171 ; CHECK: call void @h(i32 [[Reload]])
172 call void @h(i32 %phi.outer)
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000173 catchret %cp2 to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000174catchend.outer:
175 catchendpad unwind to caller
176exit:
177 ret void
178}
179
180; CHECK-LABEL: @test5(
181define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
182entry:
183 ; need store for %phi.cleanup
184 ; CHECK: entry:
185 ; CHECK: store i32 1, i32* [[CleanupSlot:%[^ ]+]]
186 ; CHECK-NEXT: invoke void @f
187 invoke void @f()
188 to label %invoke.cont unwind label %cleanup
189
190invoke.cont:
191 ; need store for %phi.cleanup
192 ; CHECK: invoke.cont:
193 ; CHECK-NEXT: store i32 2, i32* [[CleanupSlot]]
194 ; CHECK-NEXT: invoke void @f
195 invoke void @f()
196 to label %invoke.cont2 unwind label %cleanup
197
198cleanup:
199 ; cleanup phi can be loaded at cleanup entry
200 ; CHECK: cleanup:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000201 ; CHECK-NEXT: cleanuppad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000202 ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
203 %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000204 %cp = cleanuppad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000205 %b = call i1 @i()
206 br i1 %b, label %left, label %right
207
208left:
209 ; CHECK: left:
210 ; CHECK: call void @h(i32 [[CleanupReload]]
211 call void @h(i32 %phi.cleanup)
212 br label %merge
213
214right:
215 ; CHECK: right:
216 ; CHECK: call void @h(i32 [[CleanupReload]]
217 call void @h(i32 %phi.cleanup)
218 br label %merge
219
220merge:
221 ; need store for %phi.catch
222 ; CHECK: merge:
223 ; CHECK-NEXT: store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000224 ; CHECK-NEXT: cleanupret
225 cleanupret %cp unwind label %catchpad
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000226
227invoke.cont2:
228 ; need store for %phi.catch
229 ; CHECK: invoke.cont2:
230 ; CHECK-NEXT: store i32 3, i32* [[CatchSlot]]
231 ; CHECK-NEXT: invoke void @f
232 invoke void @f()
233 to label %exit unwind label %catchpad
234
235catchpad:
236 ; CHECK: catchpad:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000237 ; CHECK-NEXT: catchpad []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000238 %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000239 %cp2 = catchpad [] to label %catch unwind label %catchend
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000240
241catch:
242 ; CHECK: catch:
243 ; CHECK: [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
244 ; CHECK: call void @h(i32 [[CatchReload]]
245 call void @h(i32 %phi.catch)
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000246 catchret %cp2 to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000247
248catchend:
249 catchendpad unwind to caller
250
251exit:
252 ret void
253}
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000254
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000255; We used to demote %x, but we don't need to anymore.
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000256; CHECK-LABEL: @test6(
257define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
258entry:
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000259 ; CHECK: entry:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000260 ; CHECK: %x = invoke i32 @g()
261 ; CHECK-NEXT: to label %loop unwind label %to_caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000262 %x = invoke i32 @g()
263 to label %loop unwind label %to_caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000264to_caller:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000265 %cp1 = cleanuppad []
266 cleanupret %cp1 unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000267loop:
268 invoke void @f()
269 to label %loop unwind label %cleanup
270cleanup:
271 ; CHECK: cleanup:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000272 ; CHECK: call void @h(i32 %x)
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000273 %cp2 = cleanuppad []
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000274 call void @h(i32 %x)
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000275 cleanupret %cp2 unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000276}
277
278; CHECK-LABEL: @test7(
279define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
280entry:
281 ; %x is an EH pad phi, so gets stored in pred here
282 ; CHECK: entry:
283 ; CHECK: store i32 1, i32* [[SlotX:%[^ ]+]]
284 ; CHECK: invoke void @f()
285 invoke void @f()
286 to label %invoke.cont unwind label %catchpad
287invoke.cont:
288 ; %x is an EH pad phi, so gets stored in pred here
289 ; CHECK: invoke.cont:
290 ; CHECK: store i32 2, i32* [[SlotX]]
291 ; CHECK: invoke void @f()
292 invoke void @f()
293 to label %exit unwind label %catchpad
294catchpad:
295 ; %x phi should be eliminated
296 ; CHECK: catchpad:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000297 ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad []
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000298 %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000299 %cp = catchpad [] to label %catch unwind label %catchend
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000300catch:
301 %b = call i1 @i()
302 br i1 %b, label %left, label %right
303left:
304 ; Edge from %left to %join needs to be split so that
305 ; the load of %x can be inserted *after* the catchret
306 ; CHECK: left:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000307 ; CHECK-NEXT: catchret %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
308 catchret %cp to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000309 ; CHECK: [[SplitLeft]]:
310 ; CHECK: [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
311 ; CHECK: br label %join
312right:
313 ; Edge from %right to %join needs to be split so that
314 ; the load of %y can be inserted *after* the catchret
315 ; CHECK: right:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000316 ; CHECK: %y = call i32 @g()
317 ; CHECK: catchret %[[CatchPad]] to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000318 %y = call i32 @g()
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000319 catchret %cp to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000320catchend:
321 catchendpad unwind to caller
322join:
323 ; CHECK: join:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000324 ; CHECK: %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ]
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000325 %phi = phi i32 [ %x, %left ], [ %y, %right ]
326 call void @h(i32 %phi)
327 br label %exit
328exit:
329 ret void
330}
David Majnemer83f4bb22015-08-17 20:56:39 +0000331
332; CHECK-LABEL: @test8(
333define void @test8() personality i32 (...)* @__CxxFrameHandler3 { entry:
334 invoke void @f()
335 to label %done unwind label %cleanup1
336 invoke void @f()
337 to label %done unwind label %cleanup2
338
339done:
340 ret void
341
342cleanup1:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000343 ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad []
David Majnemer83f4bb22015-08-17 20:56:39 +0000344 ; CHECK-NEXT: call void @f()
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000345 ; CHECK-NEXT: cleanupret [[CleanupPad1]]
346 %cp0 = cleanuppad []
David Majnemer83f4bb22015-08-17 20:56:39 +0000347 br label %cleanupexit
348
349cleanup2:
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000350 ; CHECK: cleanuppad []
David Majnemer83f4bb22015-08-17 20:56:39 +0000351 ; CHECK-NEXT: call void @f()
352 ; CHECK-NEXT: unreachable
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000353 %cp1 = cleanuppad []
David Majnemer83f4bb22015-08-17 20:56:39 +0000354 br label %cleanupexit
355
356cleanupexit:
357 call void @f()
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000358 cleanupret %cp0 unwind label %cleanup2
David Majnemer83f4bb22015-08-17 20:56:39 +0000359}