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