1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --version 2
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 @g = global ptr null ; <ptr> [#uses=1]
7 define ptr @c1(ptr %q) {
8 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
9 ; FNATTRS-LABEL: define ptr @c1
10 ; FNATTRS-SAME: (ptr readnone returned [[Q:%.*]]) #[[ATTR0:[0-9]+]] {
11 ; FNATTRS-NEXT: ret ptr [[Q]]
13 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
14 ; ATTRIBUTOR-LABEL: define ptr @c1
15 ; ATTRIBUTOR-SAME: (ptr nofree readnone [[Q:%.*]]) #[[ATTR0:[0-9]+]] {
16 ; ATTRIBUTOR-NEXT: ret ptr [[Q]]
21 ; It would also be acceptable to mark %q as readnone. Update @c3 too.
22 define void @c2(ptr %q) {
23 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none)
24 ; FNATTRS-LABEL: define void @c2
25 ; FNATTRS-SAME: (ptr [[Q:%.*]]) #[[ATTR1:[0-9]+]] {
26 ; FNATTRS-NEXT: store ptr [[Q]], ptr @g, align 8
27 ; FNATTRS-NEXT: ret void
29 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
30 ; ATTRIBUTOR-LABEL: define void @c2
31 ; ATTRIBUTOR-SAME: (ptr nofree writeonly [[Q:%.*]]) #[[ATTR1:[0-9]+]] {
32 ; ATTRIBUTOR-NEXT: store ptr [[Q]], ptr @g, align 8
33 ; ATTRIBUTOR-NEXT: ret void
39 define void @c3(ptr %q) {
40 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, inaccessiblemem: none)
41 ; FNATTRS-LABEL: define void @c3
42 ; FNATTRS-SAME: (ptr [[Q:%.*]]) #[[ATTR2:[0-9]+]] {
43 ; FNATTRS-NEXT: call void @c2(ptr [[Q]])
44 ; FNATTRS-NEXT: ret void
46 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
47 ; ATTRIBUTOR-LABEL: define void @c3
48 ; ATTRIBUTOR-SAME: (ptr nofree writeonly [[Q:%.*]]) #[[ATTR1]] {
49 ; ATTRIBUTOR-NEXT: call void @c2(ptr nofree writeonly [[Q]]) #[[ATTR16:[0-9]+]]
50 ; ATTRIBUTOR-NEXT: ret void
56 define i1 @c4(ptr %q, i32 %bitno) {
57 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
58 ; FNATTRS-LABEL: define noundef i1 @c4
59 ; FNATTRS-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] {
60 ; FNATTRS-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
61 ; FNATTRS-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
62 ; FNATTRS-NEXT: [[BIT:%.*]] = trunc i32 [[TMP2]] to i1
63 ; FNATTRS-NEXT: br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]]
65 ; FNATTRS-NEXT: ret i1 false
67 ; FNATTRS-NEXT: ret i1 true
69 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
70 ; ATTRIBUTOR-LABEL: define i1 @c4
71 ; ATTRIBUTOR-SAME: (ptr nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] {
72 ; ATTRIBUTOR-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
73 ; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
74 ; ATTRIBUTOR-NEXT: [[BIT:%.*]] = trunc i32 [[TMP2]] to i1
75 ; ATTRIBUTOR-NEXT: br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]]
77 ; ATTRIBUTOR-NEXT: ret i1 false
79 ; ATTRIBUTOR-NEXT: ret i1 true
81 %tmp = ptrtoint ptr %q to i32
82 %tmp2 = lshr i32 %tmp, %bitno
83 %bit = trunc i32 %tmp2 to i1
84 br i1 %bit, label %l1, label %l0
86 ret i1 0 ; escaping value not caught by def-use chaining.
88 ret i1 1 ; escaping value not caught by def-use chaining.
91 ; c4b is c4 but without the escaping part
92 define i1 @c4b(ptr %q, i32 %bitno) {
93 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
94 ; FNATTRS-LABEL: define noundef i1 @c4b
95 ; FNATTRS-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] {
96 ; FNATTRS-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
97 ; FNATTRS-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
98 ; FNATTRS-NEXT: [[BIT:%.*]] = trunc i32 [[TMP2]] to i1
99 ; FNATTRS-NEXT: br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]]
101 ; FNATTRS-NEXT: ret i1 false
103 ; FNATTRS-NEXT: ret i1 false
105 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
106 ; ATTRIBUTOR-LABEL: define i1 @c4b
107 ; ATTRIBUTOR-SAME: (ptr nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] {
108 ; ATTRIBUTOR-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
109 ; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
110 ; ATTRIBUTOR-NEXT: [[BIT:%.*]] = trunc i32 [[TMP2]] to i1
111 ; ATTRIBUTOR-NEXT: br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]]
113 ; ATTRIBUTOR-NEXT: ret i1 false
115 ; ATTRIBUTOR-NEXT: ret i1 false
117 %tmp = ptrtoint ptr %q to i32
118 %tmp2 = lshr i32 %tmp, %bitno
119 %bit = trunc i32 %tmp2 to i1
120 br i1 %bit, label %l1, label %l0
122 ret i1 0 ; not escaping!
124 ret i1 0 ; not escaping!
127 @lookup_table = global [2 x i1] [ i1 0, i1 1 ]
129 define i1 @c5(ptr %q, i32 %bitno) {
130 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read, argmem: none, inaccessiblemem: none)
131 ; FNATTRS-LABEL: define i1 @c5
132 ; FNATTRS-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR3:[0-9]+]] {
133 ; FNATTRS-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
134 ; FNATTRS-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
135 ; FNATTRS-NEXT: [[BIT:%.*]] = and i32 [[TMP2]], 1
136 ; FNATTRS-NEXT: [[LOOKUP:%.*]] = getelementptr [2 x i1], ptr @lookup_table, i32 0, i32 [[BIT]]
137 ; FNATTRS-NEXT: [[VAL:%.*]] = load i1, ptr [[LOOKUP]], align 1
138 ; FNATTRS-NEXT: ret i1 [[VAL]]
140 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
141 ; ATTRIBUTOR-LABEL: define i1 @c5
142 ; ATTRIBUTOR-SAME: (ptr nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR2:[0-9]+]] {
143 ; ATTRIBUTOR-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
144 ; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
145 ; ATTRIBUTOR-NEXT: [[BIT:%.*]] = and i32 [[TMP2]], 1
146 ; ATTRIBUTOR-NEXT: [[LOOKUP:%.*]] = getelementptr [2 x i1], ptr @lookup_table, i32 0, i32 [[BIT]]
147 ; ATTRIBUTOR-NEXT: [[VAL:%.*]] = load i1, ptr [[LOOKUP]], align 1
148 ; ATTRIBUTOR-NEXT: ret i1 [[VAL]]
150 %tmp = ptrtoint ptr %q to i32
151 %tmp2 = lshr i32 %tmp, %bitno
152 %bit = and i32 %tmp2, 1
153 ; subtle escape mechanism follows
154 %lookup = getelementptr [2 x i1], ptr @lookup_table, i32 0, i32 %bit
155 %val = load i1, ptr %lookup
159 declare void @throw_if_bit_set(ptr, i8) readonly
161 define i1 @c6(ptr %q, i8 %bit) personality ptr @__gxx_personality_v0 {
162 ; FNATTRS: Function Attrs: nofree memory(read)
163 ; FNATTRS-LABEL: define noundef i1 @c6
164 ; FNATTRS-SAME: (ptr readonly [[Q:%.*]], i8 [[BIT:%.*]]) #[[ATTR5:[0-9]+]] personality ptr @__gxx_personality_v0 {
165 ; FNATTRS-NEXT: invoke void @throw_if_bit_set(ptr [[Q]], i8 [[BIT]])
166 ; FNATTRS-NEXT: to label [[RET0:%.*]] unwind label [[RET1:%.*]]
168 ; FNATTRS-NEXT: ret i1 false
170 ; FNATTRS-NEXT: [[EXN:%.*]] = landingpad { ptr, i32 }
171 ; FNATTRS-NEXT: cleanup
172 ; FNATTRS-NEXT: ret i1 true
174 ; ATTRIBUTOR: Function Attrs: nosync memory(read)
175 ; ATTRIBUTOR-LABEL: define i1 @c6
176 ; ATTRIBUTOR-SAME: (ptr readonly [[Q:%.*]], i8 [[BIT:%.*]]) #[[ATTR4:[0-9]+]] personality ptr @__gxx_personality_v0 {
177 ; ATTRIBUTOR-NEXT: invoke void @throw_if_bit_set(ptr [[Q]], i8 [[BIT]]) #[[ATTR4]]
178 ; ATTRIBUTOR-NEXT: to label [[RET0:%.*]] unwind label [[RET1:%.*]]
180 ; ATTRIBUTOR-NEXT: ret i1 false
182 ; ATTRIBUTOR-NEXT: [[EXN:%.*]] = landingpad { ptr, i32 }
183 ; ATTRIBUTOR-NEXT: cleanup
184 ; ATTRIBUTOR-NEXT: ret i1 true
186 invoke void @throw_if_bit_set(ptr %q, i8 %bit)
187 to label %ret0 unwind label %ret1
191 %exn = landingpad {ptr, i32}
196 declare i32 @__gxx_personality_v0(...)
198 define ptr @lookup_bit(ptr %q, i32 %bitno) readnone nounwind {
199 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
200 ; FNATTRS-LABEL: define ptr @lookup_bit
201 ; FNATTRS-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] {
202 ; FNATTRS-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
203 ; FNATTRS-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
204 ; FNATTRS-NEXT: [[BIT:%.*]] = and i32 [[TMP2]], 1
205 ; FNATTRS-NEXT: [[LOOKUP:%.*]] = getelementptr [2 x i1], ptr @lookup_table, i32 0, i32 [[BIT]]
206 ; FNATTRS-NEXT: ret ptr [[LOOKUP]]
208 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
209 ; ATTRIBUTOR-LABEL: define ptr @lookup_bit
210 ; ATTRIBUTOR-SAME: (ptr nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] {
211 ; ATTRIBUTOR-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
212 ; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
213 ; ATTRIBUTOR-NEXT: [[BIT:%.*]] = and i32 [[TMP2]], 1
214 ; ATTRIBUTOR-NEXT: [[LOOKUP:%.*]] = getelementptr [2 x i1], ptr @lookup_table, i32 0, i32 [[BIT]]
215 ; ATTRIBUTOR-NEXT: ret ptr [[LOOKUP]]
217 %tmp = ptrtoint ptr %q to i32
218 %tmp2 = lshr i32 %tmp, %bitno
219 %bit = and i32 %tmp2, 1
220 %lookup = getelementptr [2 x i1], ptr @lookup_table, i32 0, i32 %bit
224 define i1 @c7(ptr %q, i32 %bitno) {
225 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read, inaccessiblemem: none)
226 ; FNATTRS-LABEL: define i1 @c7
227 ; FNATTRS-SAME: (ptr readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR6:[0-9]+]] {
228 ; FNATTRS-NEXT: [[PTR:%.*]] = call ptr @lookup_bit(ptr [[Q]], i32 [[BITNO]])
229 ; FNATTRS-NEXT: [[VAL:%.*]] = load i1, ptr [[PTR]], align 1
230 ; FNATTRS-NEXT: ret i1 [[VAL]]
232 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
233 ; ATTRIBUTOR-LABEL: define i1 @c7
234 ; ATTRIBUTOR-SAME: (ptr nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR2]] {
235 ; ATTRIBUTOR-NEXT: [[PTR:%.*]] = call ptr @lookup_bit(ptr nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR17:[0-9]+]]
236 ; ATTRIBUTOR-NEXT: [[VAL:%.*]] = load i1, ptr [[PTR]], align 1
237 ; ATTRIBUTOR-NEXT: ret i1 [[VAL]]
239 %ptr = call ptr @lookup_bit(ptr %q, i32 %bitno)
240 %val = load i1, ptr %ptr
245 define i32 @nc1(ptr %q, ptr %p, i1 %b) {
246 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
247 ; FNATTRS-LABEL: define i32 @nc1
248 ; FNATTRS-SAME: (ptr [[Q:%.*]], ptr nocapture [[P:%.*]], i1 [[B:%.*]]) #[[ATTR7:[0-9]+]] {
250 ; FNATTRS-NEXT: br label [[L:%.*]]
252 ; FNATTRS-NEXT: [[X:%.*]] = phi ptr [ [[P]], [[E:%.*]] ]
253 ; FNATTRS-NEXT: [[Y:%.*]] = phi ptr [ [[Q]], [[E]] ]
254 ; FNATTRS-NEXT: [[TMP2:%.*]] = select i1 [[B]], ptr [[X]], ptr [[Y]]
255 ; FNATTRS-NEXT: [[VAL:%.*]] = load i32, ptr [[TMP2]], align 4
256 ; FNATTRS-NEXT: store i32 0, ptr [[X]], align 4
257 ; FNATTRS-NEXT: store ptr [[Y]], ptr @g, align 8
258 ; FNATTRS-NEXT: ret i32 [[VAL]]
260 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
261 ; ATTRIBUTOR-LABEL: define i32 @nc1
262 ; ATTRIBUTOR-SAME: (ptr nofree [[Q:%.*]], ptr nocapture nofree [[P:%.*]], i1 [[B:%.*]]) #[[ATTR5:[0-9]+]] {
263 ; ATTRIBUTOR-NEXT: e:
264 ; ATTRIBUTOR-NEXT: br label [[L:%.*]]
266 ; ATTRIBUTOR-NEXT: [[X:%.*]] = phi ptr [ [[P]], [[E:%.*]] ]
267 ; ATTRIBUTOR-NEXT: [[Y:%.*]] = phi ptr [ [[Q]], [[E]] ]
268 ; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = select i1 [[B]], ptr [[X]], ptr [[Y]]
269 ; ATTRIBUTOR-NEXT: [[VAL:%.*]] = load i32, ptr [[TMP2]], align 4
270 ; ATTRIBUTOR-NEXT: store i32 0, ptr [[X]], align 4
271 ; ATTRIBUTOR-NEXT: store ptr [[Y]], ptr @g, align 8
272 ; ATTRIBUTOR-NEXT: ret i32 [[VAL]]
277 %x = phi ptr [ %p, %e ]
278 %y = phi ptr [ %q, %e ]
279 %tmp2 = select i1 %b, ptr %x, ptr %y
280 %val = load i32, ptr %tmp2 ; <i32> [#uses=1]
286 define i32 @nc1_addrspace(ptr %q, ptr addrspace(1) %p, i1 %b) {
287 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
288 ; FNATTRS-LABEL: define i32 @nc1_addrspace
289 ; FNATTRS-SAME: (ptr [[Q:%.*]], ptr addrspace(1) nocapture [[P:%.*]], i1 [[B:%.*]]) #[[ATTR7]] {
291 ; FNATTRS-NEXT: br label [[L:%.*]]
293 ; FNATTRS-NEXT: [[X:%.*]] = phi ptr addrspace(1) [ [[P]], [[E:%.*]] ]
294 ; FNATTRS-NEXT: [[Y:%.*]] = phi ptr [ [[Q]], [[E]] ]
295 ; FNATTRS-NEXT: [[TMP:%.*]] = addrspacecast ptr addrspace(1) [[X]] to ptr
296 ; FNATTRS-NEXT: [[TMP2:%.*]] = select i1 [[B]], ptr [[TMP]], ptr [[Y]]
297 ; FNATTRS-NEXT: [[VAL:%.*]] = load i32, ptr [[TMP2]], align 4
298 ; FNATTRS-NEXT: store i32 0, ptr [[TMP]], align 4
299 ; FNATTRS-NEXT: store ptr [[Y]], ptr @g, align 8
300 ; FNATTRS-NEXT: ret i32 [[VAL]]
302 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
303 ; ATTRIBUTOR-LABEL: define i32 @nc1_addrspace
304 ; ATTRIBUTOR-SAME: (ptr nofree [[Q:%.*]], ptr addrspace(1) nocapture nofree [[P:%.*]], i1 [[B:%.*]]) #[[ATTR5]] {
305 ; ATTRIBUTOR-NEXT: e:
306 ; ATTRIBUTOR-NEXT: br label [[L:%.*]]
308 ; ATTRIBUTOR-NEXT: [[X:%.*]] = phi ptr addrspace(1) [ [[P]], [[E:%.*]] ]
309 ; ATTRIBUTOR-NEXT: [[Y:%.*]] = phi ptr [ [[Q]], [[E]] ]
310 ; ATTRIBUTOR-NEXT: [[TMP:%.*]] = addrspacecast ptr addrspace(1) [[X]] to ptr
311 ; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = select i1 [[B]], ptr [[TMP]], ptr [[Y]]
312 ; ATTRIBUTOR-NEXT: [[VAL:%.*]] = load i32, ptr [[TMP2]], align 4
313 ; ATTRIBUTOR-NEXT: store i32 0, ptr [[TMP]], align 4
314 ; ATTRIBUTOR-NEXT: store ptr [[Y]], ptr @g, align 8
315 ; ATTRIBUTOR-NEXT: ret i32 [[VAL]]
320 %x = phi ptr addrspace(1) [ %p, %e ]
321 %y = phi ptr [ %q, %e ]
322 %tmp = addrspacecast ptr addrspace(1) %x to ptr ; <ptr> [#uses=2]
323 %tmp2 = select i1 %b, ptr %tmp, ptr %y
324 %val = load i32, ptr %tmp2 ; <i32> [#uses=1]
325 store i32 0, ptr %tmp
330 define void @nc2(ptr %p, ptr %q) {
331 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
332 ; FNATTRS-LABEL: define void @nc2
333 ; FNATTRS-SAME: (ptr nocapture [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR7]] {
334 ; FNATTRS-NEXT: [[TMP1:%.*]] = call i32 @nc1(ptr [[Q]], ptr [[P]], i1 false)
335 ; FNATTRS-NEXT: ret void
337 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
338 ; ATTRIBUTOR-LABEL: define void @nc2
339 ; ATTRIBUTOR-SAME: (ptr nocapture nofree [[P:%.*]], ptr nofree [[Q:%.*]]) #[[ATTR5]] {
340 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call i32 @nc1(ptr nofree [[Q]], ptr nocapture nofree [[P]], i1 false) #[[ATTR18:[0-9]+]]
341 ; ATTRIBUTOR-NEXT: ret void
343 %1 = call i32 @nc1(ptr %q, ptr %p, i1 0) ; <i32> [#uses=0]
348 define void @nc3(ptr %p) {
349 ; FNATTRS-LABEL: define void @nc3
350 ; FNATTRS-SAME: (ptr nocapture readonly [[P:%.*]]) {
351 ; FNATTRS-NEXT: call void [[P]]()
352 ; FNATTRS-NEXT: ret void
354 ; ATTRIBUTOR-LABEL: define void @nc3
355 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull [[P:%.*]]) {
356 ; ATTRIBUTOR-NEXT: call void [[P]]()
357 ; ATTRIBUTOR-NEXT: ret void
363 declare void @external(ptr) readonly nounwind
364 define void @nc4(ptr %p) {
365 ; FNATTRS: Function Attrs: nofree nounwind memory(read)
366 ; FNATTRS-LABEL: define void @nc4
367 ; FNATTRS-SAME: (ptr nocapture readonly [[P:%.*]]) #[[ATTR9:[0-9]+]] {
368 ; FNATTRS-NEXT: call void @external(ptr [[P]])
369 ; FNATTRS-NEXT: ret void
371 ; ATTRIBUTOR: Function Attrs: nosync nounwind memory(read)
372 ; ATTRIBUTOR-LABEL: define void @nc4
373 ; ATTRIBUTOR-SAME: (ptr nocapture readonly [[P:%.*]]) #[[ATTR7:[0-9]+]] {
374 ; ATTRIBUTOR-NEXT: call void @external(ptr nocapture readonly [[P]]) #[[ATTR4]]
375 ; ATTRIBUTOR-NEXT: ret void
377 call void @external(ptr %p)
381 define void @nc5(ptr %f, ptr %p) {
382 ; FNATTRS-LABEL: define void @nc5
383 ; FNATTRS-SAME: (ptr nocapture readonly [[F:%.*]], ptr nocapture [[P:%.*]]) {
384 ; FNATTRS-NEXT: call void [[F]](ptr [[P]]) #[[ATTR8:[0-9]+]]
385 ; FNATTRS-NEXT: call void [[F]](ptr nocapture [[P]])
386 ; FNATTRS-NEXT: ret void
388 ; ATTRIBUTOR-LABEL: define void @nc5
389 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull [[F:%.*]], ptr nocapture [[P:%.*]]) {
390 ; ATTRIBUTOR-NEXT: call void [[F]](ptr [[P]]) #[[ATTR6:[0-9]+]]
391 ; ATTRIBUTOR-NEXT: call void [[F]](ptr nocapture [[P]])
392 ; ATTRIBUTOR-NEXT: ret void
394 call void %f(ptr %p) readonly nounwind
395 call void %f(ptr nocapture %p)
399 ; It would be acceptable to add readnone to %y1_1 and %y1_2.
400 define void @test1_1(ptr %x1_1, ptr %y1_1, i1 %c) {
401 ; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, inaccessiblemem: none)
402 ; FNATTRS-LABEL: define void @test1_1
403 ; FNATTRS-SAME: (ptr nocapture readnone [[X1_1:%.*]], ptr [[Y1_1:%.*]], i1 [[C:%.*]]) #[[ATTR10:[0-9]+]] {
404 ; FNATTRS-NEXT: [[TMP1:%.*]] = call ptr @test1_2(ptr [[X1_1]], ptr [[Y1_1]], i1 [[C]])
405 ; FNATTRS-NEXT: store ptr null, ptr @g, align 8
406 ; FNATTRS-NEXT: ret void
408 ; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(write)
409 ; ATTRIBUTOR-LABEL: define void @test1_1
410 ; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[X1_1:%.*]], ptr nocapture nofree readnone [[Y1_1:%.*]], i1 [[C:%.*]]) #[[ATTR8:[0-9]+]] {
411 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call ptr @test1_2(ptr nocapture nofree readnone [[X1_1]], ptr nofree readnone [[Y1_1]], i1 [[C]]) #[[ATTR8]]
412 ; ATTRIBUTOR-NEXT: store ptr null, ptr @g, align 8
413 ; ATTRIBUTOR-NEXT: ret void
415 call ptr @test1_2(ptr %x1_1, ptr %y1_1, i1 %c)
416 store ptr null, ptr @g
420 define ptr @test1_2(ptr %x1_2, ptr %y1_2, i1 %c) {
421 ; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, inaccessiblemem: none)
422 ; FNATTRS-LABEL: define ptr @test1_2
423 ; FNATTRS-SAME: (ptr nocapture readnone [[X1_2:%.*]], ptr returned [[Y1_2:%.*]], i1 [[C:%.*]]) #[[ATTR10]] {
424 ; FNATTRS-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
426 ; FNATTRS-NEXT: call void @test1_1(ptr [[X1_2]], ptr [[Y1_2]], i1 [[C]])
427 ; FNATTRS-NEXT: store ptr null, ptr @g, align 8
428 ; FNATTRS-NEXT: br label [[F]]
430 ; FNATTRS-NEXT: ret ptr [[Y1_2]]
432 ; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(write)
433 ; ATTRIBUTOR-LABEL: define ptr @test1_2
434 ; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[X1_2:%.*]], ptr nofree readnone [[Y1_2:%.*]], i1 [[C:%.*]]) #[[ATTR8]] {
435 ; ATTRIBUTOR-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
437 ; ATTRIBUTOR-NEXT: call void @test1_1(ptr nocapture nofree readnone [[X1_2]], ptr nocapture nofree readnone [[Y1_2]], i1 [[C]]) #[[ATTR8]]
438 ; ATTRIBUTOR-NEXT: store ptr null, ptr @g, align 8
439 ; ATTRIBUTOR-NEXT: br label [[F]]
441 ; ATTRIBUTOR-NEXT: ret ptr [[Y1_2]]
443 br i1 %c, label %t, label %f
445 call void @test1_1(ptr %x1_2, ptr %y1_2, i1 %c)
446 store ptr null, ptr @g
452 define void @test2(ptr %x2) {
453 ; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, inaccessiblemem: none)
454 ; FNATTRS-LABEL: define void @test2
455 ; FNATTRS-SAME: (ptr nocapture readnone [[X2:%.*]]) #[[ATTR10]] {
456 ; FNATTRS-NEXT: call void @test2(ptr [[X2]])
457 ; FNATTRS-NEXT: store ptr null, ptr @g, align 8
458 ; FNATTRS-NEXT: ret void
460 ; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(write)
461 ; ATTRIBUTOR-LABEL: define void @test2
462 ; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[X2:%.*]]) #[[ATTR8]] {
463 ; ATTRIBUTOR-NEXT: call void @test2(ptr nocapture nofree readnone [[X2]]) #[[ATTR8]]
464 ; ATTRIBUTOR-NEXT: store ptr null, ptr @g, align 8
465 ; ATTRIBUTOR-NEXT: ret void
467 call void @test2(ptr %x2)
468 store ptr null, ptr @g
472 define void @test3(ptr %x3, ptr %y3, ptr %z3) {
473 ; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, inaccessiblemem: none)
474 ; FNATTRS-LABEL: define void @test3
475 ; FNATTRS-SAME: (ptr nocapture readnone [[X3:%.*]], ptr nocapture readnone [[Y3:%.*]], ptr nocapture readnone [[Z3:%.*]]) #[[ATTR10]] {
476 ; FNATTRS-NEXT: call void @test3(ptr [[Z3]], ptr [[Y3]], ptr [[X3]])
477 ; FNATTRS-NEXT: store ptr null, ptr @g, align 8
478 ; FNATTRS-NEXT: ret void
480 ; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(write)
481 ; ATTRIBUTOR-LABEL: define void @test3
482 ; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[X3:%.*]], ptr nocapture nofree readnone [[Y3:%.*]], ptr nocapture nofree readnone [[Z3:%.*]]) #[[ATTR8]] {
483 ; ATTRIBUTOR-NEXT: call void @test3(ptr nocapture nofree readnone [[Z3]], ptr nocapture nofree readnone [[Y3]], ptr nocapture nofree readnone [[X3]]) #[[ATTR8]]
484 ; ATTRIBUTOR-NEXT: store ptr null, ptr @g, align 8
485 ; ATTRIBUTOR-NEXT: ret void
487 call void @test3(ptr %z3, ptr %y3, ptr %x3)
488 store ptr null, ptr @g
492 define void @test4_1(ptr %x4_1, i1 %c) {
493 ; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, inaccessiblemem: none)
494 ; FNATTRS-LABEL: define void @test4_1
495 ; FNATTRS-SAME: (ptr [[X4_1:%.*]], i1 [[C:%.*]]) #[[ATTR10]] {
496 ; FNATTRS-NEXT: [[TMP1:%.*]] = call ptr @test4_2(ptr [[X4_1]], ptr [[X4_1]], ptr [[X4_1]], i1 [[C]])
497 ; FNATTRS-NEXT: store ptr null, ptr @g, align 8
498 ; FNATTRS-NEXT: ret void
500 ; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(write)
501 ; ATTRIBUTOR-LABEL: define void @test4_1
502 ; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[X4_1:%.*]], i1 [[C:%.*]]) #[[ATTR8]] {
503 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call ptr @test4_2(ptr nocapture nofree readnone [[X4_1]], ptr nofree readnone [[X4_1]], ptr nocapture nofree readnone [[X4_1]], i1 [[C]]) #[[ATTR8]]
504 ; ATTRIBUTOR-NEXT: store ptr null, ptr @g, align 8
505 ; ATTRIBUTOR-NEXT: ret void
507 call ptr @test4_2(ptr %x4_1, ptr %x4_1, ptr %x4_1, i1 %c)
508 store ptr null, ptr @g
512 define ptr @test4_2(ptr %x4_2, ptr %y4_2, ptr %z4_2, i1 %c) {
513 ; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, inaccessiblemem: none)
514 ; FNATTRS-LABEL: define ptr @test4_2
515 ; FNATTRS-SAME: (ptr nocapture readnone [[X4_2:%.*]], ptr readnone returned [[Y4_2:%.*]], ptr nocapture readnone [[Z4_2:%.*]], i1 [[C:%.*]]) #[[ATTR10]] {
516 ; FNATTRS-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
518 ; FNATTRS-NEXT: call void @test4_1(ptr null, i1 [[C]])
519 ; FNATTRS-NEXT: store ptr null, ptr @g, align 8
520 ; FNATTRS-NEXT: br label [[F]]
522 ; FNATTRS-NEXT: ret ptr [[Y4_2]]
524 ; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(write)
525 ; ATTRIBUTOR-LABEL: define ptr @test4_2
526 ; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[X4_2:%.*]], ptr nofree readnone [[Y4_2:%.*]], ptr nocapture nofree readnone [[Z4_2:%.*]], i1 [[C:%.*]]) #[[ATTR8]] {
527 ; ATTRIBUTOR-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
529 ; ATTRIBUTOR-NEXT: call void @test4_1(ptr nofree readnone null, i1 [[C]]) #[[ATTR8]]
530 ; ATTRIBUTOR-NEXT: store ptr null, ptr @g, align 8
531 ; ATTRIBUTOR-NEXT: br label [[F]]
533 ; ATTRIBUTOR-NEXT: ret ptr [[Y4_2]]
535 br i1 %c, label %t, label %f
537 call void @test4_1(ptr null, i1 %c)
538 store ptr null, ptr @g
544 declare ptr @test5_1(ptr %x5_1)
546 define void @test5_2(ptr %x5_2) {
547 ; COMMON-LABEL: define void @test5_2
548 ; COMMON-SAME: (ptr [[X5_2:%.*]]) {
549 ; COMMON-NEXT: [[TMP1:%.*]] = call ptr @test5_1(ptr [[X5_2]])
550 ; COMMON-NEXT: store ptr null, ptr @g, align 8
551 ; COMMON-NEXT: ret void
553 call ptr @test5_1(ptr %x5_2)
554 store ptr null, ptr @g
558 declare void @test6_1(ptr %x6_1, ptr nocapture %y6_1, ...)
560 define void @test6_2(ptr %x6_2, ptr %y6_2, ptr %z6_2) {
561 ; FNATTRS-LABEL: define void @test6_2
562 ; FNATTRS-SAME: (ptr [[X6_2:%.*]], ptr nocapture [[Y6_2:%.*]], ptr [[Z6_2:%.*]]) {
563 ; FNATTRS-NEXT: call void (ptr, ptr, ...) @test6_1(ptr [[X6_2]], ptr [[Y6_2]], ptr [[Z6_2]])
564 ; FNATTRS-NEXT: store ptr null, ptr @g, align 8
565 ; FNATTRS-NEXT: ret void
567 ; ATTRIBUTOR-LABEL: define void @test6_2
568 ; ATTRIBUTOR-SAME: (ptr [[X6_2:%.*]], ptr nocapture [[Y6_2:%.*]], ptr [[Z6_2:%.*]]) {
569 ; ATTRIBUTOR-NEXT: call void (ptr, ptr, ...) @test6_1(ptr [[X6_2]], ptr nocapture [[Y6_2]], ptr [[Z6_2]])
570 ; ATTRIBUTOR-NEXT: store ptr null, ptr @g, align 8
571 ; ATTRIBUTOR-NEXT: ret void
573 call void (ptr, ptr, ...) @test6_1(ptr %x6_2, ptr %y6_2, ptr %z6_2)
574 store ptr null, ptr @g
578 define void @test_cmpxchg(ptr %p) {
579 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
580 ; FNATTRS-LABEL: define void @test_cmpxchg
581 ; FNATTRS-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR11:[0-9]+]] {
582 ; FNATTRS-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[P]], i32 0, i32 1 acquire monotonic, align 4
583 ; FNATTRS-NEXT: ret void
585 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
586 ; ATTRIBUTOR-LABEL: define void @test_cmpxchg
587 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull [[P:%.*]]) #[[ATTR9:[0-9]+]] {
588 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[P]], i32 0, i32 1 acquire monotonic, align 4
589 ; ATTRIBUTOR-NEXT: ret void
591 cmpxchg ptr %p, i32 0, i32 1 acquire monotonic
595 define void @test_cmpxchg_ptr(ptr %p, ptr %q) {
596 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
597 ; FNATTRS-LABEL: define void @test_cmpxchg_ptr
598 ; FNATTRS-SAME: (ptr nocapture [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR11]] {
599 ; FNATTRS-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[P]], ptr null, ptr [[Q]] acquire monotonic, align 8
600 ; FNATTRS-NEXT: ret void
602 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
603 ; ATTRIBUTOR-LABEL: define void @test_cmpxchg_ptr
604 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull [[P:%.*]], ptr nofree [[Q:%.*]]) #[[ATTR9]] {
605 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[P]], ptr null, ptr [[Q]] acquire monotonic, align 8
606 ; ATTRIBUTOR-NEXT: ret void
608 cmpxchg ptr %p, ptr null, ptr %q acquire monotonic
612 define void @test_atomicrmw(ptr %p) {
613 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
614 ; FNATTRS-LABEL: define void @test_atomicrmw
615 ; FNATTRS-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR11]] {
616 ; FNATTRS-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[P]], i32 1 seq_cst, align 4
617 ; FNATTRS-NEXT: ret void
619 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
620 ; ATTRIBUTOR-LABEL: define void @test_atomicrmw
621 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull [[P:%.*]]) #[[ATTR9]] {
622 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[P]], i32 1 seq_cst, align 4
623 ; ATTRIBUTOR-NEXT: ret void
625 atomicrmw add ptr %p, i32 1 seq_cst
629 define void @test_volatile(ptr %x) {
630 ; FNATTRS: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite)
631 ; FNATTRS-LABEL: define void @test_volatile
632 ; FNATTRS-SAME: (ptr [[X:%.*]]) #[[ATTR12:[0-9]+]] {
633 ; FNATTRS-NEXT: entry:
634 ; FNATTRS-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[X]], i64 1
635 ; FNATTRS-NEXT: store volatile i32 0, ptr [[GEP]], align 4
636 ; FNATTRS-NEXT: ret void
638 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
639 ; ATTRIBUTOR-LABEL: define void @test_volatile
640 ; ATTRIBUTOR-SAME: (ptr nofree [[X:%.*]]) #[[ATTR9]] {
641 ; ATTRIBUTOR-NEXT: entry:
642 ; ATTRIBUTOR-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[X]], i64 1
643 ; ATTRIBUTOR-NEXT: store volatile i32 0, ptr [[GEP]], align 4
644 ; ATTRIBUTOR-NEXT: ret void
647 %gep = getelementptr i32, ptr %x, i64 1
648 store volatile i32 0, ptr %gep, align 4
652 define void @nocaptureLaunder(ptr %p) {
653 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write, inaccessiblemem: readwrite)
654 ; FNATTRS-LABEL: define void @nocaptureLaunder
655 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR13:[0-9]+]] {
656 ; FNATTRS-NEXT: entry:
657 ; FNATTRS-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P]])
658 ; FNATTRS-NEXT: store i8 42, ptr [[B]], align 1
659 ; FNATTRS-NEXT: ret void
661 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)
662 ; ATTRIBUTOR-LABEL: define void @nocaptureLaunder
663 ; ATTRIBUTOR-SAME: (ptr nocapture nofree [[P:%.*]]) #[[ATTR10:[0-9]+]] {
664 ; ATTRIBUTOR-NEXT: entry:
665 ; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P]]) #[[ATTR19:[0-9]+]]
666 ; ATTRIBUTOR-NEXT: store i8 42, ptr [[B]], align 1
667 ; ATTRIBUTOR-NEXT: ret void
670 %b = call ptr @llvm.launder.invariant.group.p0(ptr %p)
675 @g2 = global ptr null
676 define void @captureLaunder(ptr %p) {
677 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: readwrite)
678 ; FNATTRS-LABEL: define void @captureLaunder
679 ; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR14:[0-9]+]] {
680 ; FNATTRS-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P]])
681 ; FNATTRS-NEXT: store ptr [[B]], ptr @g2, align 8
682 ; FNATTRS-NEXT: ret void
684 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
685 ; ATTRIBUTOR-LABEL: define void @captureLaunder
686 ; ATTRIBUTOR-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] {
687 ; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P]]) #[[ATTR19]]
688 ; ATTRIBUTOR-NEXT: store ptr [[B]], ptr @g2, align 8
689 ; ATTRIBUTOR-NEXT: ret void
691 %b = call ptr @llvm.launder.invariant.group.p0(ptr %p)
692 store ptr %b, ptr @g2
696 define void @nocaptureStrip(ptr %p) {
697 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
698 ; FNATTRS-LABEL: define void @nocaptureStrip
699 ; FNATTRS-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR15:[0-9]+]] {
700 ; FNATTRS-NEXT: entry:
701 ; FNATTRS-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[P]])
702 ; FNATTRS-NEXT: store i8 42, ptr [[B]], align 1
703 ; FNATTRS-NEXT: ret void
705 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
706 ; ATTRIBUTOR-LABEL: define void @nocaptureStrip
707 ; ATTRIBUTOR-SAME: (ptr nocapture nofree writeonly [[P:%.*]]) #[[ATTR11:[0-9]+]] {
708 ; ATTRIBUTOR-NEXT: entry:
709 ; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[P]]) #[[ATTR17]]
710 ; ATTRIBUTOR-NEXT: store i8 42, ptr [[B]], align 1
711 ; ATTRIBUTOR-NEXT: ret void
714 %b = call ptr @llvm.strip.invariant.group.p0(ptr %p)
719 @g3 = global ptr null
720 define void @captureStrip(ptr %p) {
721 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none)
722 ; FNATTRS-LABEL: define void @captureStrip
723 ; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR1]] {
724 ; FNATTRS-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[P]])
725 ; FNATTRS-NEXT: store ptr [[B]], ptr @g3, align 8
726 ; FNATTRS-NEXT: ret void
728 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
729 ; ATTRIBUTOR-LABEL: define void @captureStrip
730 ; ATTRIBUTOR-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR1]] {
731 ; ATTRIBUTOR-NEXT: [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[P]]) #[[ATTR17]]
732 ; ATTRIBUTOR-NEXT: store ptr [[B]], ptr @g3, align 8
733 ; ATTRIBUTOR-NEXT: ret void
735 %b = call ptr @llvm.strip.invariant.group.p0(ptr %p)
736 store ptr %b, ptr @g3
740 define i1 @captureICmp(ptr %x) {
741 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
742 ; FNATTRS-LABEL: define i1 @captureICmp
743 ; FNATTRS-SAME: (ptr readnone [[X:%.*]]) #[[ATTR0]] {
744 ; FNATTRS-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
745 ; FNATTRS-NEXT: ret i1 [[TMP1]]
747 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
748 ; ATTRIBUTOR-LABEL: define i1 @captureICmp
749 ; ATTRIBUTOR-SAME: (ptr nofree readnone [[X:%.*]]) #[[ATTR0]] {
750 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
751 ; ATTRIBUTOR-NEXT: ret i1 [[TMP1]]
753 %1 = icmp eq ptr %x, null
757 define i1 @captureICmpRev(ptr %x) {
758 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
759 ; FNATTRS-LABEL: define i1 @captureICmpRev
760 ; FNATTRS-SAME: (ptr readnone [[X:%.*]]) #[[ATTR0]] {
761 ; FNATTRS-NEXT: [[TMP1:%.*]] = icmp eq ptr null, [[X]]
762 ; FNATTRS-NEXT: ret i1 [[TMP1]]
764 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
765 ; ATTRIBUTOR-LABEL: define i1 @captureICmpRev
766 ; ATTRIBUTOR-SAME: (ptr nofree readnone [[X:%.*]]) #[[ATTR0]] {
767 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq ptr null, [[X]]
768 ; ATTRIBUTOR-NEXT: ret i1 [[TMP1]]
770 %1 = icmp eq ptr null, %x
774 define i1 @nocaptureInboundsGEPICmp(ptr %x) {
775 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
776 ; FNATTRS-LABEL: define i1 @nocaptureInboundsGEPICmp
777 ; FNATTRS-SAME: (ptr readnone [[X:%.*]]) #[[ATTR0]] {
778 ; FNATTRS-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[X]], i32 5
779 ; FNATTRS-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null
780 ; FNATTRS-NEXT: ret i1 [[TMP2]]
782 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
783 ; ATTRIBUTOR-LABEL: define i1 @nocaptureInboundsGEPICmp
784 ; ATTRIBUTOR-SAME: (ptr nofree readnone [[X:%.*]]) #[[ATTR0]] {
785 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[X]], i32 5
786 ; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null
787 ; ATTRIBUTOR-NEXT: ret i1 [[TMP2]]
789 %1 = getelementptr inbounds i32, ptr %x, i32 5
790 %2 = icmp eq ptr %1, null
794 define i1 @nocaptureInboundsGEPICmpRev(ptr %x) {
795 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
796 ; FNATTRS-LABEL: define i1 @nocaptureInboundsGEPICmpRev
797 ; FNATTRS-SAME: (ptr readnone [[X:%.*]]) #[[ATTR0]] {
798 ; FNATTRS-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[X]], i32 5
799 ; FNATTRS-NEXT: [[TMP2:%.*]] = icmp eq ptr null, [[TMP1]]
800 ; FNATTRS-NEXT: ret i1 [[TMP2]]
802 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
803 ; ATTRIBUTOR-LABEL: define i1 @nocaptureInboundsGEPICmpRev
804 ; ATTRIBUTOR-SAME: (ptr nofree readnone [[X:%.*]]) #[[ATTR0]] {
805 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[X]], i32 5
806 ; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = icmp eq ptr null, [[TMP1]]
807 ; ATTRIBUTOR-NEXT: ret i1 [[TMP2]]
809 %1 = getelementptr inbounds i32, ptr %x, i32 5
810 %2 = icmp eq ptr null, %1
814 define i1 @nocaptureDereferenceableOrNullICmp(ptr dereferenceable_or_null(4) %x) {
815 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
816 ; FNATTRS-LABEL: define noundef i1 @nocaptureDereferenceableOrNullICmp
817 ; FNATTRS-SAME: (ptr nocapture readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR0]] {
818 ; FNATTRS-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
819 ; FNATTRS-NEXT: ret i1 [[TMP1]]
821 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
822 ; ATTRIBUTOR-LABEL: define i1 @nocaptureDereferenceableOrNullICmp
823 ; ATTRIBUTOR-SAME: (ptr nofree readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR0]] {
824 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
825 ; ATTRIBUTOR-NEXT: ret i1 [[TMP1]]
827 %1 = icmp eq ptr %x, null
831 define i1 @captureDereferenceableOrNullICmp(ptr dereferenceable_or_null(4) %x) null_pointer_is_valid {
832 ; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)
833 ; FNATTRS-LABEL: define noundef i1 @captureDereferenceableOrNullICmp
834 ; FNATTRS-SAME: (ptr readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR16:[0-9]+]] {
835 ; FNATTRS-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
836 ; FNATTRS-NEXT: ret i1 [[TMP1]]
838 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)
839 ; ATTRIBUTOR-LABEL: define i1 @captureDereferenceableOrNullICmp
840 ; ATTRIBUTOR-SAME: (ptr nofree readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR12:[0-9]+]] {
841 ; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[X]], null
842 ; ATTRIBUTOR-NEXT: ret i1 [[TMP1]]
844 %1 = icmp eq ptr %x, null
848 declare void @capture(ptr)
850 define void @nocapture_fptr(ptr %f, ptr %p) {
851 ; FNATTRS-LABEL: define void @nocapture_fptr
852 ; FNATTRS-SAME: (ptr nocapture readonly [[F:%.*]], ptr [[P:%.*]]) {
853 ; FNATTRS-NEXT: [[RES:%.*]] = call ptr [[F]](ptr [[P]])
854 ; FNATTRS-NEXT: call void @capture(ptr [[RES]])
855 ; FNATTRS-NEXT: ret void
857 ; ATTRIBUTOR-LABEL: define void @nocapture_fptr
858 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull [[F:%.*]], ptr [[P:%.*]]) {
859 ; ATTRIBUTOR-NEXT: [[RES:%.*]] = call ptr [[F]](ptr [[P]])
860 ; ATTRIBUTOR-NEXT: call void @capture(ptr [[RES]])
861 ; ATTRIBUTOR-NEXT: ret void
863 %res = call ptr %f(ptr %p)
864 call void @capture(ptr %res)
868 define void @recurse_fptr(ptr %f, ptr %p) {
869 ; FNATTRS-LABEL: define void @recurse_fptr
870 ; FNATTRS-SAME: (ptr nocapture readonly [[F:%.*]], ptr [[P:%.*]]) {
871 ; FNATTRS-NEXT: [[RES:%.*]] = call ptr [[F]](ptr [[P]])
872 ; FNATTRS-NEXT: store i8 0, ptr [[RES]], align 1
873 ; FNATTRS-NEXT: ret void
875 ; ATTRIBUTOR-LABEL: define void @recurse_fptr
876 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull [[F:%.*]], ptr [[P:%.*]]) {
877 ; ATTRIBUTOR-NEXT: [[RES:%.*]] = call ptr [[F]](ptr [[P]])
878 ; ATTRIBUTOR-NEXT: store i8 0, ptr [[RES]], align 1
879 ; ATTRIBUTOR-NEXT: ret void
881 %res = call ptr %f(ptr %p)
886 define void @readnone_indirec(ptr %f, ptr %p) {
887 ; FNATTRS: Function Attrs: nofree nosync memory(none)
888 ; FNATTRS-LABEL: define void @readnone_indirec
889 ; FNATTRS-SAME: (ptr nocapture readonly [[F:%.*]], ptr readnone [[P:%.*]]) #[[ATTR17:[0-9]+]] {
890 ; FNATTRS-NEXT: call void [[F]](ptr [[P]]) #[[ATTR20:[0-9]+]]
891 ; FNATTRS-NEXT: ret void
893 ; ATTRIBUTOR: Function Attrs: nosync memory(none)
894 ; ATTRIBUTOR-LABEL: define void @readnone_indirec
895 ; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull readnone [[F:%.*]], ptr readnone [[P:%.*]]) #[[ATTR13:[0-9]+]] {
896 ; ATTRIBUTOR-NEXT: call void [[F]](ptr [[P]]) #[[ATTR20:[0-9]+]]
897 ; ATTRIBUTOR-NEXT: ret void
899 call void %f(ptr %p) readnone
904 declare ptr @llvm.launder.invariant.group.p0(ptr)
905 declare ptr @llvm.strip.invariant.group.p0(ptr)