1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
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
5 define void @nouses-argworn-funrn(ptr writeonly %.aaa) {
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
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
18 nouses-argworn-funrn_entry:
22 define void @nouses-argworn-funro(ptr writeonly %.aaa, ptr %.bbb) {
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
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
37 nouses-argworn-funro_entry:
38 %val = load i32 , ptr %.bbb
42 %_type_of_d-ccc = type <{ ptr, i8, i8, i8, i8 }>
44 @d-ccc = internal global %_type_of_d-ccc <{ ptr null, i8 1, i8 13, i8 0, i8 -127 }>, align 8
46 define void @nouses-argworn-funwo(ptr writeonly %.aaa) {
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
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
61 nouses-argworn-funwo_entry:
62 store i8 0, ptr getelementptr inbounds (%_type_of_d-ccc, ptr @d-ccc, i32 0, i32 3)
66 define void @test_store(ptr %p) {
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 initializes((0, 1)) [[P:%.*]]) #[[ATTR3:[0-9]+]] {
70 ; FNATTRS-NEXT: store i8 0, ptr [[P]], align 1
71 ; FNATTRS-NEXT: ret void
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
83 @G = external global ptr
84 define i8 @test_store_capture(ptr %p) {
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]]
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]]
102 %p2 = load ptr, ptr @G
103 %v = load i8, ptr %p2
107 define void @test_addressing(ptr %p) {
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 initializes((8, 12)) [[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
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
122 %gep = getelementptr i8, ptr %p, i64 8
123 store i32 0, ptr %gep
127 define void @test_readwrite(ptr %p) {
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
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
147 define void @test_volatile(ptr %p) {
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
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
160 store volatile i8 0, ptr %p
164 define void @test_atomicrmw(ptr %p) {
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
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
177 atomicrmw add ptr %p, i8 0 seq_cst
181 define void @test_ptrmask(ptr %p) {
182 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
183 ; FNATTRS-LABEL: define {{[^@]+}}@test_ptrmask
184 ; FNATTRS-SAME: (ptr writeonly [[P:%.*]]) #[[ATTR3]] {
185 ; FNATTRS-NEXT: [[MASK:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -5)
186 ; FNATTRS-NEXT: store i8 0, ptr [[MASK]], align 1
187 ; FNATTRS-NEXT: ret void
189 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
190 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_ptrmask
191 ; ATTRIBUTOR-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR3]] {
192 ; ATTRIBUTOR-NEXT: [[MASK:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -5) #[[ATTR9:[0-9]+]]
193 ; ATTRIBUTOR-NEXT: store i8 0, ptr [[MASK]], align 1
194 ; ATTRIBUTOR-NEXT: ret void
196 %mask = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -5)
197 store i8 0, ptr %mask
201 declare ptr @llvm.ptrmask.p0.i64(ptr, i64)
203 declare void @direct1_callee(ptr %p)
205 define void @direct1(ptr %p) {
206 ; COMMON-LABEL: define {{[^@]+}}@direct1
207 ; COMMON-SAME: (ptr [[P:%.*]]) {
208 ; COMMON-NEXT: call void @direct1_callee(ptr [[P]])
209 ; COMMON-NEXT: ret void
211 call void @direct1_callee(ptr %p)
215 declare void @direct2_callee(ptr %p) writeonly
217 ; writeonly w/o nocapture is not enough
218 define void @direct2(ptr %p) {
219 ; FNATTRS: Function Attrs: memory(write)
220 ; FNATTRS-LABEL: define {{[^@]+}}@direct2
221 ; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR9:[0-9]+]] {
222 ; FNATTRS-NEXT: call void @direct2_callee(ptr [[P]])
223 ; FNATTRS-NEXT: ret void
225 ; ATTRIBUTOR: Function Attrs: memory(write)
226 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@direct2
227 ; ATTRIBUTOR-SAME: (ptr writeonly [[P:%.*]]) #[[ATTR8:[0-9]+]] {
228 ; ATTRIBUTOR-NEXT: call void @direct2_callee(ptr [[P]]) #[[ATTR8]]
229 ; ATTRIBUTOR-NEXT: ret void
231 call void @direct2_callee(ptr %p)
232 ; read back from global, read through pointer...
236 define void @direct2b(ptr %p) {
237 ; FNATTRS: Function Attrs: memory(write)
238 ; FNATTRS-LABEL: define {{[^@]+}}@direct2b
239 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR9]] {
240 ; FNATTRS-NEXT: call void @direct2_callee(ptr nocapture [[P]])
241 ; FNATTRS-NEXT: ret void
243 ; ATTRIBUTOR: Function Attrs: memory(write)
244 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@direct2b
245 ; ATTRIBUTOR-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR8]] {
246 ; ATTRIBUTOR-NEXT: call void @direct2_callee(ptr nocapture writeonly [[P]]) #[[ATTR8]]
247 ; ATTRIBUTOR-NEXT: ret void
249 call void @direct2_callee(ptr nocapture %p)
253 declare void @direct3_callee(ptr nocapture writeonly %p)
255 define void @direct3(ptr %p) {
256 ; FNATTRS-LABEL: define {{[^@]+}}@direct3
257 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]]) {
258 ; FNATTRS-NEXT: call void @direct3_callee(ptr [[P]])
259 ; FNATTRS-NEXT: ret void
261 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@direct3
262 ; ATTRIBUTOR-SAME: (ptr nocapture writeonly [[P:%.*]]) {
263 ; ATTRIBUTOR-NEXT: call void @direct3_callee(ptr nocapture writeonly [[P]])
264 ; ATTRIBUTOR-NEXT: ret void
266 call void @direct3_callee(ptr %p)
270 define void @direct3b(ptr %p) {
271 ; COMMON-LABEL: define {{[^@]+}}@direct3b
272 ; COMMON-SAME: (ptr [[P:%.*]]) {
273 ; COMMON-NEXT: call void @direct3_callee(ptr [[P]]) [ "may-read-and-capture"(ptr [[P]]) ]
274 ; COMMON-NEXT: ret void
276 call void @direct3_callee(ptr %p) ["may-read-and-capture"(ptr %p)]
280 define void @direct3c(ptr %p) {
281 ; FNATTRS-LABEL: define {{[^@]+}}@direct3c
282 ; FNATTRS-SAME: (ptr nocapture [[P:%.*]]) {
283 ; FNATTRS-NEXT: call void @direct3_callee(ptr [[P]]) [ "may-read"() ]
284 ; FNATTRS-NEXT: ret void
286 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@direct3c
287 ; ATTRIBUTOR-SAME: (ptr nocapture [[P:%.*]]) {
288 ; ATTRIBUTOR-NEXT: call void @direct3_callee(ptr nocapture [[P]]) [ "may-read"() ]
289 ; ATTRIBUTOR-NEXT: ret void
291 call void @direct3_callee(ptr %p) ["may-read"()]
295 define void @fptr_test1(ptr %p, ptr %f) {
296 ; FNATTRS-LABEL: define {{[^@]+}}@fptr_test1
297 ; FNATTRS-SAME: (ptr [[P:%.*]], ptr nocapture readonly [[F:%.*]]) {
298 ; FNATTRS-NEXT: call void [[F]](ptr [[P]])
299 ; FNATTRS-NEXT: ret void
301 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test1
302 ; ATTRIBUTOR-SAME: (ptr [[P:%.*]], ptr nocapture nofree nonnull [[F:%.*]]) {
303 ; ATTRIBUTOR-NEXT: call void [[F]](ptr [[P]])
304 ; ATTRIBUTOR-NEXT: ret void
310 define void @fptr_test2(ptr %p, ptr %f) {
311 ; FNATTRS-LABEL: define {{[^@]+}}@fptr_test2
312 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]], ptr nocapture readonly [[F:%.*]]) {
313 ; FNATTRS-NEXT: call void [[F]](ptr nocapture writeonly [[P]])
314 ; FNATTRS-NEXT: ret void
316 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test2
317 ; ATTRIBUTOR-SAME: (ptr nocapture [[P:%.*]], ptr nocapture nofree nonnull [[F:%.*]]) {
318 ; ATTRIBUTOR-NEXT: call void [[F]](ptr nocapture writeonly [[P]])
319 ; ATTRIBUTOR-NEXT: ret void
321 call void %f(ptr nocapture writeonly %p)
325 define void @fptr_test3(ptr %p, ptr %f) {
326 ; FNATTRS: Function Attrs: memory(write)
327 ; FNATTRS-LABEL: define {{[^@]+}}@fptr_test3
328 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]], ptr nocapture readonly [[F:%.*]]) #[[ATTR9]] {
329 ; FNATTRS-NEXT: call void [[F]](ptr nocapture [[P]]) #[[ATTR9]]
330 ; FNATTRS-NEXT: ret void
332 ; ATTRIBUTOR: Function Attrs: memory(write)
333 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@fptr_test3
334 ; ATTRIBUTOR-SAME: (ptr nocapture writeonly [[P:%.*]], ptr nocapture nofree nonnull writeonly [[F:%.*]]) #[[ATTR8]] {
335 ; ATTRIBUTOR-NEXT: call void [[F]](ptr nocapture [[P]]) #[[ATTR8]]
336 ; ATTRIBUTOR-NEXT: ret void
338 call void %f(ptr nocapture %p) writeonly
342 define void @test_argmem_none_callee(ptr %p) {
343 ; FNATTRS-LABEL: define {{[^@]+}}@test_argmem_none_callee
344 ; FNATTRS-SAME: (ptr nocapture readnone [[P:%.*]]) {
345 ; FNATTRS-NEXT: call void @direct1_callee(ptr nocapture [[P]]) #[[ATTR10:[0-9]+]]
346 ; FNATTRS-NEXT: ret void
348 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_argmem_none_callee
349 ; ATTRIBUTOR-SAME: (ptr nocapture [[P:%.*]]) {
350 ; ATTRIBUTOR-NEXT: call void @direct1_callee(ptr nocapture [[P]]) #[[ATTR10:[0-9]+]]
351 ; ATTRIBUTOR-NEXT: ret void
353 call void @direct1_callee(ptr nocapture %p) memory(readwrite, argmem: none)
357 define void @test_argmem_read_callee(ptr %p) {
358 ; FNATTRS-LABEL: define {{[^@]+}}@test_argmem_read_callee
359 ; FNATTRS-SAME: (ptr nocapture readonly [[P:%.*]]) {
360 ; FNATTRS-NEXT: call void @direct1_callee(ptr nocapture [[P]]) #[[ATTR11:[0-9]+]]
361 ; FNATTRS-NEXT: ret void
363 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_argmem_read_callee
364 ; ATTRIBUTOR-SAME: (ptr nocapture [[P:%.*]]) {
365 ; ATTRIBUTOR-NEXT: call void @direct1_callee(ptr nocapture [[P]]) #[[ATTR11:[0-9]+]]
366 ; ATTRIBUTOR-NEXT: ret void
368 call void @direct1_callee(ptr nocapture %p) memory(readwrite, argmem: read)
372 define void @test_argmem_write_callee(ptr %p) {
373 ; FNATTRS-LABEL: define {{[^@]+}}@test_argmem_write_callee
374 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]]) {
375 ; FNATTRS-NEXT: call void @direct1_callee(ptr nocapture [[P]]) #[[ATTR12:[0-9]+]]
376 ; FNATTRS-NEXT: ret void
378 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@test_argmem_write_callee
379 ; ATTRIBUTOR-SAME: (ptr nocapture [[P:%.*]]) {
380 ; ATTRIBUTOR-NEXT: call void @direct1_callee(ptr nocapture [[P]]) #[[ATTR12:[0-9]+]]
381 ; ATTRIBUTOR-NEXT: ret void
383 call void @direct1_callee(ptr nocapture %p) memory(readwrite, argmem: write)