blob: 048466a26d160797fb6890be35f9d6196c6470b5 [file] [log] [blame]
David Majnemer8a1c45d2015-12-12 05:38:55 +00001; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s
Joseph Tremouletc9ff9142015-08-13 14:30:10 +00002
3declare i32 @__CxxFrameHandler3(...)
David Majnemerf1ff5382016-01-22 23:20:43 +00004declare i32 @__C_specific_handler(...)
Joseph Tremouletc9ff9142015-08-13 14:30:10 +00005
6declare void @f()
7
8declare i32 @g()
9
10declare void @h(i32)
11
12declare i1 @i()
13
David Majnemer3bb88c02015-12-15 21:27:27 +000014declare void @llvm.bar() nounwind
15
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000016; CHECK-LABEL: @test1(
17define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
18entry:
19 ; Spill slot should be inserted here
20 ; CHECK: [[Slot:%[^ ]+]] = alloca
21 ; Can't store for %phi at these defs because the lifetimes overlap
22 ; CHECK-NOT: store
23 %x = call i32 @g()
24 %y = call i32 @g()
25 br i1 %B, label %left, label %right
26left:
27 ; CHECK: left:
28 ; CHECK-NEXT: store i32 %x, i32* [[Slot]]
29 ; CHECK-NEXT: invoke void @f
30 invoke void @f()
31 to label %exit unwind label %merge
32right:
33 ; CHECK: right:
34 ; CHECK-NEXT: store i32 %y, i32* [[Slot]]
35 ; CHECK-NEXT: invoke void @f
36 invoke void @f()
37 to label %exit unwind label %merge
38merge:
39 ; CHECK: merge:
40 ; CHECK-NOT: = phi
41 %phi = phi i32 [ %x, %left ], [ %y, %right ]
David Majnemer8a1c45d2015-12-12 05:38:55 +000042 %cs1 = catchswitch within none [label %catch] unwind to caller
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000043
44catch:
David Majnemer8a1c45d2015-12-12 05:38:55 +000045 %cp = catchpad within %cs1 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000046 ; CHECK: catch:
47 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
48 ; CHECK-NEXT: call void @h(i32 [[Reload]])
David Majnemer3bb88c02015-12-15 21:27:27 +000049 call void @h(i32 %phi) [ "funclet"(token %cp) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +000050 catchret from %cp to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000051
52exit:
53 ret void
54}
55
56; CHECK-LABEL: @test2(
57define void @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
58entry:
59 br i1 %B, label %left, label %right
60left:
61 ; Need two stores here because %x and %y interfere so they need 2 slots
62 ; CHECK: left:
63 ; CHECK: store i32 1, i32* [[Slot1:%[^ ]+]]
64 ; CHECK: store i32 1, i32* [[Slot2:%[^ ]+]]
65 ; CHECK-NEXT: invoke void @f
66 invoke void @f()
67 to label %exit unwind label %merge.inner
68right:
69 ; Need two stores here because %x and %y interfere so they need 2 slots
70 ; CHECK: right:
71 ; CHECK-DAG: store i32 2, i32* [[Slot1]]
72 ; CHECK-DAG: store i32 2, i32* [[Slot2]]
73 ; CHECK: invoke void @f
74 invoke void @f()
75 to label %exit unwind label %merge.inner
76merge.inner:
77 ; CHECK: merge.inner:
78 ; CHECK-NOT: = phi
David Majnemer8a1c45d2015-12-12 05:38:55 +000079 ; CHECK: catchswitch within none
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000080 %x = phi i32 [ 1, %left ], [ 2, %right ]
David Majnemer8a1c45d2015-12-12 05:38:55 +000081 %cs1 = catchswitch within none [label %catch.inner] unwind label %merge.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000082
83catch.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +000084 %cpinner = catchpad within %cs1 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000085 ; Need just one store here because only %y is affected
86 ; CHECK: catch.inner:
David Majnemer3bb88c02015-12-15 21:27:27 +000087 %z = call i32 @g() [ "funclet"(token %cpinner) ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000088 ; CHECK: store i32 %z
89 ; CHECK-NEXT: invoke void @f
David Majnemer3bb88c02015-12-15 21:27:27 +000090 invoke void @f() [ "funclet"(token %cpinner) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +000091 to label %catchret.inner unwind label %merge.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000092
93catchret.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +000094 catchret from %cpinner to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000095
96merge.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +000097 %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000098 ; CHECK: merge.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +000099 ; CHECK-NOT: = phi
100 ; CHECK: catchswitch within none
101 %cs2 = catchswitch within none [label %catch.outer] unwind to caller
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000102
103catch.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000104 %cpouter = catchpad within %cs2 []
105 ; CHECK: catch.outer:
106 ; CHECK: [[CatchPad:%[^ ]+]] = catchpad within %cs2 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000107 ; 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)
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000109 ; CHECK-DAG: load i32, i32* [[Slot1]]
110 ; CHECK-DAG: load i32, i32* [[Slot2]]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000111 ; CHECK: catchret from [[CatchPad]] to label
David Majnemer3bb88c02015-12-15 21:27:27 +0000112 call void @h(i32 %x) [ "funclet"(token %cpouter) ]
113 call void @h(i32 %y) [ "funclet"(token %cpouter) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000114 catchret from %cpouter to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000115
116exit:
117 ret void
118}
119
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000120; test4: don't need stores for %phi.inner, as its only use is to feed %phi.outer
121; %phi.outer needs stores in %left, %right, and %join
122; CHECK-LABEL: @test4(
123define void @test4(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
124entry:
125 ; CHECK: entry:
126 ; CHECK: [[Slot:%[^ ]+]] = alloca
127 ; CHECK-NEXT: br
128 br i1 %B, label %left, label %right
129left:
130 ; CHECK: left:
131 ; CHECK-NOT: store
132 ; CHECK: store i32 %l, i32* [[Slot]]
133 ; CHECK-NEXT: invoke void @f
134 %l = call i32 @g()
135 invoke void @f()
136 to label %join unwind label %catchpad.inner
137right:
138 ; CHECK: right:
139 ; CHECK-NOT: store
140 ; CHECK: store i32 %r, i32* [[Slot]]
141 ; CHECK-NEXT: invoke void @f
142 %r = call i32 @g()
143 invoke void @f()
144 to label %join unwind label %catchpad.inner
145catchpad.inner:
146 ; CHECK: catchpad.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000147 ; CHECK-NEXT: catchswitch within none
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000148 %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000149 %cs1 = catchswitch within none [label %catch.inner] unwind label %catchpad.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000150catch.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000151 %cp1 = catchpad within %cs1 []
152 catchret from %cp1 to label %join
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000153join:
154 ; CHECK: join:
155 ; CHECK-NOT: store
156 ; CHECK: store i32 %j, i32* [[Slot]]
157 ; CHECK-NEXT: invoke void @f
158 %j = call i32 @g()
159 invoke void @f()
160 to label %exit unwind label %catchpad.outer
David Majnemer8a1c45d2015-12-12 05:38:55 +0000161
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000162catchpad.outer:
163 ; CHECK: catchpad.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000164 ; CHECK-NEXT: catchswitch within none
165 %phi.outer = phi i32 [ %phi.inner, %catchpad.inner ], [ %j, %join ]
166 %cs2 = catchswitch within none [label %catch.outer] unwind to caller
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000167catch.outer:
168 ; CHECK: catch.outer:
169 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
170 ; CHECK: call void @h(i32 [[Reload]])
David Majnemer8a1c45d2015-12-12 05:38:55 +0000171 %cp2 = catchpad within %cs2 []
David Majnemer3bb88c02015-12-15 21:27:27 +0000172 call void @h(i32 %phi.outer) [ "funclet"(token %cp2) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000173 catchret from %cp2 to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000174exit:
175 ret void
176}
177
178; CHECK-LABEL: @test5(
179define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
180entry:
181 ; need store for %phi.cleanup
182 ; CHECK: entry:
183 ; CHECK: store i32 1, i32* [[CleanupSlot:%[^ ]+]]
184 ; CHECK-NEXT: invoke void @f
185 invoke void @f()
186 to label %invoke.cont unwind label %cleanup
187
188invoke.cont:
189 ; need store for %phi.cleanup
190 ; CHECK: invoke.cont:
191 ; CHECK-NEXT: store i32 2, i32* [[CleanupSlot]]
192 ; CHECK-NEXT: invoke void @f
193 invoke void @f()
194 to label %invoke.cont2 unwind label %cleanup
195
196cleanup:
197 ; cleanup phi can be loaded at cleanup entry
198 ; CHECK: cleanup:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000199 ; CHECK-NEXT: cleanuppad within none []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000200 ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
201 %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000202 %cp = cleanuppad within none []
David Majnemer3bb88c02015-12-15 21:27:27 +0000203 %b = call i1 @i() [ "funclet"(token %cp) ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000204 br i1 %b, label %left, label %right
205
206left:
207 ; CHECK: left:
208 ; CHECK: call void @h(i32 [[CleanupReload]]
David Majnemer3bb88c02015-12-15 21:27:27 +0000209 call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000210 br label %merge
211
212right:
213 ; CHECK: right:
214 ; CHECK: call void @h(i32 [[CleanupReload]]
David Majnemer3bb88c02015-12-15 21:27:27 +0000215 call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000216 br label %merge
217
218merge:
219 ; need store for %phi.catch
220 ; CHECK: merge:
221 ; CHECK-NEXT: store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000222 ; CHECK-NEXT: cleanupret
David Majnemer8a1c45d2015-12-12 05:38:55 +0000223 cleanupret from %cp unwind label %catchswitch
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000224
225invoke.cont2:
226 ; need store for %phi.catch
227 ; CHECK: invoke.cont2:
228 ; CHECK-NEXT: store i32 3, i32* [[CatchSlot]]
229 ; CHECK-NEXT: invoke void @f
230 invoke void @f()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000231 to label %exit unwind label %catchswitch
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000232
David Majnemer8a1c45d2015-12-12 05:38:55 +0000233catchswitch:
234 ; CHECK: catchswitch:
235 ; CHECK-NEXT: catchswitch within none
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000236 %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000237 %cs1 = catchswitch within none [label %catch] unwind to caller
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000238
239catch:
240 ; CHECK: catch:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000241 ; CHECK: catchpad within %cs1
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000242 ; CHECK: [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
243 ; CHECK: call void @h(i32 [[CatchReload]]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000244 %cp2 = catchpad within %cs1 []
David Majnemer3bb88c02015-12-15 21:27:27 +0000245 call void @h(i32 %phi.catch) [ "funclet"(token %cp2) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000246 catchret from %cp2 to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000247
248exit:
249 ret void
250}
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000251
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000252; We used to demote %x, but we don't need to anymore.
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000253; CHECK-LABEL: @test6(
254define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
255entry:
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000256 ; CHECK: entry:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000257 ; CHECK: %x = invoke i32 @g()
258 ; CHECK-NEXT: to label %loop unwind label %to_caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000259 %x = invoke i32 @g()
260 to label %loop unwind label %to_caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000261to_caller:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000262 %cp1 = cleanuppad within none []
263 cleanupret from %cp1 unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000264loop:
265 invoke void @f()
266 to label %loop unwind label %cleanup
267cleanup:
268 ; CHECK: cleanup:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000269 ; CHECK: call void @h(i32 %x)
David Majnemer8a1c45d2015-12-12 05:38:55 +0000270 %cp2 = cleanuppad within none []
David Majnemer3bb88c02015-12-15 21:27:27 +0000271 call void @h(i32 %x) [ "funclet"(token %cp2) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000272 cleanupret from %cp2 unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000273}
274
275; CHECK-LABEL: @test7(
276define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
277entry:
278 ; %x is an EH pad phi, so gets stored in pred here
279 ; CHECK: entry:
280 ; CHECK: store i32 1, i32* [[SlotX:%[^ ]+]]
281 ; CHECK: invoke void @f()
282 invoke void @f()
283 to label %invoke.cont unwind label %catchpad
284invoke.cont:
285 ; %x is an EH pad phi, so gets stored in pred here
286 ; CHECK: invoke.cont:
287 ; CHECK: store i32 2, i32* [[SlotX]]
288 ; CHECK: invoke void @f()
289 invoke void @f()
290 to label %exit unwind label %catchpad
291catchpad:
292 ; %x phi should be eliminated
293 ; CHECK: catchpad:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000294 ; CHECK-NEXT: catchswitch within none
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000295 %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000296 %cs1 = catchswitch within none [label %catch] unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000297catch:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000298 ; CHECK: catch:
299 ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []
300 %cp = catchpad within %cs1 []
David Majnemer3bb88c02015-12-15 21:27:27 +0000301 %b = call i1 @i() [ "funclet"(token %cp) ]
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000302 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:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000307 ; CHECK-NEXT: catchret from %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
308 catchret from %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()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000317 ; CHECK: catchret from %[[CatchPad]] to label %join
David Majnemer3bb88c02015-12-15 21:27:27 +0000318 %y = call i32 @g() [ "funclet"(token %cp) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000319 catchret from %cp to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000320join:
321 ; CHECK: join:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000322 ; CHECK: %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ]
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000323 %phi = phi i32 [ %x, %left ], [ %y, %right ]
324 call void @h(i32 %phi)
325 br label %exit
326exit:
327 ret void
328}
David Majnemer83f4bb22015-08-17 20:56:39 +0000329
330; CHECK-LABEL: @test8(
David Majnemerf1ff5382016-01-22 23:20:43 +0000331define void @test8() personality i32 (...)* @__C_specific_handler { entry:
David Majnemer83f4bb22015-08-17 20:56:39 +0000332 invoke void @f()
333 to label %done unwind label %cleanup1
334 invoke void @f()
335 to label %done unwind label %cleanup2
336
337done:
338 ret void
339
340cleanup1:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000341 ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []
David Majnemer3bb88c02015-12-15 21:27:27 +0000342 ; CHECK-NEXT: call void @llvm.bar()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000343 ; CHECK-NEXT: cleanupret from [[CleanupPad1]]
344 %cp0 = cleanuppad within none []
David Majnemer83f4bb22015-08-17 20:56:39 +0000345 br label %cleanupexit
346
347cleanup2:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000348 ; CHECK: cleanuppad within none []
David Majnemer3bb88c02015-12-15 21:27:27 +0000349 ; CHECK-NEXT: call void @llvm.bar()
David Majnemer83f4bb22015-08-17 20:56:39 +0000350 ; CHECK-NEXT: unreachable
David Majnemer8a1c45d2015-12-12 05:38:55 +0000351 %cp1 = cleanuppad within none []
David Majnemer83f4bb22015-08-17 20:56:39 +0000352 br label %cleanupexit
353
354cleanupexit:
David Majnemer3bb88c02015-12-15 21:27:27 +0000355 call void @llvm.bar()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000356 cleanupret from %cp0 unwind label %cleanup2
David Majnemer83f4bb22015-08-17 20:56:39 +0000357}