236
|
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
|
252
|
2 ; RUN: opt -passes=function-attrs -S < %s | FileCheck --check-prefixes=COMMON,FNATTRS %s
|
|
3 ; RUN: opt -passes=attributor-light -S < %s | FileCheck --check-prefixes=COMMON,ATTRIBUTOR %s
|
150
|
4
|
236
|
5 define void @nouses-argworn-funrn(ptr writeonly %.aaa) {
|
252
|
6 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
7 ; FNATTRS-LABEL: define {{[^@]+}}@nouses-argworn-funrn
|
|
8 ; FNATTRS-SAME: (ptr nocapture readnone [[DOTAAA:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
9 ; FNATTRS-NEXT: nouses-argworn-funrn_entry:
|
|
10 ; FNATTRS-NEXT: ret void
|
|
11 ;
|
|
12 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
13 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@nouses-argworn-funrn
|
|
14 ; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[DOTAAA:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
15 ; ATTRIBUTOR-NEXT: nouses-argworn-funrn_entry:
|
|
16 ; ATTRIBUTOR-NEXT: ret void
|
236
|
17 ;
|
150
|
18 nouses-argworn-funrn_entry:
|
|
19 ret void
|
|
20 }
|
|
21
|
236
|
22 define void @nouses-argworn-funro(ptr writeonly %.aaa, ptr %.bbb) {
|
252
|
23 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
|
|
24 ; FNATTRS-LABEL: define {{[^@]+}}@nouses-argworn-funro
|
|
25 ; FNATTRS-SAME: (ptr nocapture readnone [[DOTAAA:%.*]], ptr nocapture readonly [[DOTBBB:%.*]]) #[[ATTR1:[0-9]+]] {
|
|
26 ; FNATTRS-NEXT: nouses-argworn-funro_entry:
|
|
27 ; FNATTRS-NEXT: [[VAL:%.*]] = load i32, ptr [[DOTBBB]], align 4
|
|
28 ; FNATTRS-NEXT: ret void
|
|
29 ;
|
|
30 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
|
|
31 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@nouses-argworn-funro
|
|
32 ; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[DOTAAA:%.*]], ptr nocapture nofree nonnull readonly [[DOTBBB:%.*]]) #[[ATTR1:[0-9]+]] {
|
|
33 ; ATTRIBUTOR-NEXT: nouses-argworn-funro_entry:
|
|
34 ; ATTRIBUTOR-NEXT: [[VAL:%.*]] = load i32, ptr [[DOTBBB]], align 4
|
|
35 ; ATTRIBUTOR-NEXT: ret void
|
236
|
36 ;
|
150
|
37 nouses-argworn-funro_entry:
|
236
|
38 %val = load i32 , ptr %.bbb
|
|
39 ret void
|
|
40 }
|
|
41
|
|
42 %_type_of_d-ccc = type <{ ptr, i8, i8, i8, i8 }>
|
|
43
|
|
44 @d-ccc = internal global %_type_of_d-ccc <{ ptr null, i8 1, i8 13, i8 0, i8 -127 }>, align 8
|
|
45
|
|
46 define void @nouses-argworn-funwo(ptr writeonly %.aaa) {
|
252
|
47 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none)
|
|
48 ; FNATTRS-LABEL: define {{[^@]+}}@nouses-argworn-funwo
|
|
49 ; FNATTRS-SAME: (ptr nocapture readnone [[DOTAAA:%.*]]) #[[ATTR2:[0-9]+]] {
|
|
50 ; FNATTRS-NEXT: nouses-argworn-funwo_entry:
|
|
51 ; FNATTRS-NEXT: store i8 0, ptr getelementptr inbounds ([[_TYPE_OF_D_CCC:%.*]], ptr @d-ccc, i32 0, i32 3), align 1
|
|
52 ; FNATTRS-NEXT: ret void
|
|
53 ;
|
|
54 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
|
|
55 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@nouses-argworn-funwo
|
|
56 ; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[DOTAAA:%.*]]) #[[ATTR2:[0-9]+]] {
|
|
57 ; ATTRIBUTOR-NEXT: nouses-argworn-funwo_entry:
|
|
58 ; ATTRIBUTOR-NEXT: store i8 0, ptr getelementptr inbounds ([[_TYPE_OF_D_CCC:%.*]], ptr @d-ccc, i32 0, i32 3), align 1
|
|
59 ; ATTRIBUTOR-NEXT: ret void
|
236
|
60 ;
|
|
61 nouses-argworn-funwo_entry:
|
|
62 store i8 0, ptr getelementptr inbounds (%_type_of_d-ccc, ptr @d-ccc, i32 0, i32 3)
|
|
63 ret void
|
|
64 }
|
|
65
|
|
66 define void @test_store(ptr %p) {
|
252
|
67 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
68 ; FNATTRS-LABEL: define {{[^@]+}}@test_store
|
|
69 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR3:[0-9]+]] {
|
|
70 ; FNATTRS-NEXT: store i8 0, ptr [[P]], align 1
|
|
71 ; FNATTRS-NEXT: ret void
|
|
72 ;
|
|
73 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
74 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_store
|
|
75 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull writeonly [[P:%.*]]) #[[ATTR3:[0-9]+]] {
|
|
76 ; ATTRIBUTOR-NEXT: store i8 0, ptr [[P]], align 1
|
|
77 ; ATTRIBUTOR-NEXT: ret void
|
236
|
78 ;
|
|
79 store i8 0, ptr %p
|
|
80 ret void
|
|
81 }
|
|
82
|
|
83 @G = external global ptr
|
|
84 define i8 @test_store_capture(ptr %p) {
|
252
|
85 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: read, inaccessiblemem: none)
|
|
86 ; FNATTRS-LABEL: define {{[^@]+}}@test_store_capture
|
|
87 ; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR4:[0-9]+]] {
|
|
88 ; FNATTRS-NEXT: store ptr [[P]], ptr @G, align 8
|
|
89 ; FNATTRS-NEXT: [[P2:%.*]] = load ptr, ptr @G, align 8
|
|
90 ; FNATTRS-NEXT: [[V:%.*]] = load i8, ptr [[P2]], align 1
|
|
91 ; FNATTRS-NEXT: ret i8 [[V]]
|
|
92 ;
|
|
93 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
|
|
94 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_store_capture
|
|
95 ; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]]) #[[ATTR4:[0-9]+]] {
|
|
96 ; ATTRIBUTOR-NEXT: store ptr [[P]], ptr @G, align 8
|
|
97 ; ATTRIBUTOR-NEXT: [[P2:%.*]] = load ptr, ptr @G, align 8
|
|
98 ; ATTRIBUTOR-NEXT: [[V:%.*]] = load i8, ptr [[P2]], align 1
|
|
99 ; ATTRIBUTOR-NEXT: ret i8 [[V]]
|
236
|
100 ;
|
|
101 store ptr %p, ptr @G
|
|
102 %p2 = load ptr, ptr @G
|
|
103 %v = load i8, ptr %p2
|
|
104 ret i8 %v
|
|
105 }
|
|
106
|
|
107 define void @test_addressing(ptr %p) {
|
252
|
108 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
109 ; FNATTRS-LABEL: define {{[^@]+}}@test_addressing
|
|
110 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR3]] {
|
|
111 ; FNATTRS-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P]], i64 8
|
|
112 ; FNATTRS-NEXT: store i32 0, ptr [[GEP]], align 4
|
|
113 ; FNATTRS-NEXT: ret void
|
|
114 ;
|
|
115 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
116 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_addressing
|
|
117 ; ATTRIBUTOR-SAME: (ptr nocapture nofree writeonly [[P:%.*]]) #[[ATTR3]] {
|
|
118 ; ATTRIBUTOR-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P]], i64 8
|
|
119 ; ATTRIBUTOR-NEXT: store i32 0, ptr [[GEP]], align 4
|
|
120 ; ATTRIBUTOR-NEXT: ret void
|
236
|
121 ;
|
|
122 %gep = getelementptr i8, ptr %p, i64 8
|
|
123 store i32 0, ptr %gep
|
|
124 ret void
|
|
125 }
|
|
126
|
|
127 define void @test_readwrite(ptr %p) {
|
252
|
128 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
|
|
129 ; FNATTRS-LABEL: define {{[^@]+}}@test_readwrite
|
|
130 ; FNATTRS-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR5:[0-9]+]] {
|
|
131 ; FNATTRS-NEXT: [[V:%.*]] = load i8, ptr [[P]], align 1
|
|
132 ; FNATTRS-NEXT: store i8 [[V]], ptr [[P]], align 1
|
|
133 ; FNATTRS-NEXT: ret void
|
|
134 ;
|
|
135 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
|
|
136 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_readwrite
|
|
137 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull [[P:%.*]]) #[[ATTR5:[0-9]+]] {
|
|
138 ; ATTRIBUTOR-NEXT: [[V:%.*]] = load i8, ptr [[P]], align 1
|
|
139 ; ATTRIBUTOR-NEXT: store i8 [[V]], ptr [[P]], align 1
|
|
140 ; ATTRIBUTOR-NEXT: ret void
|
236
|
141 ;
|
|
142 %v = load i8, ptr %p
|
|
143 store i8 %v, ptr %p
|
|
144 ret void
|
|
145 }
|
|
146
|
|
147 define void @test_volatile(ptr %p) {
|
252
|
148 ; FNATTRS: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite)
|
|
149 ; FNATTRS-LABEL: define {{[^@]+}}@test_volatile
|
|
150 ; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR6:[0-9]+]] {
|
|
151 ; FNATTRS-NEXT: store volatile i8 0, ptr [[P]], align 1
|
|
152 ; FNATTRS-NEXT: ret void
|
|
153 ;
|
|
154 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
|
|
155 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_volatile
|
|
156 ; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]]) #[[ATTR6:[0-9]+]] {
|
|
157 ; ATTRIBUTOR-NEXT: store volatile i8 0, ptr [[P]], align 1
|
|
158 ; ATTRIBUTOR-NEXT: ret void
|
236
|
159 ;
|
|
160 store volatile i8 0, ptr %p
|
150
|
161 ret void
|
|
162 }
|
|
163
|
236
|
164 define void @test_atomicrmw(ptr %p) {
|
252
|
165 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
|
|
166 ; FNATTRS-LABEL: define {{[^@]+}}@test_atomicrmw
|
|
167 ; FNATTRS-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR7:[0-9]+]] {
|
|
168 ; FNATTRS-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[P]], i8 0 seq_cst, align 1
|
|
169 ; FNATTRS-NEXT: ret void
|
|
170 ;
|
|
171 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
|
|
172 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_atomicrmw
|
|
173 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull [[P:%.*]]) #[[ATTR6]] {
|
|
174 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[P]], i8 0 seq_cst, align 1
|
|
175 ; ATTRIBUTOR-NEXT: ret void
|
236
|
176 ;
|
|
177 atomicrmw add ptr %p, i8 0 seq_cst
|
|
178 ret void
|
|
179 }
|
|
180
|
150
|
181
|
236
|
182 declare void @direct1_callee(ptr %p)
|
|
183
|
|
184 define void @direct1(ptr %p) {
|
252
|
185 ; COMMON-LABEL: define {{[^@]+}}@direct1
|
|
186 ; COMMON-SAME: (ptr [[P:%.*]]) {
|
|
187 ; COMMON-NEXT: call void @direct1_callee(ptr [[P]])
|
|
188 ; COMMON-NEXT: ret void
|
236
|
189 ;
|
|
190 call void @direct1_callee(ptr %p)
|
|
191 ret void
|
|
192 }
|
150
|
193
|
236
|
194 declare void @direct2_callee(ptr %p) writeonly
|
|
195
|
|
196 ; writeonly w/o nocapture is not enough
|
|
197 define void @direct2(ptr %p) {
|
252
|
198 ; FNATTRS: Function Attrs: memory(write)
|
|
199 ; FNATTRS-LABEL: define {{[^@]+}}@direct2
|
|
200 ; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR8:[0-9]+]] {
|
|
201 ; FNATTRS-NEXT: call void @direct2_callee(ptr [[P]])
|
|
202 ; FNATTRS-NEXT: ret void
|
|
203 ;
|
|
204 ; ATTRIBUTOR: Function Attrs: memory(write)
|
|
205 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@direct2
|
|
206 ; ATTRIBUTOR-SAME: (ptr writeonly [[P:%.*]]) #[[ATTR7:[0-9]+]] {
|
|
207 ; ATTRIBUTOR-NEXT: call void @direct2_callee(ptr [[P]]) #[[ATTR7]]
|
|
208 ; ATTRIBUTOR-NEXT: ret void
|
236
|
209 ;
|
|
210 call void @direct2_callee(ptr %p)
|
|
211 ; read back from global, read through pointer...
|
|
212 ret void
|
|
213 }
|
|
214
|
|
215 define void @direct2b(ptr %p) {
|
252
|
216 ; FNATTRS: Function Attrs: memory(write)
|
|
217 ; FNATTRS-LABEL: define {{[^@]+}}@direct2b
|
|
218 ; FNATTRS-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR8]] {
|
|
219 ; FNATTRS-NEXT: call void @direct2_callee(ptr nocapture [[P]])
|
|
220 ; FNATTRS-NEXT: ret void
|
|
221 ;
|
|
222 ; ATTRIBUTOR: Function Attrs: memory(write)
|
|
223 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@direct2b
|
|
224 ; ATTRIBUTOR-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR7]] {
|
|
225 ; ATTRIBUTOR-NEXT: call void @direct2_callee(ptr nocapture writeonly [[P]]) #[[ATTR7]]
|
|
226 ; ATTRIBUTOR-NEXT: ret void
|
236
|
227 ;
|
|
228 call void @direct2_callee(ptr nocapture %p)
|
150
|
229 ret void
|
|
230 }
|
|
231
|
236
|
232 declare void @direct3_callee(ptr nocapture writeonly %p)
|
|
233
|
|
234 define void @direct3(ptr %p) {
|
252
|
235 ; FNATTRS-LABEL: define {{[^@]+}}@direct3
|
|
236 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]]) {
|
|
237 ; FNATTRS-NEXT: call void @direct3_callee(ptr [[P]])
|
|
238 ; FNATTRS-NEXT: ret void
|
|
239 ;
|
|
240 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@direct3
|
|
241 ; ATTRIBUTOR-SAME: (ptr nocapture writeonly [[P:%.*]]) {
|
|
242 ; ATTRIBUTOR-NEXT: call void @direct3_callee(ptr nocapture writeonly [[P]])
|
|
243 ; ATTRIBUTOR-NEXT: ret void
|
236
|
244 ;
|
|
245 call void @direct3_callee(ptr %p)
|
|
246 ret void
|
|
247 }
|
|
248
|
|
249 define void @direct3b(ptr %p) {
|
252
|
250 ; COMMON-LABEL: define {{[^@]+}}@direct3b
|
|
251 ; COMMON-SAME: (ptr [[P:%.*]]) {
|
|
252 ; COMMON-NEXT: call void @direct3_callee(ptr [[P]]) [ "may-read-and-capture"(ptr [[P]]) ]
|
|
253 ; COMMON-NEXT: ret void
|
236
|
254 ;
|
|
255 call void @direct3_callee(ptr %p) ["may-read-and-capture"(ptr %p)]
|
|
256 ret void
|
|
257 }
|
|
258
|
|
259 define void @direct3c(ptr %p) {
|
252
|
260 ; FNATTRS-LABEL: define {{[^@]+}}@direct3c
|
|
261 ; FNATTRS-SAME: (ptr nocapture [[P:%.*]]) {
|
|
262 ; FNATTRS-NEXT: call void @direct3_callee(ptr [[P]]) [ "may-read"() ]
|
|
263 ; FNATTRS-NEXT: ret void
|
|
264 ;
|
|
265 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@direct3c
|
|
266 ; ATTRIBUTOR-SAME: (ptr nocapture [[P:%.*]]) {
|
|
267 ; ATTRIBUTOR-NEXT: call void @direct3_callee(ptr nocapture [[P]]) [ "may-read"() ]
|
|
268 ; ATTRIBUTOR-NEXT: ret void
|
236
|
269 ;
|
|
270 call void @direct3_callee(ptr %p) ["may-read"()]
|
|
271 ret void
|
|
272 }
|
|
273
|
|
274 define void @fptr_test1(ptr %p, ptr %f) {
|
252
|
275 ; FNATTRS-LABEL: define {{[^@]+}}@fptr_test1
|
|
276 ; FNATTRS-SAME: (ptr [[P:%.*]], ptr nocapture readonly [[F:%.*]]) {
|
|
277 ; FNATTRS-NEXT: call void [[F]](ptr [[P]])
|
|
278 ; FNATTRS-NEXT: ret void
|
|
279 ;
|
|
280 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test1
|
|
281 ; ATTRIBUTOR-SAME: (ptr [[P:%.*]], ptr nocapture nofree nonnull [[F:%.*]]) {
|
|
282 ; ATTRIBUTOR-NEXT: call void [[F]](ptr [[P]])
|
|
283 ; ATTRIBUTOR-NEXT: ret void
|
236
|
284 ;
|
|
285 call void %f(ptr %p)
|
|
286 ret void
|
|
287 }
|
|
288
|
|
289 define void @fptr_test2(ptr %p, ptr %f) {
|
252
|
290 ; FNATTRS-LABEL: define {{[^@]+}}@fptr_test2
|
|
291 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]], ptr nocapture readonly [[F:%.*]]) {
|
|
292 ; FNATTRS-NEXT: call void [[F]](ptr nocapture writeonly [[P]])
|
|
293 ; FNATTRS-NEXT: ret void
|
|
294 ;
|
|
295 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test2
|
|
296 ; ATTRIBUTOR-SAME: (ptr nocapture [[P:%.*]], ptr nocapture nofree nonnull [[F:%.*]]) {
|
|
297 ; ATTRIBUTOR-NEXT: call void [[F]](ptr nocapture writeonly [[P]])
|
|
298 ; ATTRIBUTOR-NEXT: ret void
|
236
|
299 ;
|
|
300 call void %f(ptr nocapture writeonly %p)
|
|
301 ret void
|
|
302 }
|
|
303
|
|
304 define void @fptr_test3(ptr %p, ptr %f) {
|
252
|
305 ; FNATTRS: Function Attrs: memory(write)
|
|
306 ; FNATTRS-LABEL: define {{[^@]+}}@fptr_test3
|
|
307 ; FNATTRS-SAME: (ptr nocapture [[P:%.*]], ptr nocapture readonly [[F:%.*]]) #[[ATTR8]] {
|
|
308 ; FNATTRS-NEXT: call void [[F]](ptr nocapture [[P]]) #[[ATTR8]]
|
|
309 ; FNATTRS-NEXT: ret void
|
|
310 ;
|
|
311 ; ATTRIBUTOR: Function Attrs: memory(write)
|
|
312 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test3
|
|
313 ; ATTRIBUTOR-SAME: (ptr nocapture writeonly [[P:%.*]], ptr nocapture nofree nonnull writeonly [[F:%.*]]) #[[ATTR7]] {
|
|
314 ; ATTRIBUTOR-NEXT: call void [[F]](ptr nocapture [[P]]) #[[ATTR7]]
|
|
315 ; ATTRIBUTOR-NEXT: ret void
|
236
|
316 ;
|
|
317 call void %f(ptr nocapture %p) writeonly
|
|
318 ret void
|
|
319 }
|