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