xref: /llvm-project/llvm/test/Transforms/Inline/inline-retainRV-call.ll (revision 151602c7a9935558ca671b35359989b261045db0)
1; RUN: opt < %s -passes=inline -S | FileCheck %s
2
3@g0 = global ptr null, align 8
4declare ptr @foo0()
5
6define ptr @callee0_autoreleaseRV() {
7  %call = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
8  %1 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call)
9  ret ptr %call
10}
11
12; CHECK-LABEL: define void @test0_autoreleaseRV(
13; CHECK: call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
14
15define void @test0_autoreleaseRV() {
16  %call = call ptr @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
17  ret void
18}
19
20; CHECK-LABEL: define void @test0_claimRV_autoreleaseRV(
21; CHECK: %[[CALL:.*]] = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
22; CHECK: call void @llvm.objc.release(ptr %[[CALL]])
23; CHECK-NEXT: ret void
24
25define void @test0_claimRV_autoreleaseRV() {
26  %call = call ptr @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
27  ret void
28}
29
30; CHECK-LABEL: define void @test1_autoreleaseRV(
31; CHECK: invoke ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
32
33define void @test1_autoreleaseRV() personality ptr @__gxx_personality_v0 {
34entry:
35  %call = invoke ptr @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
36          to label %invoke.cont unwind label %lpad
37
38invoke.cont:
39  ret void
40
41lpad:
42  %0 = landingpad { ptr, i32 }
43          cleanup
44  resume { ptr, i32 } undef
45}
46
47; CHECK-LABEL: define void @test1_claimRV_autoreleaseRV(
48; CHECK: %[[INVOKE:.*]] = invoke ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
49; CHECK: call void @llvm.objc.release(ptr %[[INVOKE]])
50; CHECK-NEXT: br
51
52define void @test1_claimRV_autoreleaseRV() personality ptr @__gxx_personality_v0 {
53entry:
54  %call = invoke ptr @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
55          to label %invoke.cont unwind label %lpad
56
57invoke.cont:
58  ret void
59
60lpad:
61  %0 = landingpad { ptr, i32 }
62          cleanup
63  resume { ptr, i32 } undef
64}
65
66define ptr @callee1_no_autoreleaseRV() {
67  %call = call ptr @foo0()
68  ret ptr %call
69}
70
71; CHECK-LABEL: define void @test2_no_autoreleaseRV(
72; CHECK: call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
73; CHECK-NEXT: ret void
74
75define void @test2_no_autoreleaseRV() {
76  %call = call ptr @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
77  ret void
78}
79
80; CHECK-LABEL: define void @test2_claimRV_no_autoreleaseRV(
81; CHECK: call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
82; CHECK-NEXT: ret void
83
84define void @test2_claimRV_no_autoreleaseRV() {
85  %call = call ptr @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
86  ret void
87}
88
89; CHECK-LABEL: define void @test3_no_autoreleaseRV(
90; CHECK: invoke ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
91
92define void @test3_no_autoreleaseRV() personality ptr @__gxx_personality_v0 {
93entry:
94  %call = invoke ptr @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
95          to label %invoke.cont unwind label %lpad
96
97invoke.cont:
98  ret void
99
100lpad:
101  %0 = landingpad { ptr, i32 }
102          cleanup
103  resume { ptr, i32 } undef
104}
105
106define ptr @callee2_nocall() {
107  %1 = load ptr, ptr @g0, align 8
108  ret ptr %1
109}
110
111; Check that a call to @llvm.objc.retain is inserted if there is no matching
112; autoreleaseRV call or a call.
113
114; CHECK-LABEL: define void @test4_nocall(
115; CHECK: %[[V0:.*]] = load ptr, ptr @g0,
116; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %[[V0]])
117; CHECK-NEXT: ret void
118
119define void @test4_nocall() {
120  %call = call ptr @callee2_nocall() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
121  ret void
122}
123
124; CHECK-LABEL: define void @test4_claimRV_nocall(
125; CHECK: %[[V0:.*]] = load ptr, ptr @g0,
126; CHECK-NEXT: ret void
127
128define void @test4_claimRV_nocall() {
129  %call = call ptr @callee2_nocall() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
130  ret void
131}
132
133; Check that a call to @llvm.objc.retain is inserted if call to @foo already has
134; the attribute. I'm not sure this will happen in practice.
135
136define ptr @callee3_marker() {
137  %1 = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
138  ret ptr %1
139}
140
141; CHECK-LABEL: define void @test5(
142; CHECK: %[[V0:.*]] = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
143; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %[[V0]])
144; CHECK-NEXT: ret void
145
146define void @test5() {
147  %call = call ptr @callee3_marker() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
148  ret void
149}
150
151; Don't pair up an autoreleaseRV in the callee and an retainRV in the caller
152; if there is an instruction between the ret instruction and the call to
153; autoreleaseRV that isn't a cast instruction.
154
155define ptr @callee0_autoreleaseRV2() {
156  %call = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
157  %1 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call)
158  store ptr null, ptr @g0
159  ret ptr %call
160}
161
162; CHECK-LABEL: define void @test6(
163; CHECK: %[[V0:.*]] = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
164; CHECK: call ptr @llvm.objc.autoreleaseReturnValue(ptr %[[V0]])
165; CHECK: store ptr null, ptr @g0, align 8
166; CHECK: call ptr @llvm.objc.retain(ptr %[[V0]])
167; CHECK-NEXT: ret void
168
169define void @test6() {
170  %call = call ptr @callee0_autoreleaseRV2() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
171  ret void
172}
173
174declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)
175declare ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr)
176declare ptr @llvm.objc.autoreleaseReturnValue(ptr)
177declare i32 @__gxx_personality_v0(...)
178