xref: /llvm-project/llvm/test/Transforms/ObjCARC/post-inlining.ll (revision 25bc999d1fb2efccc3ece398550af738aea7d310)
1; RUN: opt -S -passes=objc-arc < %s | FileCheck %s
2
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 void
14; CHECK-NEXT: }
15define void @test0(ptr %call.i) {
16entry:
17  %0 = tail call ptr @llvm.objc.retain(ptr %call.i) nounwind
18  %1 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %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(ptr %call.i) {
29entry:
30  %0 = tail call ptr @llvm.objc.retain(ptr %call.i) nounwind
31  %1 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %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(ptr %p)
40; CHECK-NEXT:   ret void
41; CHECK-NEXT: }
42define void @test24(ptr %p) {
43entry:
44  call ptr @llvm.objc.autoreleaseReturnValue(ptr %p) nounwind
45  call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %p) nounwind
46  call void @use_pointer(ptr %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 ptr @testNoop(
56; CHECK: entry:
57; CHECK-NEXT: ret ptr %call.i
58; CHECK-NEXT: }
59define ptr @testNoop(ptr %call.i) {
60entry:
61  %0 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call.i) nounwind
62  %1 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call.i) nounwind
63  ret ptr %call.i
64}
65
66; 2) Lifetime markers.
67
68declare void @llvm.lifetime.start.p0(i64, ptr)
69declare void @llvm.lifetime.end.p0(i64, ptr)
70
71; CHECK-LABEL: define ptr @testLifetime(
72; CHECK: entry:
73; CHECK-NEXT: %obj = alloca i8
74; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr %obj)
75; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr %obj)
76; CHECK-NEXT: ret ptr %call.i
77; CHECK-NEXT: }
78define ptr @testLifetime(ptr %call.i) {
79entry:
80  %obj = alloca i8
81  call void @llvm.lifetime.start.p0(i64 8, ptr %obj)
82  %0 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call.i) nounwind
83  call void @llvm.lifetime.end.p0(i64 8, ptr %obj)
84  %1 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call.i) nounwind
85  ret ptr %call.i
86}
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 %arg
97; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr %save)
98; CHECK-NEXT: ret ptr %call.i
99; CHECK-NEXT: }
100define ptr @testStack(ptr %call.i, i8 %arg) {
101entry:
102  %save = tail call ptr @llvm.stacksave()
103  %obj = alloca i8, i8 %arg
104  %0 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call.i) nounwind
105  call void @llvm.stackrestore(ptr %save)
106  %1 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call.i) nounwind
107  ret ptr %call.i
108}
109