[InstCombine] Signed saturation patterns
[llvm-core.git] / test / CodeGen / WinEH / wineh-demotion.ll
blob411952d84bb6ce3ff3c077641f55e0c0092fc5b8
1 ; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -winehprepare  < %s | FileCheck %s
3 declare i32 @__CxxFrameHandler3(...)
5 declare void @f()
7 declare i32 @g()
9 declare void @h(i32)
11 declare i1 @i()
13 declare void @llvm.bar() nounwind
15 ; CHECK-LABEL: @test1(
16 define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
17 entry:
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
25 left:
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
31 right:
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
37 merge:
38   ; CHECK: merge:
39   ; CHECK-NOT: = phi
40   %phi = phi i32 [ %x, %left ], [ %y, %right ]
41   %cs1 = catchswitch within none [label %catch] unwind to caller
43 catch:
44   %cp = catchpad within %cs1 []
45   ; CHECK: catch:
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
51 exit:
52   ret void
55 ; CHECK-LABEL: @test2(
56 define void @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
57 entry:
58   br i1 %B, label %left, label %right
59 left:
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
67 right:
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
75 merge.inner:
76   ; CHECK: merge.inner:
77   ; CHECK-NOT: = phi
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
82 catch.inner:
83   %cpinner = catchpad within %cs1 []
84   ; Need just one store here because only %y is affected
85   ; CHECK: catch.inner:
86   %z = call i32 @g() [ "funclet"(token %cpinner) ]
87   ; CHECK:   store i32 %z
88   ; CHECK-NEXT: invoke void @f
89   invoke void @f() [ "funclet"(token %cpinner) ]
90           to label %catchret.inner unwind label %merge.outer
92 catchret.inner:
93   catchret from %cpinner to label %exit
95 merge.outer:
96   %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ]
97   ; CHECK: merge.outer:
98   ; CHECK-NOT: = phi
99   ; CHECK: catchswitch within none
100   %cs2 = catchswitch within none [label %catch.outer] unwind to caller
102 catch.outer:
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
115 exit:
116   ret void
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 {
123 entry:
124   ; CHECK:      entry:
125   ; CHECK:        [[Slot:%[^ ]+]] = alloca
126   ; CHECK-NEXT:   br
127   br i1 %B, label %left, label %right
128 left:
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
136 right:
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
144 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
149 catch.inner:
150    %cp1 = catchpad within %cs1 []
151    catchret from %cp1 to label %join
152 join:
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
161 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
166 catch.outer:
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
173 exit:
174    ret void
177 ; CHECK-LABEL: @test5(
178 define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
179 entry:
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
187 invoke.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
195 cleanup:
196   ; cleanup phi can be loaded at cleanup entry
197   ; CHECK: cleanup:
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
205 left:
206   ; CHECK: left:
207   ; CHECK:   call void @h(i32 [[CleanupReload]]
208   call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
209   br label %merge
211 right:
212   ; CHECK: right:
213   ; CHECK:   call void @h(i32 [[CleanupReload]]
214   call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
215   br label %merge
217 merge:
218   ; need store for %phi.catch
219   ; CHECK:      merge:
220   ; CHECK-NEXT:   store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
221   ; CHECK-NEXT:   cleanupret
222   cleanupret from %cp unwind label %catchswitch
224 invoke.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()
230           to label %exit unwind label %catchswitch
232 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
238 catch:
239   ; CHECK: catch:
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
247 exit:
248   ret void
251 ; We used to demote %x, but we don't need to anymore.
252 ; CHECK-LABEL: @test6(
253 define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
254 entry:
255   ; CHECK: entry:
256   ; CHECK: %x = invoke i32 @g()
257   ; CHECK-NEXT: to label %loop unwind label %to_caller
258   %x = invoke i32 @g()
259           to label %loop unwind label %to_caller
260 to_caller:
261   %cp1 = cleanuppad within none []
262   cleanupret from %cp1 unwind to caller
263 loop:
264   invoke void @f()
265           to label %loop unwind label %cleanup
266 cleanup:
267   ; CHECK: 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 {
276 entry:
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
283 invoke.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
290 catchpad:
291   ; %x phi should be eliminated
292   ; CHECK: catchpad:
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
296 catch:
297   ; CHECK: catch:
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
302 left:
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:
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
311 right:
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:
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
319 join:
320   ; CHECK: join:
321   ; CHECK:   %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ]
322   %phi = phi i32 [ %x, %left ], [ %y, %right ]
323   call void @h(i32 %phi)
324   br label %exit
325 exit:
326   ret void
329 ; CHECK-LABEL: @test8(
330 define void @test8() personality i32 (...)* @__CxxFrameHandler3 { entry:
331   invoke void @f()
332           to label %done unwind label %cleanup1
333   invoke void @f()
334           to label %done unwind label %cleanup2
336 done:
337   ret void
339 cleanup1:
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
346 cleanup2:
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
353 cleanupexit:
354   call void @llvm.bar()
355   cleanupret from %cp0 unwind label %cleanup2