xref: /aosp_15_r20/external/llvm/test/Transforms/ObjCARC/contract.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker
3*9880d681SAndroid Build Coastguard Workertarget datalayout = "e-p:64:64:64"
4*9880d681SAndroid Build Coastguard Worker
5*9880d681SAndroid Build Coastguard Workerdeclare i8* @objc_retain(i8*)
6*9880d681SAndroid Build Coastguard Workerdeclare void @objc_release(i8*)
7*9880d681SAndroid Build Coastguard Workerdeclare i8* @objc_autorelease(i8*)
8*9880d681SAndroid Build Coastguard Workerdeclare i8* @objc_autoreleaseReturnValue(i8*)
9*9880d681SAndroid Build Coastguard Workerdeclare i8* @objc_retainAutoreleasedReturnValue(i8*)
10*9880d681SAndroid Build Coastguard Worker
11*9880d681SAndroid Build Coastguard Workerdeclare void @use_pointer(i8*)
12*9880d681SAndroid Build Coastguard Workerdeclare i8* @returner()
13*9880d681SAndroid Build Coastguard Workerdeclare void @callee()
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test0(
16*9880d681SAndroid Build Coastguard Worker; CHECK: call void @use_pointer(i8* %0)
17*9880d681SAndroid Build Coastguard Worker; CHECK: }
18*9880d681SAndroid Build Coastguard Workerdefine void @test0(i8* %x) nounwind {
19*9880d681SAndroid Build Coastguard Workerentry:
20*9880d681SAndroid Build Coastguard Worker  %0 = call i8* @objc_retain(i8* %x) nounwind
21*9880d681SAndroid Build Coastguard Worker  call void @use_pointer(i8* %x)
22*9880d681SAndroid Build Coastguard Worker  ret void
23*9880d681SAndroid Build Coastguard Worker}
24*9880d681SAndroid Build Coastguard Worker
25*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test1(
26*9880d681SAndroid Build Coastguard Worker; CHECK: call void @use_pointer(i8* %0)
27*9880d681SAndroid Build Coastguard Worker; CHECK: }
28*9880d681SAndroid Build Coastguard Workerdefine void @test1(i8* %x) nounwind {
29*9880d681SAndroid Build Coastguard Workerentry:
30*9880d681SAndroid Build Coastguard Worker  %0 = call i8* @objc_autorelease(i8* %x) nounwind
31*9880d681SAndroid Build Coastguard Worker  call void @use_pointer(i8* %x)
32*9880d681SAndroid Build Coastguard Worker  ret void
33*9880d681SAndroid Build Coastguard Worker}
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker; Merge objc_retain and objc_autorelease into objc_retainAutorelease.
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test2(
38*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retainAutorelease(i8* %x) [[NUW:#[0-9]+]]
39*9880d681SAndroid Build Coastguard Worker; CHECK: }
40*9880d681SAndroid Build Coastguard Workerdefine void @test2(i8* %x) nounwind {
41*9880d681SAndroid Build Coastguard Workerentry:
42*9880d681SAndroid Build Coastguard Worker  %0 = tail call i8* @objc_retain(i8* %x) nounwind
43*9880d681SAndroid Build Coastguard Worker  call i8* @objc_autorelease(i8* %0) nounwind
44*9880d681SAndroid Build Coastguard Worker  call void @use_pointer(i8* %x)
45*9880d681SAndroid Build Coastguard Worker  ret void
46*9880d681SAndroid Build Coastguard Worker}
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker; Same as test2 but the value is returned. Do an RV optimization.
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i8* @test2b(
51*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retainAutoreleaseReturnValue(i8* %x) [[NUW]]
52*9880d681SAndroid Build Coastguard Worker; CHECK: }
53*9880d681SAndroid Build Coastguard Workerdefine i8* @test2b(i8* %x) nounwind {
54*9880d681SAndroid Build Coastguard Workerentry:
55*9880d681SAndroid Build Coastguard Worker  %0 = tail call i8* @objc_retain(i8* %x) nounwind
56*9880d681SAndroid Build Coastguard Worker  tail call i8* @objc_autoreleaseReturnValue(i8* %0) nounwind
57*9880d681SAndroid Build Coastguard Worker  ret i8* %x
58*9880d681SAndroid Build Coastguard Worker}
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker; Merge a retain,autorelease pair around a call.
61*9880d681SAndroid Build Coastguard Worker
62*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test3(
63*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retainAutorelease(i8* %x) [[NUW]]
64*9880d681SAndroid Build Coastguard Worker; CHECK: @use_pointer(i8* %0)
65*9880d681SAndroid Build Coastguard Worker; CHECK: }
66*9880d681SAndroid Build Coastguard Workerdefine void @test3(i8* %x, i64 %n) {
67*9880d681SAndroid Build Coastguard Workerentry:
68*9880d681SAndroid Build Coastguard Worker  tail call i8* @objc_retain(i8* %x) nounwind
69*9880d681SAndroid Build Coastguard Worker  call void @use_pointer(i8* %x)
70*9880d681SAndroid Build Coastguard Worker  call i8* @objc_autorelease(i8* %x) nounwind
71*9880d681SAndroid Build Coastguard Worker  ret void
72*9880d681SAndroid Build Coastguard Worker}
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker; Trivial retain,autorelease pair with intervening call, but it's post-dominated
75*9880d681SAndroid Build Coastguard Worker; by another release. The retain and autorelease can be merged.
76*9880d681SAndroid Build Coastguard Worker
77*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test4(
78*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: entry:
79*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: @objc_retainAutorelease(i8* %x) [[NUW]]
80*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: @use_pointer
81*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: @objc_release
82*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret void
83*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: }
84*9880d681SAndroid Build Coastguard Workerdefine void @test4(i8* %x, i64 %n) {
85*9880d681SAndroid Build Coastguard Workerentry:
86*9880d681SAndroid Build Coastguard Worker  tail call i8* @objc_retain(i8* %x) nounwind
87*9880d681SAndroid Build Coastguard Worker  call void @use_pointer(i8* %x)
88*9880d681SAndroid Build Coastguard Worker  call i8* @objc_autorelease(i8* %x) nounwind
89*9880d681SAndroid Build Coastguard Worker  tail call void @objc_release(i8* %x) nounwind
90*9880d681SAndroid Build Coastguard Worker  ret void
91*9880d681SAndroid Build Coastguard Worker}
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker; Don't merge retain and autorelease if they're not control-equivalent.
94*9880d681SAndroid Build Coastguard Worker
95*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test5(
96*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retain(i8* %p) [[NUW]]
97*9880d681SAndroid Build Coastguard Worker; CHECK: true:
98*9880d681SAndroid Build Coastguard Worker; CHECK: call i8* @objc_autorelease(i8* %0) [[NUW]]
99*9880d681SAndroid Build Coastguard Worker; CHECK: }
100*9880d681SAndroid Build Coastguard Workerdefine void @test5(i8* %p, i1 %a) {
101*9880d681SAndroid Build Coastguard Workerentry:
102*9880d681SAndroid Build Coastguard Worker  tail call i8* @objc_retain(i8* %p) nounwind
103*9880d681SAndroid Build Coastguard Worker  br i1 %a, label %true, label %false
104*9880d681SAndroid Build Coastguard Worker
105*9880d681SAndroid Build Coastguard Workertrue:
106*9880d681SAndroid Build Coastguard Worker  call i8* @objc_autorelease(i8* %p) nounwind
107*9880d681SAndroid Build Coastguard Worker  call void @use_pointer(i8* %p)
108*9880d681SAndroid Build Coastguard Worker  ret void
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Workerfalse:
111*9880d681SAndroid Build Coastguard Worker  ret void
112*9880d681SAndroid Build Coastguard Worker}
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker; Don't eliminate objc_retainAutoreleasedReturnValue by merging it into
115*9880d681SAndroid Build Coastguard Worker; an objc_autorelease.
116*9880d681SAndroid Build Coastguard Worker; TODO? Merge objc_retainAutoreleasedReturnValue and objc_autorelease into
117*9880d681SAndroid Build Coastguard Worker; objc_retainAutoreleasedReturnValueAutorelease and merge
118*9880d681SAndroid Build Coastguard Worker; objc_retainAutoreleasedReturnValue and objc_autoreleaseReturnValue
119*9880d681SAndroid Build Coastguard Worker; into objc_retainAutoreleasedReturnValueAutoreleaseReturnValue?
120*9880d681SAndroid Build Coastguard Worker; Those entrypoints don't exist yet though.
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i8* @test6(
123*9880d681SAndroid Build Coastguard Worker; CHECK: call i8* @objc_retainAutoreleasedReturnValue(i8* %p) [[NUW]]
124*9880d681SAndroid Build Coastguard Worker; CHECK: %t = tail call i8* @objc_autoreleaseReturnValue(i8* %1) [[NUW]]
125*9880d681SAndroid Build Coastguard Worker; CHECK: }
126*9880d681SAndroid Build Coastguard Workerdefine i8* @test6() {
127*9880d681SAndroid Build Coastguard Worker  %p = call i8* @returner()
128*9880d681SAndroid Build Coastguard Worker  tail call i8* @objc_retainAutoreleasedReturnValue(i8* %p) nounwind
129*9880d681SAndroid Build Coastguard Worker  %t = tail call i8* @objc_autoreleaseReturnValue(i8* %p) nounwind
130*9880d681SAndroid Build Coastguard Worker  call void @use_pointer(i8* %t)
131*9880d681SAndroid Build Coastguard Worker  ret i8* %t
132*9880d681SAndroid Build Coastguard Worker}
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker; Don't spoil the RV optimization.
135*9880d681SAndroid Build Coastguard Worker
136*9880d681SAndroid Build Coastguard Worker; CHECK: define i8* @test7(i8* %p)
137*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retain(i8* %p)
138*9880d681SAndroid Build Coastguard Worker; CHECK: call void @use_pointer(i8* %1)
139*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %1)
140*9880d681SAndroid Build Coastguard Worker; CHECK: ret i8* %2
141*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: }
142*9880d681SAndroid Build Coastguard Workerdefine i8* @test7(i8* %p) {
143*9880d681SAndroid Build Coastguard Worker  %1 = tail call i8* @objc_retain(i8* %p)
144*9880d681SAndroid Build Coastguard Worker  call void @use_pointer(i8* %p)
145*9880d681SAndroid Build Coastguard Worker  %2 = tail call i8* @objc_autoreleaseReturnValue(i8* %p)
146*9880d681SAndroid Build Coastguard Worker  ret i8* %p
147*9880d681SAndroid Build Coastguard Worker}
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker; Do the return value substitution for PHI nodes too.
150*9880d681SAndroid Build Coastguard Worker
151*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i8* @test8(
152*9880d681SAndroid Build Coastguard Worker; CHECK: %retval = phi i8* [ %p, %if.then ], [ null, %entry ]
153*9880d681SAndroid Build Coastguard Worker; CHECK: }
154*9880d681SAndroid Build Coastguard Workerdefine i8* @test8(i1 %x, i8* %c) {
155*9880d681SAndroid Build Coastguard Workerentry:
156*9880d681SAndroid Build Coastguard Worker  br i1 %x, label %return, label %if.then
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Workerif.then:                                          ; preds = %entry
159*9880d681SAndroid Build Coastguard Worker  %p = call i8* @objc_retain(i8* %c) nounwind
160*9880d681SAndroid Build Coastguard Worker  br label %return
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Workerreturn:                                           ; preds = %if.then, %entry
163*9880d681SAndroid Build Coastguard Worker  %retval = phi i8* [ %c, %if.then ], [ null, %entry ]
164*9880d681SAndroid Build Coastguard Worker  ret i8* %retval
165*9880d681SAndroid Build Coastguard Worker}
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Worker; Kill calls to @clang.arc.use(...)
168*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test9(
169*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: clang.arc.use
170*9880d681SAndroid Build Coastguard Worker; CHECK: }
171*9880d681SAndroid Build Coastguard Workerdefine void @test9(i8* %a, i8* %b) {
172*9880d681SAndroid Build Coastguard Worker  call void (...) @clang.arc.use(i8* %a, i8* %b) nounwind
173*9880d681SAndroid Build Coastguard Worker  ret void
174*9880d681SAndroid Build Coastguard Worker}
175*9880d681SAndroid Build Coastguard Worker
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Worker; Turn objc_retain into objc_retainAutoreleasedReturnValue if its operand
178*9880d681SAndroid Build Coastguard Worker; is a return value.
179*9880d681SAndroid Build Coastguard Worker
180*9880d681SAndroid Build Coastguard Worker; CHECK: define void @test10()
181*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
182*9880d681SAndroid Build Coastguard Workerdefine void @test10() {
183*9880d681SAndroid Build Coastguard Worker  %p = call i8* @returner()
184*9880d681SAndroid Build Coastguard Worker  tail call i8* @objc_retain(i8* %p) nounwind
185*9880d681SAndroid Build Coastguard Worker  ret void
186*9880d681SAndroid Build Coastguard Worker}
187*9880d681SAndroid Build Coastguard Worker
188*9880d681SAndroid Build Coastguard Worker; Convert objc_retain to objc_retainAutoreleasedReturnValue if its
189*9880d681SAndroid Build Coastguard Worker; argument is a return value.
190*9880d681SAndroid Build Coastguard Worker
191*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test11(
192*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %y = call i8* @returner()
193*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %y) [[NUW]]
194*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret void
195*9880d681SAndroid Build Coastguard Workerdefine void @test11() {
196*9880d681SAndroid Build Coastguard Worker  %y = call i8* @returner()
197*9880d681SAndroid Build Coastguard Worker  tail call i8* @objc_retain(i8* %y) nounwind
198*9880d681SAndroid Build Coastguard Worker  ret void
199*9880d681SAndroid Build Coastguard Worker}
200*9880d681SAndroid Build Coastguard Worker
201*9880d681SAndroid Build Coastguard Worker; Don't convert objc_retain to objc_retainAutoreleasedReturnValue if its
202*9880d681SAndroid Build Coastguard Worker; argument is not a return value.
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test12(
205*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: tail call i8* @objc_retain(i8* %y) [[NUW]]
206*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret void
207*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: }
208*9880d681SAndroid Build Coastguard Workerdefine void @test12(i8* %y) {
209*9880d681SAndroid Build Coastguard Worker  tail call i8* @objc_retain(i8* %y) nounwind
210*9880d681SAndroid Build Coastguard Worker  ret void
211*9880d681SAndroid Build Coastguard Worker}
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Worker; Don't Convert objc_retain to objc_retainAutoreleasedReturnValue if it
214*9880d681SAndroid Build Coastguard Worker; isn't next to the call providing its return value.
215*9880d681SAndroid Build Coastguard Worker
216*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test13(
217*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %y = call i8* @returner()
218*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: call void @callee()
219*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: tail call i8* @objc_retain(i8* %y) [[NUW]]
220*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret void
221*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: }
222*9880d681SAndroid Build Coastguard Workerdefine void @test13() {
223*9880d681SAndroid Build Coastguard Worker  %y = call i8* @returner()
224*9880d681SAndroid Build Coastguard Worker  call void @callee()
225*9880d681SAndroid Build Coastguard Worker  tail call i8* @objc_retain(i8* %y) nounwind
226*9880d681SAndroid Build Coastguard Worker  ret void
227*9880d681SAndroid Build Coastguard Worker}
228*9880d681SAndroid Build Coastguard Worker
229*9880d681SAndroid Build Coastguard Worker
230*9880d681SAndroid Build Coastguard Workerdeclare void @clang.arc.use(...) nounwind
231*9880d681SAndroid Build Coastguard Worker
232*9880d681SAndroid Build Coastguard Worker; CHECK: attributes [[NUW]] = { nounwind }
233