Added back in the test for arc-annotations.
[oota-llvm.git] / test / Transforms / ObjCARC / arc-annotations.ll
1 ; This file consists of various tests which ensure that the objc-arc-annotations
2 ; are working correctly. In the future, I will use this in other lit tests to
3 ; check the data flow analysis of ARC.
4
5 ; REQUIRES: asserts
6 ; RUN: opt -S -objc-arc -enable-objc-arc-annotations < %s | FileCheck %s
7
8 declare i8* @objc_retain(i8*)
9 declare i8* @objc_retainAutoreleasedReturnValue(i8*)
10 declare void @objc_release(i8*)
11 declare i8* @objc_autorelease(i8*)
12 declare i8* @objc_autoreleaseReturnValue(i8*)
13 declare void @objc_autoreleasePoolPop(i8*)
14 declare i8* @objc_autoreleasePoolPush()
15 declare i8* @objc_retainBlock(i8*)
16
17 declare i8* @objc_retainedObject(i8*)
18 declare i8* @objc_unretainedObject(i8*)
19 declare i8* @objc_unretainedPointer(i8*)
20
21 declare void @use_pointer(i8*)
22 declare void @callee()
23 declare void @callee_fnptr(void ()*)
24 declare void @invokee()
25 declare i8* @returner()
26
27 ; Simple retain+release pair deletion, with some intervening control
28 ; flow and harmless instructions.
29
30 ; CHECK: define void @test0(
31 ; CHECK: entry:
32 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
33 ; CHECK:   %0 = tail call i8* @objc_retain(i8* %a) #0, !llvm.arc.annotation.bottomup !0, !llvm.arc.annotation.topdown !1
34 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Use)
35 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
36 ; CHECK: t:
37 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
38 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
39 ; CHECK:   store float 2.000000e+00, float* %b, !llvm.arc.annotation.bottomup !2
40 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
41 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
42 ; CHECK: f:
43 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
44 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
45 ; CHECK:   store i32 7, i32* %x, !llvm.arc.annotation.bottomup !2
46 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
47 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
48 ; CHECK: return:
49 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
50 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Release)
51 ; CHECK:   call void @objc_release(i8* %c) #0, !llvm.arc.annotation.bottomup !3, !llvm.arc.annotation.topdown !4
52 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
53 ; CHECK: }
54 define void @test0(i32* %x, i1 %p) nounwind {
55 entry:
56   %a = bitcast i32* %x to i8*
57   %0 = call i8* @objc_retain(i8* %a) nounwind
58   br i1 %p, label %t, label %f
59
60 t:
61   store i8 3, i8* %a
62   %b = bitcast i32* %x to float*
63   store float 2.0, float* %b
64   br label %return
65
66 f:
67   store i32 7, i32* %x
68   br label %return
69
70 return:
71   %c = bitcast i32* %x to i8*
72   call void @objc_release(i8* %c) nounwind
73   ret void
74 }
75
76 ; Like test0 but the release isn't always executed when the retain is,
77 ; so the optimization is not safe.
78
79 ; TODO: Make the objc_release's argument be %0.
80
81 ; CHECK: define void @test1(
82 ; CHECK: entry:
83 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
84 ; CHECK:   %0 = tail call i8* @objc_retain(i8* %a) #0, !llvm.arc.annotation.bottomup !5, !llvm.arc.annotation.topdown !6
85 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_None)
86 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
87 ; CHECK: t:
88 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
89 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
90 ; CHECK:   store float 2.000000e+00, float* %b, !llvm.arc.annotation.bottomup !7
91 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
92 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
93 ; CHECK: f:
94 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
95 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
96 ; CHECK:   call void @callee(), !llvm.arc.annotation.topdown !8
97 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_None)
98 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_CanRelease)
99 ; CHECK: return:
100 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_None)
101 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Release)
102 ; CHECK:   call void @objc_release(i8* %c) #0, !llvm.arc.annotation.bottomup !9
103 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
104 ; CHECK: alt_return:
105 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_None)
106 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
107 ; CHECK: }
108 define void @test1(i32* %x, i1 %p, i1 %q) nounwind {
109 entry:
110   %a = bitcast i32* %x to i8*
111   %0 = call i8* @objc_retain(i8* %a) nounwind
112   br i1 %p, label %t, label %f
113
114 t:
115   store i8 3, i8* %a
116   %b = bitcast i32* %x to float*
117   store float 2.0, float* %b
118   br label %return
119
120 f:
121   store i32 7, i32* %x
122   call void @callee()
123   br i1 %q, label %return, label %alt_return
124
125 return:
126   %c = bitcast i32* %x to i8*
127   call void @objc_release(i8* %c) nounwind
128   ret void
129
130 alt_return:
131   ret void
132 }
133
134 ; Don't do partial elimination into two different CFG diamonds.
135
136 ; CHECK: define void @test1b(
137 ; CHECK: entry:
138 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
139 ; CHECK:   %0 = tail call i8* @objc_retain(i8* %x) #0, !llvm.arc.annotation.bottomup !10, !llvm.arc.annotation.topdown !11
140 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_None)
141 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
142 ; CHECK: if.then:
143 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
144 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_CanRelease)
145 ; CHECK:   tail call void @callee(), !llvm.arc.annotation.bottomup !12, !llvm.arc.annotation.topdown !13
146 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Use)
147 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_CanRelease)
148 ; CHECK: if.end:
149 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_CanRelease)
150 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
151 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Use)
152 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_CanRelease)
153 ; CHECK: if.then3:
154 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_CanRelease)
155 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
156 ; CHECK:   tail call void @use_pointer(i8* %x), !llvm.arc.annotation.bottomup !14, !llvm.arc.annotation.topdown !15
157 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_MovableRelease)
158 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Use)
159 ; CHECK: if.end5:
160 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_None)
161 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_MovableRelease)
162 ; CHECK:   tail call void @objc_release(i8* %x) #0, !clang.imprecise_release !16, !llvm.arc.annotation.bottomup !17
163 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
164 ; CHECK: }
165 define void @test1b(i8* %x, i1 %p, i1 %q) {
166 entry:
167   tail call i8* @objc_retain(i8* %x) nounwind
168   br i1 %p, label %if.then, label %if.end
169
170 if.then:                                          ; preds = %entry
171   tail call void @callee()
172   br label %if.end
173
174 if.end:                                           ; preds = %if.then, %entry
175   br i1 %q, label %if.then3, label %if.end5
176
177 if.then3:                                         ; preds = %if.end
178   tail call void @use_pointer(i8* %x)
179   br label %if.end5
180
181 if.end5:                                          ; preds = %if.then3, %if.end
182   tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0
183   ret void
184 }
185
186 ; Like test0 but the pointer is passed to an intervening call,
187 ; so the optimization is not safe.
188
189 ; CHECK: define void @test2(
190 ; CHECK: entry:
191 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
192 ; CHECK:   %e = tail call i8* @objc_retain(i8* %a) #0, !llvm.arc.annotation.bottomup !18, !llvm.arc.annotation.topdown !19
193 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_CanRelease)
194 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
195 ; CHECK: t:
196 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
197 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Use)
198 ; CHECK:   store float 2.000000e+00, float* %b, !llvm.arc.annotation.bottomup !20
199 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
200 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
201 ; CHECK: f:
202 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
203 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_CanRelease)
204 ; CHECK:   call void @use_pointer(i8* %e), !llvm.arc.annotation.bottomup !21, !llvm.arc.annotation.topdown !22
205 ; CHECK:   store float 3.000000e+00, float* %d, !llvm.arc.annotation.bottomup !20, !llvm.arc.annotation.topdown !23
206 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
207 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Use)
208 ; CHECK: return:
209 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Use)
210 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Release)
211 ; CHECK:   call void @objc_release(i8* %c) #0, !llvm.arc.annotation.bottomup !24, !llvm.arc.annotation.topdown !25
212 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
213 ; CHECK: }
214 define void @test2(i32* %x, i1 %p) nounwind {
215 entry:
216   %a = bitcast i32* %x to i8*
217   %e = call i8* @objc_retain(i8* %a) nounwind
218   br i1 %p, label %t, label %f
219
220 t:
221   store i8 3, i8* %a
222   %b = bitcast i32* %x to float*
223   store float 2.0, float* %b
224   br label %return
225
226 f:
227   store i32 7, i32* %x
228   call void @use_pointer(i8* %e)
229   %d = bitcast i32* %x to float*
230   store float 3.0, float* %d
231   br label %return
232
233 return:
234   %c = bitcast i32* %x to i8*
235   call void @objc_release(i8* %c) nounwind
236   ret void
237 }
238
239 ; Like test0 but the release is in a loop,
240 ; so the optimization is not safe.
241
242 ; TODO: For now, assume this can't happen.
243
244 ; CHECK: define void @test3(
245 ; CHECK: entry:
246 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_None)
247 ; CHECK:   tail call i8* @objc_retain(i8* %a) #0, !llvm.arc.annotation.bottomup !26, !llvm.arc.annotation.topdown !27
248 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbend(i8** @x, i8** @S_Release)
249 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_Retain)
250 ; CHECK: loop:
251 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_Retain)
252 ; CHECK:   call void @llvm.arc.annotation.bottomup.bbstart(i8** @x, i8** @S_Release)
253 ; CHECK:   call void @objc_release(i8* %c) #0, !llvm.arc.annotation.bottomup !28, !llvm.arc.annotation.topdown !29
254 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
255 ; CHECK: return:
256 ; CHECK:   call void @llvm.arc.annotation.topdown.bbstart(i8** @x, i8** @S_None)
257 ; CHECK:   call void @llvm.arc.annotation.topdown.bbend(i8** @x, i8** @S_None)
258 ; CHECK: }
259 define void @test3(i32* %x, i1* %q) nounwind {
260 entry:
261   %a = bitcast i32* %x to i8*
262   %0 = call i8* @objc_retain(i8* %a) nounwind
263   br label %loop
264
265 loop:
266   %c = bitcast i32* %x to i8*
267   call void @objc_release(i8* %c) nounwind
268   %j = load volatile i1* %q
269   br i1 %j, label %loop, label %return
270
271 return:
272   ret void
273 }
274
275 !0 = metadata !{}
276
277 ; CHECK: !0 = metadata !{metadata !"(test0,%x)", metadata !"S_Use", metadata !"S_None"}
278 ; CHECK: !1 = metadata !{metadata !"(test0,%x)", metadata !"S_None", metadata !"S_Retain"}
279 ; CHECK: !2 = metadata !{metadata !"(test0,%x)", metadata !"S_Release", metadata !"S_Use"}
280 ; CHECK: !3 = metadata !{metadata !"(test0,%x)", metadata !"S_None", metadata !"S_Release"}
281 ; CHECK: !4 = metadata !{metadata !"(test0,%x)", metadata !"S_Retain", metadata !"S_None"}
282 ; CHECK: !5 = metadata !{metadata !"(test1,%x)", metadata !"S_None", metadata !"S_None"}
283 ; CHECK: !6 = metadata !{metadata !"(test1,%x)", metadata !"S_None", metadata !"S_Retain"}
284 ; CHECK: !7 = metadata !{metadata !"(test1,%x)", metadata !"S_Release", metadata !"S_Use"}
285 ; CHECK: !8 = metadata !{metadata !"(test1,%x)", metadata !"S_Retain", metadata !"S_CanRelease"}
286 ; CHECK: !9 = metadata !{metadata !"(test1,%x)", metadata !"S_None", metadata !"S_Release"}
287 ; CHECK: !10 = metadata !{metadata !"(test1b,%x)", metadata !"S_None", metadata !"S_None"}
288 ; CHECK: !11 = metadata !{metadata !"(test1b,%x)", metadata !"S_None", metadata !"S_Retain"}
289 ; CHECK: !12 = metadata !{metadata !"(test1b,%x)", metadata !"S_Use", metadata !"S_CanRelease"}
290 ; CHECK: !13 = metadata !{metadata !"(test1b,%x)", metadata !"S_Retain", metadata !"S_CanRelease"}
291 ; CHECK: !14 = metadata !{metadata !"(test1b,%x)", metadata !"S_MovableRelease", metadata !"S_Use"}
292 ; CHECK: !15 = metadata !{metadata !"(test1b,%x)", metadata !"S_CanRelease", metadata !"S_Use"}
293 ; CHECK: !16 = metadata !{}
294 ; CHECK: !17 = metadata !{metadata !"(test1b,%x)", metadata !"S_None", metadata !"S_MovableRelease"}
295 ; CHECK: !18 = metadata !{metadata !"(test2,%x)", metadata !"S_CanRelease", metadata !"S_None"}
296 ; CHECK: !19 = metadata !{metadata !"(test2,%x)", metadata !"S_None", metadata !"S_Retain"}
297 ; CHECK: !20 = metadata !{metadata !"(test2,%x)", metadata !"S_Release", metadata !"S_Use"}
298 ; CHECK: !21 = metadata !{metadata !"(test2,%x)", metadata !"S_Use", metadata !"S_CanRelease"}
299 ; CHECK: !22 = metadata !{metadata !"(test2,%x)", metadata !"S_Retain", metadata !"S_CanRelease"}
300 ; CHECK: !23 = metadata !{metadata !"(test2,%x)", metadata !"S_CanRelease", metadata !"S_Use"}
301 ; CHECK: !24 = metadata !{metadata !"(test2,%x)", metadata !"S_None", metadata !"S_Release"}
302 ; CHECK: !25 = metadata !{metadata !"(test2,%x)", metadata !"S_Use", metadata !"S_None"}
303 ; CHECK: !26 = metadata !{metadata !"(test3,%x)", metadata !"S_Release", metadata !"S_None"}
304 ; CHECK: !27 = metadata !{metadata !"(test3,%x)", metadata !"S_None", metadata !"S_Retain"}
305 ; CHECK: !28 = metadata !{metadata !"(test3,%x)", metadata !"S_None", metadata !"S_Release"}
306 ; CHECK: !29 = metadata !{metadata !"(test3,%x)", metadata !"S_Retain", metadata !"S_None"}
307