109 lines · plain
1; RUN: opt -S -passes=objc-arc < %s | FileCheck %s2 3declare void @use_pointer(ptr)4declare ptr @returner()5declare ptr @llvm.objc.retain(ptr)6declare ptr @llvm.objc.autoreleaseReturnValue(ptr)7declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)8 9; Clean up residue left behind after inlining.10 11; CHECK-LABEL: define void @test0(12; CHECK: entry:13; CHECK-NEXT: ret void14; CHECK-NEXT: }15define void @test0(ptr %call.i) {16entry:17 %0 = tail call ptr @llvm.objc.retain(ptr %call.i) nounwind18 %1 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %0) nounwind19 ret void20}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 void27; CHECK-NEXT: }28define void @test1(ptr %call.i) {29entry:30 %0 = tail call ptr @llvm.objc.retain(ptr %call.i) nounwind31 %1 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call.i) nounwind32 ret void33}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(ptr %p)40; CHECK-NEXT: ret void41; CHECK-NEXT: }42define void @test24(ptr %p) {43entry:44 call ptr @llvm.objc.autoreleaseReturnValue(ptr %p) nounwind45 call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %p) nounwind46 call void @use_pointer(ptr %p)47 ret void48}49 50; Check that we can delete the autoreleaseRV+retainAutoreleasedRV pair even in51; 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 ptr @testNoop(56; CHECK: entry:57; CHECK-NEXT: ret ptr %call.i58; CHECK-NEXT: }59define ptr @testNoop(ptr %call.i) {60entry:61 %0 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call.i) nounwind62 %1 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call.i) nounwind63 ret ptr %call.i64}65 66; 2) Lifetime markers.67 68declare void @llvm.lifetime.start.p0(ptr)69declare void @llvm.lifetime.end.p0(ptr)70 71; CHECK-LABEL: define ptr @testLifetime(72; CHECK: entry:73; CHECK-NEXT: %obj = alloca i874; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr %obj)75; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr %obj)76; CHECK-NEXT: ret ptr %call.i77; CHECK-NEXT: }78define ptr @testLifetime(ptr %call.i) {79entry:80 %obj = alloca i881 call void @llvm.lifetime.start.p0(ptr %obj)82 %0 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call.i) nounwind83 call void @llvm.lifetime.end.p0(ptr %obj)84 %1 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call.i) nounwind85 ret ptr %call.i86}87 88; 3) Dynamic alloca markers.89 90declare ptr @llvm.stacksave()91declare void @llvm.stackrestore(ptr)92 93; CHECK-LABEL: define ptr @testStack(94; CHECK: entry:95; CHECK-NEXT: %save = tail call ptr @llvm.stacksave.p0()96; CHECK-NEXT: %obj = alloca i8, i8 %arg97; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %save)98; CHECK-NEXT: ret ptr %call.i99; CHECK-NEXT: }100define ptr @testStack(ptr %call.i, i8 %arg) {101entry:102 %save = tail call ptr @llvm.stacksave()103 %obj = alloca i8, i8 %arg104 %0 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call.i) nounwind105 call void @llvm.stackrestore(ptr %save)106 %1 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call.i) nounwind107 ret ptr %call.i108}109