1 ; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s
3 declare i32 @__CxxFrameHandler3(...)
13 declare void @llvm.bar() nounwind
15 ; CHECK-LABEL: @test1(
16 define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
18 ; Spill slot should be inserted here
19 ; CHECK: [[Slot:%[^ ]+]] = alloca
20 ; Can't store for %phi at these defs because the lifetimes overlap
24 br i1 %B, label %left, label %right
27 ; CHECK-NEXT: store i32 %x, i32* [[Slot]]
28 ; CHECK-NEXT: invoke void @f
30 to label %exit unwind label %merge
33 ; CHECK-NEXT: store i32 %y, i32* [[Slot]]
34 ; CHECK-NEXT: invoke void @f
36 to label %exit unwind label %merge
40 %phi = phi i32 [ %x, %left ], [ %y, %right ]
41 %cs1 = catchswitch within none [label %catch] unwind to caller
44 %cp = catchpad within %cs1 []
46 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
47 ; CHECK-NEXT: call void @h(i32 [[Reload]])
48 call void @h(i32 %phi) [ "funclet"(token %cp) ]
49 catchret from %cp to label %exit
55 ; CHECK-LABEL: @test2(
56 define void @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
58 br i1 %B, label %left, label %right
60 ; Need two stores here because %x and %y interfere so they need 2 slots
62 ; CHECK: store i32 1, i32* [[Slot1:%[^ ]+]]
63 ; CHECK: store i32 1, i32* [[Slot2:%[^ ]+]]
64 ; CHECK-NEXT: invoke void @f
66 to label %exit unwind label %merge.inner
68 ; Need two stores here because %x and %y interfere so they need 2 slots
70 ; CHECK-DAG: store i32 2, i32* [[Slot1]]
71 ; CHECK-DAG: store i32 2, i32* [[Slot2]]
72 ; CHECK: invoke void @f
74 to label %exit unwind label %merge.inner
78 ; CHECK: catchswitch within none
79 %x = phi i32 [ 1, %left ], [ 2, %right ]
80 %cs1 = catchswitch within none [label %catch.inner] unwind label %merge.outer
83 %cpinner = catchpad within %cs1 []
84 ; Need just one store here because only %y is affected
86 %z = call i32 @g() [ "funclet"(token %cpinner) ]
88 ; CHECK-NEXT: invoke void @f
89 invoke void @f() [ "funclet"(token %cpinner) ]
90 to label %catchret.inner unwind label %merge.outer
93 catchret from %cpinner to label %exit
96 %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ]
99 ; CHECK: catchswitch within none
100 %cs2 = catchswitch within none [label %catch.outer] unwind to caller
103 %cpouter = catchpad within %cs2 []
104 ; CHECK: catch.outer:
105 ; CHECK: [[CatchPad:%[^ ]+]] = catchpad within %cs2 []
106 ; Need to load x and y from two different slots since they're both live
107 ; and can have different values (if we came from catch.inner)
108 ; CHECK-DAG: load i32, i32* [[Slot1]]
109 ; CHECK-DAG: load i32, i32* [[Slot2]]
110 ; CHECK: catchret from [[CatchPad]] to label
111 call void @h(i32 %x) [ "funclet"(token %cpouter) ]
112 call void @h(i32 %y) [ "funclet"(token %cpouter) ]
113 catchret from %cpouter to label %exit
119 ; test4: don't need stores for %phi.inner, as its only use is to feed %phi.outer
120 ; %phi.outer needs stores in %left, %right, and %join
121 ; CHECK-LABEL: @test4(
122 define void @test4(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
125 ; CHECK: [[Slot:%[^ ]+]] = alloca
127 br i1 %B, label %left, label %right
131 ; CHECK: store i32 %l, i32* [[Slot]]
132 ; CHECK-NEXT: invoke void @f
135 to label %join unwind label %catchpad.inner
139 ; CHECK: store i32 %r, i32* [[Slot]]
140 ; CHECK-NEXT: invoke void @f
143 to label %join unwind label %catchpad.inner
145 ; CHECK: catchpad.inner:
146 ; CHECK-NEXT: catchswitch within none
147 %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
148 %cs1 = catchswitch within none [label %catch.inner] unwind label %catchpad.outer
150 %cp1 = catchpad within %cs1 []
151 catchret from %cp1 to label %join
155 ; CHECK: store i32 %j, i32* [[Slot]]
156 ; CHECK-NEXT: invoke void @f
159 to label %exit unwind label %catchpad.outer
162 ; CHECK: catchpad.outer:
163 ; CHECK-NEXT: catchswitch within none
164 %phi.outer = phi i32 [ %phi.inner, %catchpad.inner ], [ %j, %join ]
165 %cs2 = catchswitch within none [label %catch.outer] unwind to caller
167 ; CHECK: catch.outer:
168 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
169 ; CHECK: call void @h(i32 [[Reload]])
170 %cp2 = catchpad within %cs2 []
171 call void @h(i32 %phi.outer) [ "funclet"(token %cp2) ]
172 catchret from %cp2 to label %exit
177 ; CHECK-LABEL: @test5(
178 define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
180 ; need store for %phi.cleanup
182 ; CHECK: store i32 1, i32* [[CleanupSlot:%[^ ]+]]
183 ; CHECK-NEXT: invoke void @f
185 to label %invoke.cont unwind label %cleanup
188 ; need store for %phi.cleanup
189 ; CHECK: invoke.cont:
190 ; CHECK-NEXT: store i32 2, i32* [[CleanupSlot]]
191 ; CHECK-NEXT: invoke void @f
193 to label %invoke.cont2 unwind label %cleanup
196 ; cleanup phi can be loaded at cleanup entry
198 ; CHECK-NEXT: cleanuppad within none []
199 ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
200 %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
201 %cp = cleanuppad within none []
202 %b = call i1 @i() [ "funclet"(token %cp) ]
203 br i1 %b, label %left, label %right
207 ; CHECK: call void @h(i32 [[CleanupReload]]
208 call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
213 ; CHECK: call void @h(i32 [[CleanupReload]]
214 call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
218 ; need store for %phi.catch
220 ; CHECK-NEXT: store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
221 ; CHECK-NEXT: cleanupret
222 cleanupret from %cp unwind label %catchswitch
225 ; need store for %phi.catch
226 ; CHECK: invoke.cont2:
227 ; CHECK-NEXT: store i32 3, i32* [[CatchSlot]]
228 ; CHECK-NEXT: invoke void @f
230 to label %exit unwind label %catchswitch
233 ; CHECK: catchswitch:
234 ; CHECK-NEXT: catchswitch within none
235 %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
236 %cs1 = catchswitch within none [label %catch] unwind to caller
240 ; CHECK: catchpad within %cs1
241 ; CHECK: [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
242 ; CHECK: call void @h(i32 [[CatchReload]]
243 %cp2 = catchpad within %cs1 []
244 call void @h(i32 %phi.catch) [ "funclet"(token %cp2) ]
245 catchret from %cp2 to label %exit
251 ; We used to demote %x, but we don't need to anymore.
252 ; CHECK-LABEL: @test6(
253 define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
256 ; CHECK: %x = invoke i32 @g()
257 ; CHECK-NEXT: to label %loop unwind label %to_caller
259 to label %loop unwind label %to_caller
261 %cp1 = cleanuppad within none []
262 cleanupret from %cp1 unwind to caller
265 to label %loop unwind label %cleanup
268 ; CHECK: call void @h(i32 %x)
269 %cp2 = cleanuppad within none []
270 call void @h(i32 %x) [ "funclet"(token %cp2) ]
271 cleanupret from %cp2 unwind to caller
274 ; CHECK-LABEL: @test7(
275 define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
277 ; %x is an EH pad phi, so gets stored in pred here
279 ; CHECK: store i32 1, i32* [[SlotX:%[^ ]+]]
280 ; CHECK: invoke void @f()
282 to label %invoke.cont unwind label %catchpad
284 ; %x is an EH pad phi, so gets stored in pred here
285 ; CHECK: invoke.cont:
286 ; CHECK: store i32 2, i32* [[SlotX]]
287 ; CHECK: invoke void @f()
289 to label %exit unwind label %catchpad
291 ; %x phi should be eliminated
293 ; CHECK-NEXT: catchswitch within none
294 %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
295 %cs1 = catchswitch within none [label %catch] unwind to caller
298 ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []
299 %cp = catchpad within %cs1 []
300 %b = call i1 @i() [ "funclet"(token %cp) ]
301 br i1 %b, label %left, label %right
303 ; Edge from %left to %join needs to be split so that
304 ; the load of %x can be inserted *after* the catchret
306 ; CHECK-NEXT: catchret from %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
307 catchret from %cp to label %join
308 ; CHECK: [[SplitLeft]]:
309 ; CHECK: [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
310 ; CHECK: br label %join
312 ; Edge from %right to %join needs to be split so that
313 ; the load of %y can be inserted *after* the catchret
315 ; CHECK: %y = call i32 @g()
316 ; CHECK: catchret from %[[CatchPad]] to label %join
317 %y = call i32 @g() [ "funclet"(token %cp) ]
318 catchret from %cp to label %join
321 ; CHECK: %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ]
322 %phi = phi i32 [ %x, %left ], [ %y, %right ]
323 call void @h(i32 %phi)
329 ; CHECK-LABEL: @test8(
330 define void @test8() personality i32 (...)* @__CxxFrameHandler3 { entry:
332 to label %done unwind label %cleanup1
334 to label %done unwind label %cleanup2
340 ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []
341 ; CHECK-NEXT: call void @llvm.bar()
342 ; CHECK-NEXT: cleanupret from [[CleanupPad1]]
343 %cp0 = cleanuppad within none []
344 br label %cleanupexit
347 ; CHECK: cleanuppad within none []
348 ; CHECK-NEXT: call void @llvm.bar()
349 ; CHECK-NEXT: unreachable
350 %cp1 = cleanuppad within none []
351 br label %cleanupexit
354 call void @llvm.bar()
355 cleanupret from %cp0 unwind label %cleanup2