1; RUN: opt -S -objc-arc < %s | FileCheck %s 2 3declare void @use_pointer(i8*) 4declare i8* @returner() 5declare i8* @llvm.objc.retain(i8*) 6declare i8* @llvm.objc.autoreleaseReturnValue(i8*) 7declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) 8 9; Clean up residue left behind after inlining. 10 11; CHECK-LABEL: define void @test0( 12; CHECK: entry: 13; CHECK-NEXT: ret void 14; CHECK-NEXT: } 15define void @test0(i8* %call.i) { 16entry: 17 %0 = tail call i8* @llvm.objc.retain(i8* %call.i) nounwind 18 %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind 19 ret void 20} 21 22; Same as test0, but with slightly different use arrangements. 23 24; CHECK-LABEL: define void @test1( 25; CHECK: entry: 26; CHECK-NEXT: ret void 27; CHECK-NEXT: } 28define void @test1(i8* %call.i) { 29entry: 30 %0 = tail call i8* @llvm.objc.retain(i8* %call.i) nounwind 31 %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind 32 ret void 33} 34 35; Delete a retainRV+autoreleaseRV even if the pointer is used. 36 37; CHECK-LABEL: define void @test24( 38; CHECK-NEXT: entry: 39; CHECK-NEXT: call void @use_pointer(i8* %p) 40; CHECK-NEXT: ret void 41; CHECK-NEXT: } 42define void @test24(i8* %p) { 43entry: 44 call i8* @llvm.objc.autoreleaseReturnValue(i8* %p) nounwind 45 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p) nounwind 46 call void @use_pointer(i8* %p) 47 ret void 48} 49 50; Check that we can delete the autoreleaseRV+retainAutoreleasedRV pair even in 51; presence of instructions added by the inliner as part of the return sequence. 52 53; 1) Noop instructions: bitcasts and zero-indices GEPs. 54 55; CHECK-LABEL: define i8* @testNoop( 56; CHECK: entry: 57; CHECK-NEXT: %noop0 = bitcast i8* %call.i to i64* 58; CHECK-NEXT: %noop1 = getelementptr i8, i8* %call.i, i32 0 59; CHECK-NEXT: ret i8* %call.i 60; CHECK-NEXT: } 61define i8* @testNoop(i8* %call.i) { 62entry: 63 %0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind 64 %noop0 = bitcast i8* %call.i to i64* 65 %noop1 = getelementptr i8, i8* %call.i, i32 0 66 %1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call.i) nounwind 67 ret i8* %call.i 68} 69 70; 2) Lifetime markers. 71 72declare void @llvm.lifetime.start.p0i8(i64, i8*) 73declare void @llvm.lifetime.end.p0i8(i64, i8*) 74 75; CHECK-LABEL: define i8* @testLifetime( 76; CHECK: entry: 77; CHECK-NEXT: %obj = alloca i8 78; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* %obj) 79; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* %obj) 80; CHECK-NEXT: ret i8* %call.i 81; CHECK-NEXT: } 82define i8* @testLifetime(i8* %call.i) { 83entry: 84 %obj = alloca i8 85 call void @llvm.lifetime.start.p0i8(i64 8, i8* %obj) 86 %0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind 87 call void @llvm.lifetime.end.p0i8(i64 8, i8* %obj) 88 %1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call.i) nounwind 89 ret i8* %call.i 90} 91 92; 3) Dynamic alloca markers. 93 94declare i8* @llvm.stacksave() 95declare void @llvm.stackrestore(i8*) 96 97; CHECK-LABEL: define i8* @testStack( 98; CHECK: entry: 99; CHECK-NEXT: %save = tail call i8* @llvm.stacksave() 100; CHECK-NEXT: %obj = alloca i8, i8 %arg 101; CHECK-NEXT: call void @llvm.stackrestore(i8* %save) 102; CHECK-NEXT: ret i8* %call.i 103; CHECK-NEXT: } 104define i8* @testStack(i8* %call.i, i8 %arg) { 105entry: 106 %save = tail call i8* @llvm.stacksave() 107 %obj = alloca i8, i8 %arg 108 %0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind 109 call void @llvm.stackrestore(i8* %save) 110 %1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call.i) nounwind 111 ret i8* %call.i 112} 113