blob: bd239133ea878388c8f64858fd06b70089298cf4 [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(...)
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 ]
David Majnemer8a1c45d2015-12-12 05:38:55 +000039 %cs1 = catchswitch within none [label %catch] unwind to caller
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000040
41catch:
David Majnemer8a1c45d2015-12-12 05:38:55 +000042 %cp = catchpad within %cs1 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000043 ; CHECK: catch:
44 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
45 ; CHECK-NEXT: call void @h(i32 [[Reload]])
46 call void @h(i32 %phi)
David Majnemer8a1c45d2015-12-12 05:38:55 +000047 catchret from %cp to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000048
49exit:
50 ret void
51}
52
53; CHECK-LABEL: @test2(
54define void @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
55entry:
56 br i1 %B, label %left, label %right
57left:
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
65right:
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
73merge.inner:
74 ; CHECK: merge.inner:
75 ; CHECK-NOT: = phi
David Majnemer8a1c45d2015-12-12 05:38:55 +000076 ; CHECK: catchswitch within none
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000077 %x = phi i32 [ 1, %left ], [ 2, %right ]
David Majnemer8a1c45d2015-12-12 05:38:55 +000078 %cs1 = catchswitch within none [label %catch.inner] unwind label %merge.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000079
80catch.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +000081 %cpinner = catchpad within %cs1 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000082 ; 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()
David Majnemer8a1c45d2015-12-12 05:38:55 +000088 to label %catchret.inner unwind label %merge.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000089
90catchret.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +000091 catchret from %cpinner to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000092
93merge.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +000094 %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000095 ; CHECK: merge.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +000096 ; CHECK-NOT: = phi
97 ; CHECK: catchswitch within none
98 %cs2 = catchswitch within none [label %catch.outer] unwind to caller
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000099
100catch.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000101 %cpouter = catchpad within %cs2 []
102 ; CHECK: catch.outer:
103 ; CHECK: [[CatchPad:%[^ ]+]] = catchpad within %cs2 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000104 ; 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)
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000106 ; CHECK-DAG: load i32, i32* [[Slot1]]
107 ; CHECK-DAG: load i32, i32* [[Slot2]]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000108 ; CHECK: catchret from [[CatchPad]] to label
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000109 call void @h(i32 %x)
110 call void @h(i32 %y)
David Majnemer8a1c45d2015-12-12 05:38:55 +0000111 catchret from %cpouter to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000112
113exit:
114 ret void
115}
116
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000117; 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(
120define void @test4(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
121entry:
122 ; CHECK: entry:
123 ; CHECK: [[Slot:%[^ ]+]] = alloca
124 ; CHECK-NEXT: br
125 br i1 %B, label %left, label %right
126left:
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
134right:
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
142catchpad.inner:
143 ; CHECK: catchpad.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000144 ; CHECK-NEXT: catchswitch within none
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000145 %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000146 %cs1 = catchswitch within none [label %catch.inner] unwind label %catchpad.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000147catch.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000148 %cp1 = catchpad within %cs1 []
149 catchret from %cp1 to label %join
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000150join:
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
David Majnemer8a1c45d2015-12-12 05:38:55 +0000158
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000159catchpad.outer:
160 ; CHECK: catchpad.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000161 ; 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
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000164catch.outer:
165 ; CHECK: catch.outer:
166 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
167 ; CHECK: call void @h(i32 [[Reload]])
David Majnemer8a1c45d2015-12-12 05:38:55 +0000168 %cp2 = catchpad within %cs2 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000169 call void @h(i32 %phi.outer)
David Majnemer8a1c45d2015-12-12 05:38:55 +0000170 catchret from %cp2 to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000171exit:
172 ret void
173}
174
175; CHECK-LABEL: @test5(
176define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
177entry:
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
185invoke.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
193cleanup:
194 ; cleanup phi can be loaded at cleanup entry
195 ; CHECK: cleanup:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000196 ; CHECK-NEXT: cleanuppad within none []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000197 ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
198 %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000199 %cp = cleanuppad within none []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000200 %b = call i1 @i()
201 br i1 %b, label %left, label %right
202
203left:
204 ; CHECK: left:
205 ; CHECK: call void @h(i32 [[CleanupReload]]
206 call void @h(i32 %phi.cleanup)
207 br label %merge
208
209right:
210 ; CHECK: right:
211 ; CHECK: call void @h(i32 [[CleanupReload]]
212 call void @h(i32 %phi.cleanup)
213 br label %merge
214
215merge:
216 ; need store for %phi.catch
217 ; CHECK: merge:
218 ; CHECK-NEXT: store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000219 ; CHECK-NEXT: cleanupret
David Majnemer8a1c45d2015-12-12 05:38:55 +0000220 cleanupret from %cp unwind label %catchswitch
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000221
222invoke.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()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000228 to label %exit unwind label %catchswitch
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000229
David Majnemer8a1c45d2015-12-12 05:38:55 +0000230catchswitch:
231 ; CHECK: catchswitch:
232 ; CHECK-NEXT: catchswitch within none
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000233 %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000234 %cs1 = catchswitch within none [label %catch] unwind to caller
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000235
236catch:
237 ; CHECK: catch:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000238 ; CHECK: catchpad within %cs1
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000239 ; CHECK: [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
240 ; CHECK: call void @h(i32 [[CatchReload]]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000241 %cp2 = catchpad within %cs1 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000242 call void @h(i32 %phi.catch)
David Majnemer8a1c45d2015-12-12 05:38:55 +0000243 catchret from %cp2 to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000244
245exit:
246 ret void
247}
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000248
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000249; We used to demote %x, but we don't need to anymore.
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000250; CHECK-LABEL: @test6(
251define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
252entry:
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000253 ; CHECK: entry:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000254 ; CHECK: %x = invoke i32 @g()
255 ; CHECK-NEXT: to label %loop unwind label %to_caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000256 %x = invoke i32 @g()
257 to label %loop unwind label %to_caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000258to_caller:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000259 %cp1 = cleanuppad within none []
260 cleanupret from %cp1 unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000261loop:
262 invoke void @f()
263 to label %loop unwind label %cleanup
264cleanup:
265 ; CHECK: cleanup:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000266 ; CHECK: call void @h(i32 %x)
David Majnemer8a1c45d2015-12-12 05:38:55 +0000267 %cp2 = cleanuppad within none []
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000268 call void @h(i32 %x)
David Majnemer8a1c45d2015-12-12 05:38:55 +0000269 cleanupret from %cp2 unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000270}
271
272; CHECK-LABEL: @test7(
273define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
274entry:
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
281invoke.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
288catchpad:
289 ; %x phi should be eliminated
290 ; CHECK: catchpad:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000291 ; CHECK-NEXT: catchswitch within none
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000292 %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000293 %cs1 = catchswitch within none [label %catch] unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000294catch:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000295 ; CHECK: catch:
296 ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []
297 %cp = catchpad within %cs1 []
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000298 %b = call i1 @i()
299 br i1 %b, label %left, label %right
300left:
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:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000304 ; CHECK-NEXT: catchret from %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
305 catchret from %cp to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000306 ; CHECK: [[SplitLeft]]:
307 ; CHECK: [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
308 ; CHECK: br label %join
309right:
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:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000313 ; CHECK: %y = call i32 @g()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000314 ; CHECK: catchret from %[[CatchPad]] to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000315 %y = call i32 @g()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000316 catchret from %cp to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000317join:
318 ; CHECK: join:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000319 ; CHECK: %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ]
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000320 %phi = phi i32 [ %x, %left ], [ %y, %right ]
321 call void @h(i32 %phi)
322 br label %exit
323exit:
324 ret void
325}
David Majnemer83f4bb22015-08-17 20:56:39 +0000326
327; CHECK-LABEL: @test8(
328define 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
334done:
335 ret void
336
337cleanup1:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000338 ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []
David Majnemer83f4bb22015-08-17 20:56:39 +0000339 ; CHECK-NEXT: call void @f()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000340 ; CHECK-NEXT: cleanupret from [[CleanupPad1]]
341 %cp0 = cleanuppad within none []
David Majnemer83f4bb22015-08-17 20:56:39 +0000342 br label %cleanupexit
343
344cleanup2:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000345 ; CHECK: cleanuppad within none []
David Majnemer83f4bb22015-08-17 20:56:39 +0000346 ; CHECK-NEXT: call void @f()
347 ; CHECK-NEXT: unreachable
David Majnemer8a1c45d2015-12-12 05:38:55 +0000348 %cp1 = cleanuppad within none []
David Majnemer83f4bb22015-08-17 20:56:39 +0000349 br label %cleanupexit
350
351cleanupexit:
352 call void @f()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000353 cleanupret from %cp0 unwind label %cleanup2
David Majnemer83f4bb22015-08-17 20:56:39 +0000354}