SimplifyCFG: don't remove unreachable default switch destinations
[oota-llvm.git] / test / Transforms / ObjCARC / invoke.ll
1 ; RUN: opt -S -objc-arc < %s | FileCheck %s
2
3 declare i8* @objc_retain(i8*)
4 declare void @objc_release(i8*)
5 declare i8* @objc_retainAutoreleasedReturnValue(i8*)
6 declare i8* @objc_msgSend(i8*, i8*, ...)
7 declare void @use_pointer(i8*)
8 declare void @callee()
9 declare i8* @returner()
10
11 ; ARCOpt shouldn't try to move the releases to the block containing the invoke.
12
13 ; CHECK-LABEL: define void @test0(
14 ; CHECK: invoke.cont:
15 ; CHECK:   call void @objc_release(i8* %zipFile) [[NUW:#[0-9]+]], !clang.imprecise_release !0
16 ; CHECK:   ret void
17 ; CHECK: lpad:
18 ; CHECK:   call void @objc_release(i8* %zipFile) [[NUW]], !clang.imprecise_release !0
19 ; CHECK:   ret void
20 ; CHECK-NEXT: }
21 define void @test0(i8* %zipFile) {
22 entry:
23   call i8* @objc_retain(i8* %zipFile) nounwind
24   call void @use_pointer(i8* %zipFile)
25   invoke void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*)*)(i8* %zipFile) 
26           to label %invoke.cont unwind label %lpad
27
28 invoke.cont:                                      ; preds = %entry
29   call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
30   ret void
31
32 lpad:                                             ; preds = %entry
33   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
34            cleanup
35   call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
36   ret void
37 }
38
39 ; ARCOpt should move the release before the callee calls.
40
41 ; CHECK-LABEL: define void @test1(
42 ; CHECK: invoke.cont:
43 ; CHECK:   call void @objc_release(i8* %zipFile) [[NUW]], !clang.imprecise_release !0
44 ; CHECK:   call void @callee()
45 ; CHECK:   br label %done
46 ; CHECK: lpad:
47 ; CHECK:   call void @objc_release(i8* %zipFile) [[NUW]], !clang.imprecise_release !0
48 ; CHECK:   call void @callee()
49 ; CHECK:   br label %done
50 ; CHECK: done:
51 ; CHECK-NEXT: ret void
52 ; CHECK-NEXT: }
53 define void @test1(i8* %zipFile) {
54 entry:
55   call i8* @objc_retain(i8* %zipFile) nounwind
56   call void @use_pointer(i8* %zipFile)
57   invoke void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*)*)(i8* %zipFile)
58           to label %invoke.cont unwind label %lpad
59
60 invoke.cont:                                      ; preds = %entry
61   call void @callee()
62   br label %done
63
64 lpad:                                             ; preds = %entry
65   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
66            cleanup
67   call void @callee()
68   br label %done
69
70 done:
71   call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
72   ret void
73 }
74
75 ; The optimizer should ignore invoke unwind paths consistently.
76 ; PR12265
77
78 ; CHECK: define void @test2() {
79 ; CHECK: invoke.cont:
80 ; CHECK-NEXT: call i8* @objc_retain
81 ; CHECK-NOT: @objc_r
82 ; CHECK: finally.cont:
83 ; CHECK-NEXT: call void @objc_release
84 ; CHECK-NOT: @objc
85 ; CHECK: finally.rethrow:
86 ; CHECK-NOT: @objc
87 ; CHECK: }
88 define void @test2() {
89 entry:
90   %call = invoke i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* ()*)()
91           to label %invoke.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
92
93 invoke.cont:                                      ; preds = %entry
94   %tmp1 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
95   call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void ()*)(), !clang.arc.no_objc_arc_exceptions !0
96   invoke void @use_pointer(i8* %call)
97           to label %finally.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
98
99 finally.cont:                                     ; preds = %invoke.cont
100   tail call void @objc_release(i8* %call) nounwind, !clang.imprecise_release !0
101   ret void
102
103 finally.rethrow:                                  ; preds = %invoke.cont, %entry
104   %tmp2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
105           catch i8* null
106   unreachable
107 }
108
109 ; Don't try to place code on invoke critical edges.
110
111 ; CHECK-LABEL: define void @test3(
112 ; CHECK: if.end:
113 ; CHECK-NEXT: call void @objc_release(i8* %p) [[NUW]]
114 ; CHECK-NEXT: ret void
115 ; CHECK-NEXT: }
116 define void @test3(i8* %p, i1 %b) {
117 entry:
118   %0 = call i8* @objc_retain(i8* %p)
119   call void @callee()
120   br i1 %b, label %if.else, label %if.then
121
122 if.then:
123   invoke void @use_pointer(i8* %p)
124           to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
125
126 if.else:
127   invoke void @use_pointer(i8* %p)
128           to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
129
130 lpad:
131   %r = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
132        cleanup
133   ret void
134
135 if.end:
136   call void @objc_release(i8* %p)
137   ret void
138 }
139
140 ; Like test3, but with ARC-relevant exception handling.
141
142 ; CHECK-LABEL: define void @test4(
143 ; CHECK: lpad:
144 ; CHECK-NEXT: %r = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
145 ; CHECK-NEXT: cleanup
146 ; CHECK-NEXT: call void @objc_release(i8* %p) [[NUW]]
147 ; CHECK-NEXT: ret void
148 ; CHECK: if.end:
149 ; CHECK-NEXT: call void @objc_release(i8* %p) [[NUW]]
150 ; CHECK-NEXT: ret void
151 ; CHECK-NEXT: }
152 define void @test4(i8* %p, i1 %b) {
153 entry:
154   %0 = call i8* @objc_retain(i8* %p)
155   call void @callee()
156   br i1 %b, label %if.else, label %if.then
157
158 if.then:
159   invoke void @use_pointer(i8* %p)
160           to label %if.end unwind label %lpad
161
162 if.else:
163   invoke void @use_pointer(i8* %p)
164           to label %if.end unwind label %lpad
165
166 lpad:
167   %r = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
168        cleanup
169   call void @objc_release(i8* %p)
170   ret void
171
172 if.end:
173   call void @objc_release(i8* %p)
174   ret void
175 }
176
177 ; Don't turn the retainAutoreleaseReturnValue into retain, because it's
178 ; for an invoke which we can assume codegen will put immediately prior.
179
180 ; CHECK-LABEL: define void @test5(
181 ; CHECK: call i8* @objc_retainAutoreleasedReturnValue(i8* %z)
182 ; CHECK: }
183 define void @test5() {
184 entry:
185   %z = invoke i8* @returner()
186           to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
187
188 lpad:
189   %r13 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
190           cleanup
191   ret void
192
193 if.end:
194   call i8* @objc_retainAutoreleasedReturnValue(i8* %z)
195   ret void
196 }
197
198 ; Like test5, but there's intervening code.
199
200 ; CHECK-LABEL: define void @test6(
201 ; CHECK: call i8* @objc_retain(i8* %z)
202 ; CHECK: }
203 define void @test6() {
204 entry:
205   %z = invoke i8* @returner()
206           to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
207
208 lpad:
209   %r13 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
210           cleanup
211   ret void
212
213 if.end:
214   call void @callee()
215   call i8* @objc_retainAutoreleasedReturnValue(i8* %z)
216   ret void
217 }
218
219 declare i32 @__gxx_personality_v0(...)
220 declare i32 @__objc_personality_v0(...)
221
222 ; CHECK: attributes [[NUW]] = { nounwind }
223
224 !0 = !{}