Mercurial > hg > CbC > CbC_llvm
comparison test/Transforms/ObjCARC/contract-storestrong.ll @ 147:c2174574ed3a
LLVM 10
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 16:55:33 +0900 |
parents | 803732b1fca8 |
children |
comparison
equal
deleted
inserted
replaced
134:3a76565eade5 | 147:c2174574ed3a |
---|---|
1 ; RUN: opt -objc-arc-contract -S < %s | FileCheck %s | 1 ; RUN: opt -objc-arc-contract -S < %s | FileCheck %s |
2 | 2 |
3 target datalayout = "e-p:64:64:64" | 3 target datalayout = "e-p:64:64:64" |
4 | 4 |
5 declare i8* @objc_retain(i8*) | 5 declare i8* @llvm.objc.retain(i8*) |
6 declare void @objc_release(i8*) | 6 declare void @llvm.objc.release(i8*) |
7 declare void @use_pointer(i8*) | 7 declare void @use_pointer(i8*) |
8 | 8 |
9 @x = external global i8* | 9 @x = external global i8* |
10 | 10 |
11 ; CHECK-LABEL: define void @test0( | 11 ; CHECK-LABEL: define void @test0( |
12 ; CHECK: entry: | 12 ; CHECK: entry: |
13 ; CHECK-NEXT: tail call void @objc_storeStrong(i8** @x, i8* %p) [[NUW:#[0-9]+]] | 13 ; CHECK-NEXT: tail call void @llvm.objc.storeStrong(i8** @x, i8* %p) [[NUW:#[0-9]+]] |
14 ; CHECK-NEXT: ret void | 14 ; CHECK-NEXT: ret void |
15 ; CHECK-NEXT: } | 15 ; CHECK-NEXT: } |
16 define void @test0(i8* %p) { | 16 define void @test0(i8* %p) { |
17 entry: | 17 entry: |
18 %0 = tail call i8* @objc_retain(i8* %p) nounwind | 18 %0 = tail call i8* @llvm.objc.retain(i8* %p) nounwind |
19 %tmp = load i8*, i8** @x, align 8 | 19 %tmp = load i8*, i8** @x, align 8 |
20 store i8* %0, i8** @x, align 8 | 20 store i8* %0, i8** @x, align 8 |
21 tail call void @objc_release(i8* %tmp) nounwind | 21 tail call void @llvm.objc.release(i8* %tmp) nounwind |
22 ret void | 22 ret void |
23 } | 23 } |
24 | 24 |
25 ; Don't do this if the load is volatile. | 25 ; Don't do this if the load is volatile. |
26 | 26 |
27 ; CHECK-LABEL: define void @test1(i8* %p) { | 27 ; CHECK-LABEL: define void @test1(i8* %p) { |
28 ; CHECK-NEXT: entry: | 28 ; CHECK-NEXT: entry: |
29 ; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) [[NUW]] | 29 ; CHECK-NEXT: %0 = tail call i8* @llvm.objc.retain(i8* %p) [[NUW]] |
30 ; CHECK-NEXT: %tmp = load volatile i8*, i8** @x, align 8 | 30 ; CHECK-NEXT: %tmp = load volatile i8*, i8** @x, align 8 |
31 ; CHECK-NEXT: store i8* %0, i8** @x, align 8 | 31 ; CHECK-NEXT: store i8* %0, i8** @x, align 8 |
32 ; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]] | 32 ; CHECK-NEXT: tail call void @llvm.objc.release(i8* %tmp) [[NUW]] |
33 ; CHECK-NEXT: ret void | 33 ; CHECK-NEXT: ret void |
34 ; CHECK-NEXT: } | 34 ; CHECK-NEXT: } |
35 define void @test1(i8* %p) { | 35 define void @test1(i8* %p) { |
36 entry: | 36 entry: |
37 %0 = tail call i8* @objc_retain(i8* %p) nounwind | 37 %0 = tail call i8* @llvm.objc.retain(i8* %p) nounwind |
38 %tmp = load volatile i8*, i8** @x, align 8 | 38 %tmp = load volatile i8*, i8** @x, align 8 |
39 store i8* %0, i8** @x, align 8 | 39 store i8* %0, i8** @x, align 8 |
40 tail call void @objc_release(i8* %tmp) nounwind | 40 tail call void @llvm.objc.release(i8* %tmp) nounwind |
41 ret void | 41 ret void |
42 } | 42 } |
43 | 43 |
44 ; Don't do this if the store is volatile. | 44 ; Don't do this if the store is volatile. |
45 | 45 |
46 ; CHECK-LABEL: define void @test2(i8* %p) { | 46 ; CHECK-LABEL: define void @test2(i8* %p) { |
47 ; CHECK-NEXT: entry: | 47 ; CHECK-NEXT: entry: |
48 ; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) [[NUW]] | 48 ; CHECK-NEXT: %0 = tail call i8* @llvm.objc.retain(i8* %p) [[NUW]] |
49 ; CHECK-NEXT: %tmp = load i8*, i8** @x, align 8 | 49 ; CHECK-NEXT: %tmp = load i8*, i8** @x, align 8 |
50 ; CHECK-NEXT: store volatile i8* %0, i8** @x, align 8 | 50 ; CHECK-NEXT: store volatile i8* %0, i8** @x, align 8 |
51 ; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]] | 51 ; CHECK-NEXT: tail call void @llvm.objc.release(i8* %tmp) [[NUW]] |
52 ; CHECK-NEXT: ret void | 52 ; CHECK-NEXT: ret void |
53 ; CHECK-NEXT: } | 53 ; CHECK-NEXT: } |
54 define void @test2(i8* %p) { | 54 define void @test2(i8* %p) { |
55 entry: | 55 entry: |
56 %0 = tail call i8* @objc_retain(i8* %p) nounwind | 56 %0 = tail call i8* @llvm.objc.retain(i8* %p) nounwind |
57 %tmp = load i8*, i8** @x, align 8 | 57 %tmp = load i8*, i8** @x, align 8 |
58 store volatile i8* %0, i8** @x, align 8 | 58 store volatile i8* %0, i8** @x, align 8 |
59 tail call void @objc_release(i8* %tmp) nounwind | 59 tail call void @llvm.objc.release(i8* %tmp) nounwind |
60 ret void | 60 ret void |
61 } | 61 } |
62 | 62 |
63 ; Don't do this if there's a use of the old pointer value between the store | 63 ; Don't do this if there's a use of the old pointer value between the store |
64 ; and the release. | 64 ; and the release. |
65 | 65 |
66 ; CHECK-LABEL: define void @test3(i8* %newValue) { | 66 ; CHECK-LABEL: define void @test3(i8* %newValue) { |
67 ; CHECK-NEXT: entry: | 67 ; CHECK-NEXT: entry: |
68 ; CHECK-NEXT: %x0 = tail call i8* @objc_retain(i8* %newValue) [[NUW]] | 68 ; CHECK-NEXT: %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) [[NUW]] |
69 ; CHECK-NEXT: %x1 = load i8*, i8** @x, align 8 | 69 ; CHECK-NEXT: %x1 = load i8*, i8** @x, align 8 |
70 ; CHECK-NEXT: store i8* %x0, i8** @x, align 8 | 70 ; CHECK-NEXT: store i8* %x0, i8** @x, align 8 |
71 ; CHECK-NEXT: tail call void @use_pointer(i8* %x1), !clang.arc.no_objc_arc_exceptions !0 | 71 ; CHECK-NEXT: tail call void @use_pointer(i8* %x1), !clang.arc.no_objc_arc_exceptions !0 |
72 ; CHECK-NEXT: tail call void @objc_release(i8* %x1) [[NUW]], !clang.imprecise_release !0 | 72 ; CHECK-NEXT: tail call void @llvm.objc.release(i8* %x1) [[NUW]], !clang.imprecise_release !0 |
73 ; CHECK-NEXT: ret void | 73 ; CHECK-NEXT: ret void |
74 ; CHECK-NEXT: } | 74 ; CHECK-NEXT: } |
75 define void @test3(i8* %newValue) { | 75 define void @test3(i8* %newValue) { |
76 entry: | 76 entry: |
77 %x0 = tail call i8* @objc_retain(i8* %newValue) nounwind | 77 %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind |
78 %x1 = load i8*, i8** @x, align 8 | 78 %x1 = load i8*, i8** @x, align 8 |
79 store i8* %newValue, i8** @x, align 8 | 79 store i8* %newValue, i8** @x, align 8 |
80 tail call void @use_pointer(i8* %x1), !clang.arc.no_objc_arc_exceptions !0 | 80 tail call void @use_pointer(i8* %x1), !clang.arc.no_objc_arc_exceptions !0 |
81 tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0 | 81 tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0 |
82 ret void | 82 ret void |
83 } | 83 } |
84 | 84 |
85 ; Like test3, but with an icmp use instead of a call, for good measure. | 85 ; Like test3, but with an icmp use instead of a call, for good measure. |
86 | 86 |
87 ; CHECK-LABEL: define i1 @test4(i8* %newValue, i8* %foo) { | 87 ; CHECK-LABEL: define i1 @test4(i8* %newValue, i8* %foo) { |
88 ; CHECK-NEXT: entry: | 88 ; CHECK-NEXT: entry: |
89 ; CHECK-NEXT: %x0 = tail call i8* @objc_retain(i8* %newValue) [[NUW]] | 89 ; CHECK-NEXT: %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) [[NUW]] |
90 ; CHECK-NEXT: %x1 = load i8*, i8** @x, align 8 | 90 ; CHECK-NEXT: %x1 = load i8*, i8** @x, align 8 |
91 ; CHECK-NEXT: store i8* %x0, i8** @x, align 8 | 91 ; CHECK-NEXT: store i8* %x0, i8** @x, align 8 |
92 ; CHECK-NEXT: %t = icmp eq i8* %x1, %foo | 92 ; CHECK-NEXT: %t = icmp eq i8* %x1, %foo |
93 ; CHECK-NEXT: tail call void @objc_release(i8* %x1) [[NUW]], !clang.imprecise_release !0 | 93 ; CHECK-NEXT: tail call void @llvm.objc.release(i8* %x1) [[NUW]], !clang.imprecise_release !0 |
94 ; CHECK-NEXT: ret i1 %t | 94 ; CHECK-NEXT: ret i1 %t |
95 ; CHECK-NEXT: } | 95 ; CHECK-NEXT: } |
96 define i1 @test4(i8* %newValue, i8* %foo) { | 96 define i1 @test4(i8* %newValue, i8* %foo) { |
97 entry: | 97 entry: |
98 %x0 = tail call i8* @objc_retain(i8* %newValue) nounwind | 98 %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind |
99 %x1 = load i8*, i8** @x, align 8 | 99 %x1 = load i8*, i8** @x, align 8 |
100 store i8* %newValue, i8** @x, align 8 | 100 store i8* %newValue, i8** @x, align 8 |
101 %t = icmp eq i8* %x1, %foo | 101 %t = icmp eq i8* %x1, %foo |
102 tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0 | 102 tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0 |
103 ret i1 %t | 103 ret i1 %t |
104 } | 104 } |
105 | 105 |
106 ; Do form an objc_storeStrong here, because the use is before the store. | 106 ; Do form an llvm.objc.storeStrong here, because the use is before the store. |
107 | 107 |
108 ; CHECK-LABEL: define i1 @test5(i8* %newValue, i8* %foo) { | 108 ; CHECK-LABEL: define i1 @test5(i8* %newValue, i8* %foo) { |
109 ; CHECK: %t = icmp eq i8* %x1, %foo | 109 ; CHECK: %t = icmp eq i8* %x1, %foo |
110 ; CHECK: tail call void @objc_storeStrong(i8** @x, i8* %newValue) [[NUW]] | 110 ; CHECK: tail call void @llvm.objc.storeStrong(i8** @x, i8* %newValue) [[NUW]] |
111 ; CHECK: } | 111 ; CHECK: } |
112 define i1 @test5(i8* %newValue, i8* %foo) { | 112 define i1 @test5(i8* %newValue, i8* %foo) { |
113 entry: | 113 entry: |
114 %x0 = tail call i8* @objc_retain(i8* %newValue) nounwind | 114 %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind |
115 %x1 = load i8*, i8** @x, align 8 | 115 %x1 = load i8*, i8** @x, align 8 |
116 %t = icmp eq i8* %x1, %foo | 116 %t = icmp eq i8* %x1, %foo |
117 store i8* %newValue, i8** @x, align 8 | 117 store i8* %newValue, i8** @x, align 8 |
118 tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0 | 118 tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0 |
119 ret i1 %t | 119 ret i1 %t |
120 } | 120 } |
121 | 121 |
122 ; Like test5, but the release is before the store. | 122 ; Like test5, but the release is before the store. |
123 | 123 |
124 ; CHECK-LABEL: define i1 @test6(i8* %newValue, i8* %foo) { | 124 ; CHECK-LABEL: define i1 @test6(i8* %newValue, i8* %foo) { |
125 ; CHECK: %t = icmp eq i8* %x1, %foo | 125 ; CHECK: %t = icmp eq i8* %x1, %foo |
126 ; CHECK: tail call void @objc_storeStrong(i8** @x, i8* %newValue) [[NUW]] | 126 ; CHECK: tail call void @llvm.objc.storeStrong(i8** @x, i8* %newValue) [[NUW]] |
127 ; CHECK: } | 127 ; CHECK: } |
128 define i1 @test6(i8* %newValue, i8* %foo) { | 128 define i1 @test6(i8* %newValue, i8* %foo) { |
129 entry: | 129 entry: |
130 %x0 = tail call i8* @objc_retain(i8* %newValue) nounwind | 130 %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind |
131 %x1 = load i8*, i8** @x, align 8 | 131 %x1 = load i8*, i8** @x, align 8 |
132 tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0 | 132 tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0 |
133 %t = icmp eq i8* %x1, %foo | 133 %t = icmp eq i8* %x1, %foo |
134 store i8* %newValue, i8** @x, align 8 | 134 store i8* %newValue, i8** @x, align 8 |
135 ret i1 %t | 135 ret i1 %t |
136 } | 136 } |
137 | 137 |
138 ; Like test0, but there's no store, so don't form an objc_storeStrong. | 138 ; Like test0, but there's no store, so don't form an llvm.objc.storeStrong. |
139 | 139 |
140 ; CHECK-LABEL: define void @test7( | 140 ; CHECK-LABEL: define void @test7( |
141 ; CHECK-NEXT: entry: | 141 ; CHECK-NEXT: entry: |
142 ; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) [[NUW]] | 142 ; CHECK-NEXT: %0 = tail call i8* @llvm.objc.retain(i8* %p) [[NUW]] |
143 ; CHECK-NEXT: %tmp = load i8*, i8** @x, align 8 | 143 ; CHECK-NEXT: %tmp = load i8*, i8** @x, align 8 |
144 ; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]] | 144 ; CHECK-NEXT: tail call void @llvm.objc.release(i8* %tmp) [[NUW]] |
145 ; CHECK-NEXT: ret void | 145 ; CHECK-NEXT: ret void |
146 ; CHECK-NEXT: } | 146 ; CHECK-NEXT: } |
147 define void @test7(i8* %p) { | 147 define void @test7(i8* %p) { |
148 entry: | 148 entry: |
149 %0 = tail call i8* @objc_retain(i8* %p) nounwind | 149 %0 = tail call i8* @llvm.objc.retain(i8* %p) nounwind |
150 %tmp = load i8*, i8** @x, align 8 | 150 %tmp = load i8*, i8** @x, align 8 |
151 tail call void @objc_release(i8* %tmp) nounwind | 151 tail call void @llvm.objc.release(i8* %tmp) nounwind |
152 ret void | 152 ret void |
153 } | 153 } |
154 | 154 |
155 ; Like test0, but there's no retain, so don't form an objc_storeStrong. | 155 ; Like test0, but there's no retain, so don't form an llvm.objc.storeStrong. |
156 | 156 |
157 ; CHECK-LABEL: define void @test8( | 157 ; CHECK-LABEL: define void @test8( |
158 ; CHECK-NEXT: entry: | 158 ; CHECK-NEXT: entry: |
159 ; CHECK-NEXT: %tmp = load i8*, i8** @x, align 8 | 159 ; CHECK-NEXT: %tmp = load i8*, i8** @x, align 8 |
160 ; CHECK-NEXT: store i8* %p, i8** @x, align 8 | 160 ; CHECK-NEXT: store i8* %p, i8** @x, align 8 |
161 ; CHECK-NEXT: tail call void @objc_release(i8* %tmp) [[NUW]] | 161 ; CHECK-NEXT: tail call void @llvm.objc.release(i8* %tmp) [[NUW]] |
162 ; CHECK-NEXT: ret void | 162 ; CHECK-NEXT: ret void |
163 ; CHECK-NEXT: } | 163 ; CHECK-NEXT: } |
164 define void @test8(i8* %p) { | 164 define void @test8(i8* %p) { |
165 entry: | 165 entry: |
166 %tmp = load i8*, i8** @x, align 8 | 166 %tmp = load i8*, i8** @x, align 8 |
167 store i8* %p, i8** @x, align 8 | 167 store i8* %p, i8** @x, align 8 |
168 tail call void @objc_release(i8* %tmp) nounwind | 168 tail call void @llvm.objc.release(i8* %tmp) nounwind |
169 ret void | 169 ret void |
170 } | 170 } |
171 | 171 |
172 ; Make sure that we properly handle release that *may* release our new | 172 ; Make sure that we properly handle release that *may* release our new |
173 ; value in between the retain and the store. We need to be sure that | 173 ; value in between the retain and the store. We need to be sure that |
174 ; this we can safely move the retain to the store. This specific test | 174 ; this we can safely move the retain to the store. This specific test |
175 ; makes sure that we properly handled a release of an unrelated | 175 ; makes sure that we properly handled a release of an unrelated |
176 ; pointer. | 176 ; pointer. |
177 ; | 177 ; |
178 ; CHECK-LABEL: define i1 @test9(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { | 178 ; CHECK-LABEL: define i1 @test9(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { |
179 ; CHECK-NOT: objc_storeStrong | 179 ; CHECK-NOT: llvm.objc.storeStrong |
180 define i1 @test9(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { | 180 define i1 @test9(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { |
181 entry: | 181 entry: |
182 %x0 = tail call i8* @objc_retain(i8* %newValue) nounwind | 182 %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind |
183 tail call void @objc_release(i8* %unrelated_ptr) nounwind, !clang.imprecise_release !0 | 183 tail call void @llvm.objc.release(i8* %unrelated_ptr) nounwind, !clang.imprecise_release !0 |
184 %x1 = load i8*, i8** @x, align 8 | 184 %x1 = load i8*, i8** @x, align 8 |
185 tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0 | 185 tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0 |
186 %t = icmp eq i8* %x1, %foo | 186 %t = icmp eq i8* %x1, %foo |
187 store i8* %newValue, i8** @x, align 8 | 187 store i8* %newValue, i8** @x, align 8 |
188 ret i1 %t | 188 ret i1 %t |
189 } | 189 } |
190 | 190 |
191 ; Make sure that we don't perform the optimization when we just have a call. | 191 ; Make sure that we don't perform the optimization when we just have a call. |
192 ; | 192 ; |
193 ; CHECK-LABEL: define i1 @test10(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { | 193 ; CHECK-LABEL: define i1 @test10(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { |
194 ; CHECK-NOT: objc_storeStrong | 194 ; CHECK-NOT: llvm.objc.storeStrong |
195 define i1 @test10(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { | 195 define i1 @test10(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { |
196 entry: | 196 entry: |
197 %x0 = tail call i8* @objc_retain(i8* %newValue) nounwind | 197 %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind |
198 call void @use_pointer(i8* %unrelated_ptr) | 198 call void @use_pointer(i8* %unrelated_ptr) |
199 %x1 = load i8*, i8** @x, align 8 | 199 %x1 = load i8*, i8** @x, align 8 |
200 tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0 | 200 tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0 |
201 %t = icmp eq i8* %x1, %foo | 201 %t = icmp eq i8* %x1, %foo |
202 store i8* %newValue, i8** @x, align 8 | 202 store i8* %newValue, i8** @x, align 8 |
203 ret i1 %t | 203 ret i1 %t |
204 } | 204 } |
205 | 205 |
206 ; Make sure we form the store strong if the use in between the retain | 206 ; Make sure we form the store strong if the use in between the retain |
207 ; and the store does not touch reference counts. | 207 ; and the store does not touch reference counts. |
208 ; CHECK-LABEL: define i1 @test11(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { | 208 ; CHECK-LABEL: define i1 @test11(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { |
209 ; CHECK: objc_storeStrong | 209 ; CHECK: llvm.objc.storeStrong |
210 define i1 @test11(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { | 210 define i1 @test11(i8* %newValue, i8* %foo, i8* %unrelated_ptr) { |
211 entry: | 211 entry: |
212 %x0 = tail call i8* @objc_retain(i8* %newValue) nounwind | 212 %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind |
213 %t = icmp eq i8* %newValue, %foo | 213 %t = icmp eq i8* %newValue, %foo |
214 %x1 = load i8*, i8** @x, align 8 | 214 %x1 = load i8*, i8** @x, align 8 |
215 tail call void @objc_release(i8* %x1) nounwind, !clang.imprecise_release !0 | 215 tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0 |
216 store i8* %newValue, i8** @x, align 8 | 216 store i8* %newValue, i8** @x, align 8 |
217 ret i1 %t | 217 ret i1 %t |
218 } | 218 } |
219 | 219 |
220 ; Make sure that we form the store strong even if there are bitcasts on | 220 ; Make sure that we form the store strong even if there are bitcasts on |
225 ; CHECK-NEXT: %tmp16 = load i16*, i16** %p16, align 8 | 225 ; CHECK-NEXT: %tmp16 = load i16*, i16** %p16, align 8 |
226 ; CHECK-NEXT: %tmp8 = bitcast i16* %tmp16 to i8* | 226 ; CHECK-NEXT: %tmp8 = bitcast i16* %tmp16 to i8* |
227 ; CHECK-NEXT: %p32 = bitcast i8** @x to i32** | 227 ; CHECK-NEXT: %p32 = bitcast i8** @x to i32** |
228 ; CHECK-NEXT: %v32 = bitcast i8* %p to i32* | 228 ; CHECK-NEXT: %v32 = bitcast i8* %p to i32* |
229 ; CHECK-NEXT: %0 = bitcast i16** %p16 to i8** | 229 ; CHECK-NEXT: %0 = bitcast i16** %p16 to i8** |
230 ; CHECK-NEXT: tail call void @objc_storeStrong(i8** %0, i8* %p) | 230 ; CHECK-NEXT: tail call void @llvm.objc.storeStrong(i8** %0, i8* %p) |
231 ; CHECK-NEXT: ret void | 231 ; CHECK-NEXT: ret void |
232 ; CHECK-NEXT: } | 232 ; CHECK-NEXT: } |
233 define void @test12(i8* %p) { | 233 define void @test12(i8* %p) { |
234 entry: | 234 entry: |
235 %retain = tail call i8* @objc_retain(i8* %p) nounwind | 235 %retain = tail call i8* @llvm.objc.retain(i8* %p) nounwind |
236 %p16 = bitcast i8** @x to i16** | 236 %p16 = bitcast i8** @x to i16** |
237 %tmp16 = load i16*, i16** %p16, align 8 | 237 %tmp16 = load i16*, i16** %p16, align 8 |
238 %tmp8 = bitcast i16* %tmp16 to i8* | 238 %tmp8 = bitcast i16* %tmp16 to i8* |
239 %p32 = bitcast i8** @x to i32** | 239 %p32 = bitcast i8** @x to i32** |
240 %v32 = bitcast i8* %retain to i32* | 240 %v32 = bitcast i8* %retain to i32* |
241 store i32* %v32, i32** %p32, align 8 | 241 store i32* %v32, i32** %p32, align 8 |
242 tail call void @objc_release(i8* %tmp8) nounwind | 242 tail call void @llvm.objc.release(i8* %tmp8) nounwind |
243 ret void | 243 ret void |
244 } | 244 } |
245 | 245 |
246 ; This used to crash. | 246 ; This used to crash. |
247 ; CHECK-LABEL: define i8* @test13( | 247 ; CHECK-LABEL: define i8* @test13( |
248 ; CHECK: tail call void @objc_storeStrong(i8** %{{.*}}, i8* %[[NEW:.*]]) | 248 ; CHECK: tail call void @llvm.objc.storeStrong(i8** %{{.*}}, i8* %[[NEW:.*]]) |
249 ; CHECK-NEXT: ret i8* %[[NEW]] | 249 ; CHECK-NEXT: ret i8* %[[NEW]] |
250 | 250 |
251 define i8* @test13(i8* %a0, i8* %a1, i8** %addr, i8* %new) { | 251 define i8* @test13(i8* %a0, i8* %a1, i8** %addr, i8* %new) { |
252 %old = load i8*, i8** %addr, align 8 | 252 %old = load i8*, i8** %addr, align 8 |
253 call void @objc_release(i8* %old) | 253 call void @llvm.objc.release(i8* %old) |
254 %retained = call i8* @objc_retain(i8* %new) | 254 %retained = call i8* @llvm.objc.retain(i8* %new) |
255 store i8* %retained, i8** %addr, align 8 | 255 store i8* %retained, i8** %addr, align 8 |
256 ret i8* %retained | 256 ret i8* %retained |
257 } | 257 } |
258 | 258 |
259 !0 = !{} | 259 !0 = !{} |