blob: 76e82a587b8d8086e1043bbca35fcccebe42b608 [file] [log] [blame]
Dan Gohman00fa9632011-06-16 20:57:14 +00001; RUN: opt -S -objc-arc < %s | FileCheck %s
2
3declare i8* @objc_retain(i8*)
4declare void @objc_release(i8*)
Dan Gohman532fb812012-03-14 23:05:06 +00005declare i8* @objc_retainAutoreleasedReturnValue(i8*)
Dan Gohman00fa9632011-06-16 20:57:14 +00006declare i8* @objc_msgSend(i8*, i8*, ...)
7declare void @use_pointer(i8*)
8declare void @callee()
Dan Gohmane3ed2b02012-03-23 18:09:00 +00009declare i8* @returner()
Dan Gohman00fa9632011-06-16 20:57:14 +000010
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
20define void @test0(i8* %zipFile) {
21entry:
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
27invoke.cont: ; preds = %entry
28 call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
29 ret void
30
31lpad: ; preds = %entry
Bill Wendlinge6174a22011-08-31 21:04:11 +000032 %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
33 cleanup
Dan Gohman00fa9632011-06-16 20:57:14 +000034 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
51define void @test1(i8* %zipFile) {
52entry:
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
58invoke.cont: ; preds = %entry
59 call void @callee()
60 br label %done
61
62lpad: ; preds = %entry
Bill Wendlinge6174a22011-08-31 21:04:11 +000063 %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
64 cleanup
Dan Gohman00fa9632011-06-16 20:57:14 +000065 call void @callee()
66 br label %done
67
68done:
69 call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
70 ret void
71}
72
Dan Gohman532fb812012-03-14 23:05:06 +000073; 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: }
86define void @test2() {
87entry:
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
91invoke.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
97finally.cont: ; preds = %invoke.cont
98 tail call void @objc_release(i8* %call) nounwind, !clang.imprecise_release !0
99 ret void
100
101finally.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
Dan Gohman5c70fad2012-03-23 17:47:54 +0000107; 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
113define void @test3(i8* %p, i1 %b) {
114entry:
115 %0 = call i8* @objc_retain(i8* %p)
116 call void @callee()
117 br i1 %b, label %if.else, label %if.then
118
119if.then:
120 invoke void @use_pointer(i8* %p)
121 to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
122
123if.else:
124 invoke void @use_pointer(i8* %p)
125 to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
126
127lpad:
128 %r = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
129 cleanup
130 ret void
131
132if.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
148define void @test4(i8* %p, i1 %b) {
149entry:
150 %0 = call i8* @objc_retain(i8* %p)
151 call void @callee()
152 br i1 %b, label %if.else, label %if.then
153
154if.then:
155 invoke void @use_pointer(i8* %p)
156 to label %if.end unwind label %lpad
157
158if.else:
159 invoke void @use_pointer(i8* %p)
160 to label %if.end unwind label %lpad
161
162lpad:
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
168if.end:
169 call void @objc_release(i8* %p)
170 ret void
171}
172
Dan Gohmane3ed2b02012-03-23 18:09:00 +0000173; 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: }
179define void @test5() {
180entry:
181 %z = invoke i8* @returner()
182 to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
183
184lpad:
185 %r13 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
186 cleanup
187 ret void
188
189if.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: }
199define void @test6() {
200entry:
201 %z = invoke i8* @returner()
202 to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
203
204lpad:
205 %r13 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
206 cleanup
207 ret void
208
209if.end:
210 call void @callee()
211 call i8* @objc_retainAutoreleasedReturnValue(i8* %z)
212 ret void
213}
214
Bill Wendlinge6174a22011-08-31 21:04:11 +0000215declare i32 @__gxx_personality_v0(...)
Dan Gohman532fb812012-03-14 23:05:06 +0000216declare i32 @__objc_personality_v0(...)
Bill Wendlinge6174a22011-08-31 21:04:11 +0000217
Dan Gohman00fa9632011-06-16 20:57:14 +0000218!0 = metadata !{}