blob: 411952d84bb6ce3ff3c077641f55e0c0092fc5b8 [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
David Majnemer3bb88c02015-12-15 21:27:27 +000013declare void @llvm.bar() nounwind
14
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000015; CHECK-LABEL: @test1(
16define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
17entry:
18 ; Spill slot should be inserted here
19 ; CHECK: [[Slot:%[^ ]+]] = alloca
20 ; Can't store for %phi at these defs because the lifetimes overlap
21 ; CHECK-NOT: store
22 %x = call i32 @g()
23 %y = call i32 @g()
24 br i1 %B, label %left, label %right
25left:
26 ; CHECK: left:
27 ; CHECK-NEXT: store i32 %x, i32* [[Slot]]
28 ; CHECK-NEXT: invoke void @f
29 invoke void @f()
30 to label %exit unwind label %merge
31right:
32 ; CHECK: right:
33 ; CHECK-NEXT: store i32 %y, i32* [[Slot]]
34 ; CHECK-NEXT: invoke void @f
35 invoke void @f()
36 to label %exit unwind label %merge
37merge:
38 ; CHECK: merge:
39 ; CHECK-NOT: = phi
40 %phi = phi i32 [ %x, %left ], [ %y, %right ]
David Majnemer8a1c45d2015-12-12 05:38:55 +000041 %cs1 = catchswitch within none [label %catch] unwind to caller
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000042
43catch:
David Majnemer8a1c45d2015-12-12 05:38:55 +000044 %cp = catchpad within %cs1 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000045 ; CHECK: catch:
46 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
47 ; CHECK-NEXT: call void @h(i32 [[Reload]])
David Majnemer3bb88c02015-12-15 21:27:27 +000048 call void @h(i32 %phi) [ "funclet"(token %cp) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +000049 catchret from %cp to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000050
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
David Majnemer8a1c45d2015-12-12 05:38:55 +000078 ; CHECK: catchswitch within none
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000079 %x = phi i32 [ 1, %left ], [ 2, %right ]
David Majnemer8a1c45d2015-12-12 05:38:55 +000080 %cs1 = catchswitch within none [label %catch.inner] unwind label %merge.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000081
82catch.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +000083 %cpinner = catchpad within %cs1 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000084 ; Need just one store here because only %y is affected
85 ; CHECK: catch.inner:
David Majnemer3bb88c02015-12-15 21:27:27 +000086 %z = call i32 @g() [ "funclet"(token %cpinner) ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000087 ; CHECK: store i32 %z
88 ; CHECK-NEXT: invoke void @f
David Majnemer3bb88c02015-12-15 21:27:27 +000089 invoke void @f() [ "funclet"(token %cpinner) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +000090 to label %catchret.inner unwind label %merge.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000091
92catchret.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +000093 catchret from %cpinner to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000094
95merge.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +000096 %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +000097 ; CHECK: merge.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +000098 ; CHECK-NOT: = phi
99 ; CHECK: catchswitch within none
100 %cs2 = catchswitch within none [label %catch.outer] unwind to caller
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000101
102catch.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000103 %cpouter = catchpad within %cs2 []
104 ; CHECK: catch.outer:
105 ; CHECK: [[CatchPad:%[^ ]+]] = catchpad within %cs2 []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000106 ; 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)
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000108 ; CHECK-DAG: load i32, i32* [[Slot1]]
109 ; CHECK-DAG: load i32, i32* [[Slot2]]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000110 ; CHECK: catchret from [[CatchPad]] to label
David Majnemer3bb88c02015-12-15 21:27:27 +0000111 call void @h(i32 %x) [ "funclet"(token %cpouter) ]
112 call void @h(i32 %y) [ "funclet"(token %cpouter) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000113 catchret from %cpouter to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000114
115exit:
116 ret void
117}
118
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000119; 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(
122define void @test4(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
123entry:
124 ; CHECK: entry:
125 ; CHECK: [[Slot:%[^ ]+]] = alloca
126 ; CHECK-NEXT: br
127 br i1 %B, label %left, label %right
128left:
129 ; CHECK: left:
130 ; CHECK-NOT: store
131 ; CHECK: store i32 %l, i32* [[Slot]]
132 ; CHECK-NEXT: invoke void @f
133 %l = call i32 @g()
134 invoke void @f()
135 to label %join unwind label %catchpad.inner
136right:
137 ; CHECK: right:
138 ; CHECK-NOT: store
139 ; CHECK: store i32 %r, i32* [[Slot]]
140 ; CHECK-NEXT: invoke void @f
141 %r = call i32 @g()
142 invoke void @f()
143 to label %join unwind label %catchpad.inner
144catchpad.inner:
145 ; CHECK: catchpad.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000146 ; CHECK-NEXT: catchswitch within none
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000147 %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000148 %cs1 = catchswitch within none [label %catch.inner] unwind label %catchpad.outer
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000149catch.inner:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000150 %cp1 = catchpad within %cs1 []
151 catchret from %cp1 to label %join
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000152join:
153 ; CHECK: join:
154 ; CHECK-NOT: store
155 ; CHECK: store i32 %j, i32* [[Slot]]
156 ; CHECK-NEXT: invoke void @f
157 %j = call i32 @g()
158 invoke void @f()
159 to label %exit unwind label %catchpad.outer
David Majnemer8a1c45d2015-12-12 05:38:55 +0000160
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000161catchpad.outer:
162 ; CHECK: catchpad.outer:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000163 ; 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
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000166catch.outer:
167 ; CHECK: catch.outer:
168 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
169 ; CHECK: call void @h(i32 [[Reload]])
David Majnemer8a1c45d2015-12-12 05:38:55 +0000170 %cp2 = catchpad within %cs2 []
David Majnemer3bb88c02015-12-15 21:27:27 +0000171 call void @h(i32 %phi.outer) [ "funclet"(token %cp2) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000172 catchret from %cp2 to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000173exit:
174 ret void
175}
176
177; CHECK-LABEL: @test5(
178define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
179entry:
180 ; need store for %phi.cleanup
181 ; CHECK: entry:
182 ; CHECK: store i32 1, i32* [[CleanupSlot:%[^ ]+]]
183 ; CHECK-NEXT: invoke void @f
184 invoke void @f()
185 to label %invoke.cont unwind label %cleanup
186
187invoke.cont:
188 ; need store for %phi.cleanup
189 ; CHECK: invoke.cont:
190 ; CHECK-NEXT: store i32 2, i32* [[CleanupSlot]]
191 ; CHECK-NEXT: invoke void @f
192 invoke void @f()
193 to label %invoke.cont2 unwind label %cleanup
194
195cleanup:
196 ; cleanup phi can be loaded at cleanup entry
197 ; CHECK: cleanup:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000198 ; CHECK-NEXT: cleanuppad within none []
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000199 ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
200 %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000201 %cp = cleanuppad within none []
David Majnemer3bb88c02015-12-15 21:27:27 +0000202 %b = call i1 @i() [ "funclet"(token %cp) ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000203 br i1 %b, label %left, label %right
204
205left:
206 ; CHECK: left:
207 ; CHECK: call void @h(i32 [[CleanupReload]]
David Majnemer3bb88c02015-12-15 21:27:27 +0000208 call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000209 br label %merge
210
211right:
212 ; CHECK: right:
213 ; CHECK: call void @h(i32 [[CleanupReload]]
David Majnemer3bb88c02015-12-15 21:27:27 +0000214 call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000215 br label %merge
216
217merge:
218 ; need store for %phi.catch
219 ; CHECK: merge:
220 ; CHECK-NEXT: store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
Joseph Tremoulet8220bcc2015-08-23 00:26:33 +0000221 ; CHECK-NEXT: cleanupret
David Majnemer8a1c45d2015-12-12 05:38:55 +0000222 cleanupret from %cp unwind label %catchswitch
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000223
224invoke.cont2:
225 ; need store for %phi.catch
226 ; CHECK: invoke.cont2:
227 ; CHECK-NEXT: store i32 3, i32* [[CatchSlot]]
228 ; CHECK-NEXT: invoke void @f
229 invoke void @f()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000230 to label %exit unwind label %catchswitch
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000231
David Majnemer8a1c45d2015-12-12 05:38:55 +0000232catchswitch:
233 ; CHECK: catchswitch:
234 ; CHECK-NEXT: catchswitch within none
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000235 %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000236 %cs1 = catchswitch within none [label %catch] unwind to caller
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000237
238catch:
239 ; CHECK: catch:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000240 ; CHECK: catchpad within %cs1
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000241 ; CHECK: [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
242 ; CHECK: call void @h(i32 [[CatchReload]]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000243 %cp2 = catchpad within %cs1 []
David Majnemer3bb88c02015-12-15 21:27:27 +0000244 call void @h(i32 %phi.catch) [ "funclet"(token %cp2) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000245 catchret from %cp2 to label %exit
Joseph Tremouletc9ff9142015-08-13 14:30:10 +0000246
247exit:
248 ret void
249}
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000250
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000251; We used to demote %x, but we don't need to anymore.
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000252; CHECK-LABEL: @test6(
253define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
254entry:
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000255 ; CHECK: entry:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000256 ; CHECK: %x = invoke i32 @g()
257 ; CHECK-NEXT: to label %loop unwind label %to_caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000258 %x = invoke i32 @g()
259 to label %loop unwind label %to_caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000260to_caller:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000261 %cp1 = cleanuppad within none []
262 cleanupret from %cp1 unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000263loop:
264 invoke void @f()
265 to label %loop unwind label %cleanup
266cleanup:
267 ; CHECK: cleanup:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000268 ; CHECK: call void @h(i32 %x)
David Majnemer8a1c45d2015-12-12 05:38:55 +0000269 %cp2 = cleanuppad within none []
David Majnemer3bb88c02015-12-15 21:27:27 +0000270 call void @h(i32 %x) [ "funclet"(token %cp2) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000271 cleanupret from %cp2 unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000272}
273
274; CHECK-LABEL: @test7(
275define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
276entry:
277 ; %x is an EH pad phi, so gets stored in pred here
278 ; CHECK: entry:
279 ; CHECK: store i32 1, i32* [[SlotX:%[^ ]+]]
280 ; CHECK: invoke void @f()
281 invoke void @f()
282 to label %invoke.cont unwind label %catchpad
283invoke.cont:
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()
288 invoke void @f()
289 to label %exit unwind label %catchpad
290catchpad:
291 ; %x phi should be eliminated
292 ; CHECK: catchpad:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000293 ; CHECK-NEXT: catchswitch within none
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000294 %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000295 %cs1 = catchswitch within none [label %catch] unwind to caller
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000296catch:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000297 ; CHECK: catch:
298 ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []
299 %cp = catchpad within %cs1 []
David Majnemer3bb88c02015-12-15 21:27:27 +0000300 %b = call i1 @i() [ "funclet"(token %cp) ]
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000301 br i1 %b, label %left, label %right
302left:
303 ; Edge from %left to %join needs to be split so that
304 ; the load of %x can be inserted *after* the catchret
305 ; CHECK: left:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000306 ; CHECK-NEXT: catchret from %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
307 catchret from %cp to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000308 ; CHECK: [[SplitLeft]]:
309 ; CHECK: [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
310 ; CHECK: br label %join
311right:
312 ; Edge from %right to %join needs to be split so that
313 ; the load of %y can be inserted *after* the catchret
314 ; CHECK: right:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000315 ; CHECK: %y = call i32 @g()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000316 ; CHECK: catchret from %[[CatchPad]] to label %join
David Majnemer3bb88c02015-12-15 21:27:27 +0000317 %y = call i32 @g() [ "funclet"(token %cp) ]
David Majnemer8a1c45d2015-12-12 05:38:55 +0000318 catchret from %cp to label %join
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000319join:
320 ; CHECK: join:
Reid Klecknercc2f6c32015-11-19 23:23:33 +0000321 ; CHECK: %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ]
Joseph Tremoulet7031c9f2015-08-17 13:51:37 +0000322 %phi = phi i32 [ %x, %left ], [ %y, %right ]
323 call void @h(i32 %phi)
324 br label %exit
325exit:
326 ret void
327}
David Majnemer83f4bb22015-08-17 20:56:39 +0000328
329; CHECK-LABEL: @test8(
David Majnemer784d4a42016-02-01 03:29:38 +0000330define void @test8() personality i32 (...)* @__CxxFrameHandler3 { entry:
David Majnemer83f4bb22015-08-17 20:56:39 +0000331 invoke void @f()
332 to label %done unwind label %cleanup1
333 invoke void @f()
334 to label %done unwind label %cleanup2
335
336done:
337 ret void
338
339cleanup1:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000340 ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []
David Majnemer3bb88c02015-12-15 21:27:27 +0000341 ; CHECK-NEXT: call void @llvm.bar()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000342 ; CHECK-NEXT: cleanupret from [[CleanupPad1]]
343 %cp0 = cleanuppad within none []
David Majnemer83f4bb22015-08-17 20:56:39 +0000344 br label %cleanupexit
345
346cleanup2:
David Majnemer8a1c45d2015-12-12 05:38:55 +0000347 ; CHECK: cleanuppad within none []
David Majnemer3bb88c02015-12-15 21:27:27 +0000348 ; CHECK-NEXT: call void @llvm.bar()
David Majnemer83f4bb22015-08-17 20:56:39 +0000349 ; CHECK-NEXT: unreachable
David Majnemer8a1c45d2015-12-12 05:38:55 +0000350 %cp1 = cleanuppad within none []
David Majnemer83f4bb22015-08-17 20:56:39 +0000351 br label %cleanupexit
352
353cleanupexit:
David Majnemer3bb88c02015-12-15 21:27:27 +0000354 call void @llvm.bar()
David Majnemer8a1c45d2015-12-12 05:38:55 +0000355 cleanupret from %cp0 unwind label %cleanup2
David Majnemer83f4bb22015-08-17 20:56:39 +0000356}