[IR] Reformulate LLVM's EH funclet IR
[oota-llvm.git] / test / CodeGen / WinEH / wineh-no-demotion.ll
1 ; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare -disable-demotion < %s | FileCheck %s
2
3 declare i32 @__CxxFrameHandler3(...)
4
5 declare i32 @__C_specific_handler(...)
6
7 declare void @f()
8
9 declare i32 @g()
10
11 declare void @h(i32)
12
13 ; CHECK-LABEL: @test1(
14 define void @test1() personality i32 (...)* @__C_specific_handler {
15 entry:
16   invoke void @f()
17           to label %invoke.cont1 unwind label %left
18
19 invoke.cont1:
20   invoke void @f()
21           to label %invoke.cont2 unwind label %right
22
23 invoke.cont2:
24   invoke void @f()
25           to label %exit unwind label %inner
26
27 left:
28   %0 = cleanuppad within none []
29   br label %shared
30
31 right:
32   %1 = cleanuppad within none []
33   br label %shared
34
35 shared:
36   %x = call i32 @g()
37   invoke void @f()
38           to label %shared.cont unwind label %inner
39
40 shared.cont:
41   unreachable
42
43 inner:
44   %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont2 ]
45   %i = cleanuppad within none []
46   call void @h(i32 %phi)
47   unreachable
48
49 ; CHECK: %phi = phi i32 [ %x, %right ], [ 0, %invoke.cont2 ], [ %x.for.left, %left ]
50 ; CHECK: %i = cleanuppad within none []
51 ; CHECK: call void @h(i32 %phi)
52
53 exit:
54   unreachable
55 }
56
57 ; CHECK-LABEL: @test2(
58 define void @test2() personality i32 (...)* @__C_specific_handler {
59 entry:
60   invoke void @f()
61           to label %invoke.cont unwind label %left
62
63 invoke.cont:
64   invoke void @f()
65           to label %exit unwind label %right
66
67 left:
68   cleanuppad within none []
69   br label %shared
70
71 right:
72   cleanuppad within none []
73   br label %shared
74
75 shared:
76   %x = call i32 @g()
77   invoke void @f()
78           to label %shared.cont unwind label %inner
79
80 shared.cont:
81   unreachable
82
83 inner:
84   %i = cleanuppad within none []
85   call void @h(i32 %x)
86   unreachable
87
88 ; CHECK:  %x1 = phi i32 [ %x.for.left, %left ], [ %x, %right ]
89 ; CHECK:  %i = cleanuppad within none []
90 ; CHECK:  call void @h(i32 %x1)
91
92 exit:
93   unreachable
94 }
95
96 ; CHECK-LABEL: @test3(
97 define void @test3() personality i32 (...)* @__CxxFrameHandler3 {
98 entry:
99   invoke void @f()
100           to label %invoke.cont unwind label %terminate
101
102 invoke.cont:
103   ret void
104
105 terminate:
106 ; CHECK:  cleanuppad within none []
107 ; CHECK:  call void @__std_terminate()
108 ; CHECK:  unreachable
109   terminatepad within none [void ()* @__std_terminate] unwind to caller
110 }
111
112 ; CHECK-LABEL: @test4(
113 define void @test4(i1 %x) personality i32 (...)* @__CxxFrameHandler3 {
114 entry:
115   invoke void @f()
116           to label %invoke.cont1 unwind label %left
117
118 invoke.cont1:
119   invoke void @f()
120           to label %exit unwind label %right
121
122 left:
123   %0 = cleanuppad within none []
124   br label %shared
125
126 right:
127   %1 = cleanuppad within none []
128   br i1 %x, label %shared, label %right.other
129
130 right.other:
131   br label %shared
132
133 shared:
134   %phi = phi i32 [ 1, %left ], [ 0, %right ], [ -1, %right.other ]
135   call void @h(i32 %phi)
136   unreachable
137
138 ; CHECK: %0 = cleanuppad within none []
139 ; CHECK: call void @h(i32 1)
140
141 ; CHECK: %1 = cleanuppad within none []
142 ; CHECK: %phi = phi i32 [ 0, %right ], [ -1, %right.other ]
143 ; CHECK: call void @h(i32 %phi)
144
145 exit:
146   unreachable
147 }
148
149 declare void @__std_terminate()