1 ; RUN: opt < %s -inline -S | FileCheck %s
3 @g0 = global i8* null, align 8
6 define i8* @callee0_autoreleaseRV() {
7 %call = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
8 %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)
12 ; CHECK-LABEL: define void @test0_autoreleaseRV(
13 ; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
15 define void @test0_autoreleaseRV() {
16 %call = call i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
20 ; CHECK-LABEL: define void @test0_claimRV_autoreleaseRV(
21 ; CHECK: %[[CALL:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
22 ; CHECK: call void @llvm.objc.release(i8* %[[CALL]])
23 ; CHECK-NEXT: ret void
25 define void @test0_claimRV_autoreleaseRV() {
26 %call = call i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]
30 ; CHECK-LABEL: define void @test1_autoreleaseRV(
31 ; CHECK: invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
33 define void @test1_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
35 %call = invoke i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
36 to label %invoke.cont unwind label %lpad
42 %0 = landingpad { i8*, i32 }
44 resume { i8*, i32 } undef
47 ; CHECK-LABEL: define void @test1_claimRV_autoreleaseRV(
48 ; CHECK: %[[INVOKE:.*]] = invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
49 ; CHECK: call void @llvm.objc.release(i8* %[[INVOKE]])
52 define void @test1_claimRV_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
54 %call = invoke i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]
55 to label %invoke.cont unwind label %lpad
61 %0 = landingpad { i8*, i32 }
63 resume { i8*, i32 } undef
66 define i8* @callee1_no_autoreleaseRV() {
67 %call = call i8* @foo0()
71 ; CHECK-LABEL: define void @test2_no_autoreleaseRV(
72 ; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
73 ; CHECK-NEXT: ret void
75 define void @test2_no_autoreleaseRV() {
76 %call = call i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
80 ; CHECK-LABEL: define void @test2_claimRV_no_autoreleaseRV(
81 ; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 1) ]
82 ; CHECK-NEXT: ret void
84 define void @test2_claimRV_no_autoreleaseRV() {
85 %call = call i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]
89 ; CHECK-LABEL: define void @test3_no_autoreleaseRV(
90 ; CHECK: invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
92 define void @test3_no_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
94 %call = invoke i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
95 to label %invoke.cont unwind label %lpad
101 %0 = landingpad { i8*, i32 }
103 resume { i8*, i32 } undef
106 define i8* @callee2_nocall() {
107 %1 = load i8*, i8** @g0, align 8
111 ; Check that a call to @llvm.objc.retain is inserted if there is no matching
112 ; autoreleaseRV call or a call.
114 ; CHECK-LABEL: define void @test4_nocall(
115 ; CHECK: %[[V0:.*]] = load i8*, i8** @g0,
116 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %[[V0]])
117 ; CHECK-NEXT: ret void
119 define void @test4_nocall() {
120 %call = call i8* @callee2_nocall() [ "clang.arc.attachedcall"(i64 0) ]
124 ; CHECK-LABEL: define void @test4_claimRV_nocall(
125 ; CHECK: %[[V0:.*]] = load i8*, i8** @g0,
126 ; CHECK-NEXT: ret void
128 define void @test4_claimRV_nocall() {
129 %call = call i8* @callee2_nocall() [ "clang.arc.attachedcall"(i64 1) ]
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.
136 define i8* @callee3_marker() {
137 %1 = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
141 ; CHECK-LABEL: define void @test5(
142 ; CHECK: %[[V0:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
143 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %[[V0]])
144 ; CHECK-NEXT: ret void
146 define void @test5() {
147 %call = call i8* @callee3_marker() [ "clang.arc.attachedcall"(i64 0) ]
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.
155 define i8* @callee0_autoreleaseRV2() {
156 %call = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
157 %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)
158 store i8* null, i8** @g0
162 ; CHECK-LABEL: define void @test6(
163 ; CHECK: %[[V0:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
164 ; CHECK: call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[V0]])
165 ; CHECK: store i8* null, i8** @g0, align 8
166 ; CHECK: call i8* @llvm.objc.retain(i8* %[[V0]])
167 ; CHECK-NEXT: ret void
169 define void @test6() {
170 %call = call i8* @callee0_autoreleaseRV2() [ "clang.arc.attachedcall"(i64 0) ]
174 declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
175 declare i32 @__gxx_personality_v0(...)