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