xref: /llvm-project/llvm/test/Transforms/ObjCARC/intrinsic-use.ll (revision 01e4f41b43b57dee751146fde9992c660bd7c714)
1; RUN: opt -passes=objc-arc -S < %s | FileCheck %s
2
3target datalayout = "e-p:64:64:64"
4
5declare ptr @llvm.objc.retain(ptr)
6declare ptr @llvm.objc.retainAutorelease(ptr)
7declare void @llvm.objc.release(ptr)
8declare ptr @llvm.objc.autorelease(ptr)
9
10declare void @llvm.objc.clang.arc.use(...)
11declare void @llvm.objc.clang.arc.noop.use(...)
12
13declare void @test0_helper(ptr, ptr)
14declare void @can_release(ptr)
15
16; Ensure that we honor clang.arc.use as a use and don't miscompile
17; the reduced test case from <rdar://13195034>.
18;
19; CHECK-LABEL:      define void @test0(
20; CHECK:        @llvm.objc.retain(ptr %x)
21; CHECK-NEXT:   store ptr %y, ptr %temp0
22; CHECK-NEXT:   @llvm.objc.retain(ptr %y)
23; CHECK-NEXT:   call void @test0_helper
24; CHECK-NEXT:   [[VAL1:%.*]] = load ptr, ptr %temp0
25; CHECK-NEXT:   @llvm.objc.retain(ptr [[VAL1]])
26; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(ptr %y)
27; CHECK-NEXT:   @llvm.objc.release(ptr %y)
28; CHECK-NEXT:   store ptr [[VAL1]], ptr %temp1
29; CHECK-NEXT:   call void @test0_helper
30; CHECK-NEXT:   [[VAL2:%.*]] = load ptr, ptr %temp1
31; CHECK-NEXT:   @llvm.objc.retain(ptr [[VAL2]])
32; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(ptr [[VAL1]])
33; CHECK-NEXT:   @llvm.objc.release(ptr [[VAL1]])
34; CHECK-NEXT:   @llvm.objc.autorelease(ptr %x)
35; CHECK-NEXT:   store ptr %x, ptr %out
36; CHECK-NEXT:   @llvm.objc.retain(ptr %x)
37; CHECK-NEXT:   @llvm.objc.release(ptr [[VAL2]])
38; CHECK-NEXT:   @llvm.objc.release(ptr %x)
39; CHECK-NEXT:   ret void
40; CHECK-NEXT: }
41define void @test0(ptr %out, ptr %x, ptr %y) {
42entry:
43  %temp0 = alloca ptr, align 8
44  %temp1 = alloca ptr, align 8
45  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
46  %1 = call ptr @llvm.objc.retain(ptr %y) nounwind
47  store ptr %y, ptr %temp0
48  call void @test0_helper(ptr %x, ptr %temp0)
49  %val1 = load ptr, ptr %temp0
50  %2 = call ptr @llvm.objc.retain(ptr %val1) nounwind
51  call void (...) @llvm.objc.clang.arc.use(ptr %y) nounwind
52  call void @llvm.objc.release(ptr %y) nounwind
53  store ptr %val1, ptr %temp1
54  call void @test0_helper(ptr %x, ptr %temp1)
55  %val2 = load ptr, ptr %temp1
56  %3 = call ptr @llvm.objc.retain(ptr %val2) nounwind
57  call void (...) @llvm.objc.clang.arc.use(ptr %val1) nounwind
58  call void @llvm.objc.release(ptr %val1) nounwind
59  %4 = call ptr @llvm.objc.retain(ptr %x) nounwind
60  %5 = call ptr @llvm.objc.autorelease(ptr %x) nounwind
61  store ptr %x, ptr %out
62  call void @llvm.objc.release(ptr %val2) nounwind
63  call void @llvm.objc.release(ptr %x) nounwind
64  ret void
65}
66
67; CHECK-LABEL:      define void @test0a(
68; CHECK:        @llvm.objc.retain(ptr %x)
69; CHECK-NEXT:   store ptr %y, ptr %temp0
70; CHECK-NEXT:   @llvm.objc.retain(ptr %y)
71; CHECK-NEXT:   call void @test0_helper
72; CHECK-NEXT:   [[VAL1:%.*]] = load ptr, ptr %temp0
73; CHECK-NEXT:   @llvm.objc.retain(ptr [[VAL1]])
74; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(ptr %y)
75; CHECK-NEXT:   @llvm.objc.release(ptr %y)
76; CHECK-NEXT:   store ptr [[VAL1]], ptr %temp1
77; CHECK-NEXT:   call void @test0_helper
78; CHECK-NEXT:   [[VAL2:%.*]] = load ptr, ptr %temp1
79; CHECK-NEXT:   @llvm.objc.retain(ptr [[VAL2]])
80; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(ptr [[VAL1]])
81; CHECK-NEXT:   @llvm.objc.release(ptr [[VAL1]])
82; CHECK-NEXT:   @llvm.objc.autorelease(ptr %x)
83; CHECK-NEXT:   @llvm.objc.release(ptr [[VAL2]])
84; CHECK-NEXT:   store ptr %x, ptr %out
85; CHECK-NEXT:   ret void
86; CHECK-NEXT: }
87define void @test0a(ptr %out, ptr %x, ptr %y) {
88entry:
89  %temp0 = alloca ptr, align 8
90  %temp1 = alloca ptr, align 8
91  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
92  %1 = call ptr @llvm.objc.retain(ptr %y) nounwind
93  store ptr %y, ptr %temp0
94  call void @test0_helper(ptr %x, ptr %temp0)
95  %val1 = load ptr, ptr %temp0
96  %2 = call ptr @llvm.objc.retain(ptr %val1) nounwind
97  call void (...) @llvm.objc.clang.arc.use(ptr %y) nounwind
98  call void @llvm.objc.release(ptr %y) nounwind, !clang.imprecise_release !0
99  store ptr %val1, ptr %temp1
100  call void @test0_helper(ptr %x, ptr %temp1)
101  %val2 = load ptr, ptr %temp1
102  %3 = call ptr @llvm.objc.retain(ptr %val2) nounwind
103  call void (...) @llvm.objc.clang.arc.use(ptr %val1) nounwind
104  call void @llvm.objc.release(ptr %val1) nounwind, !clang.imprecise_release !0
105  %4 = call ptr @llvm.objc.retain(ptr %x) nounwind
106  %5 = call ptr @llvm.objc.autorelease(ptr %x) nounwind
107  store ptr %x, ptr %out
108  call void @llvm.objc.release(ptr %val2) nounwind, !clang.imprecise_release !0
109  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
110  ret void
111}
112
113; ARC optimizer should be able to safely remove the retain/release pair as the
114; call to @llvm.objc.clang.arc.noop.use is a no-op.
115
116; CHECK-LABEL: define void @test_arc_noop_use(
117; CHECK-NEXT:    call void @can_release(ptr %x)
118; CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use(
119; CHECK-NEXT:    ret void
120
121define void @test_arc_noop_use(ptr %out, ptr %x) {
122  call ptr @llvm.objc.retain(ptr %x)
123  call void @can_release(ptr %x)
124  call void (...) @llvm.objc.clang.arc.noop.use(ptr %x)
125  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0
126  ret void
127}
128
129!0 = !{}
130
131