[Transforms] Silence a warning in SROA.cpp (NFC)
[llvm-project.git] / llvm / test / Transforms / FunctionAttrs / nocapture.ll
blob7df6132ac6a315705b59d1a53ea1240e34a9a77e
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]]
18   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
35   store ptr %q, ptr @g
36   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
52   call void @c2(ptr %q)
53   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:%.*]]
64 ; FNATTRS:       l0:
65 ; FNATTRS-NEXT:    ret i1 false
66 ; FNATTRS:       l1:
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:%.*]]
76 ; ATTRIBUTOR:       l0:
77 ; ATTRIBUTOR-NEXT:    ret i1 false
78 ; ATTRIBUTOR:       l1:
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
85 l0:
86   ret i1 0 ; escaping value not caught by def-use chaining.
87 l1:
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:%.*]]
100 ; FNATTRS:       l0:
101 ; FNATTRS-NEXT:    ret i1 false
102 ; FNATTRS:       l1:
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:%.*]]
112 ; ATTRIBUTOR:       l0:
113 ; ATTRIBUTOR-NEXT:    ret i1 false
114 ; ATTRIBUTOR:       l1:
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
156   ret i1 %val
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:%.*]]
167 ; FNATTRS:       ret0:
168 ; FNATTRS-NEXT:    ret i1 false
169 ; FNATTRS:       ret1:
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:%.*]]
179 ; ATTRIBUTOR:       ret0:
180 ; ATTRIBUTOR-NEXT:    ret i1 false
181 ; ATTRIBUTOR:       ret1:
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
188 ret0:
189   ret i1 0
190 ret1:
191   %exn = landingpad {ptr, i32}
192   cleanup
193   ret i1 1
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
221   ret ptr %lookup
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
241   ret i1 %val
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]+]] {
249 ; FNATTRS-NEXT:  e:
250 ; FNATTRS-NEXT:    br label [[L:%.*]]
251 ; FNATTRS:       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:%.*]]
265 ; ATTRIBUTOR:       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]]
275   br label %l
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]
281   store i32 0, ptr %x
282   store ptr %y, ptr @g
283   ret i32 %val
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]] {
290 ; FNATTRS-NEXT:  e:
291 ; FNATTRS-NEXT:    br label [[L:%.*]]
292 ; FNATTRS:       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:%.*]]
307 ; ATTRIBUTOR:       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]]
318   br label %l
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
326   store ptr %y, ptr @g
327   ret i32 %val
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]
344   ret void
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
359   call void %p()
360   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)
378   ret void
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)
396   ret void
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
417   ret void
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:%.*]]
425 ; FNATTRS:       t:
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]]
429 ; FNATTRS:       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:%.*]]
436 ; ATTRIBUTOR:       t:
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]]
440 ; ATTRIBUTOR:       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
447   br label %f
449   ret ptr %y1_2
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
469   ret void
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
489   ret void
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
509   ret void
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:%.*]]
517 ; FNATTRS:       t:
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]]
521 ; FNATTRS:       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:%.*]]
528 ; ATTRIBUTOR:       t:
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]]
532 ; ATTRIBUTOR:       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
539   br label %f
541   ret ptr %y4_2
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
555   ret void
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
575   ret void
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
592   ret void
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
609   ret void
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
626   ret void
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
646 entry:
647   %gep = getelementptr i32, ptr %x, i64 1
648   store volatile i32 0, ptr %gep, align 4
649   ret void
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
669 entry:
670   %b = call ptr @llvm.launder.invariant.group.p0(ptr %p)
671   store i8 42, ptr %b
672   ret void
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
693   ret void
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
713 entry:
714   %b = call ptr @llvm.strip.invariant.group.p0(ptr %p)
715   store i8 42, ptr %b
716   ret void
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
737   ret void
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
754   ret i1 %1
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
771   ret i1 %1
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
791   ret i1 %2
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
811   ret i1 %2
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
828   ret i1 %1
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
845   ret i1 %1
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)
865   ret void
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)
882   store i8 0, ptr %res
883   ret void
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
900   ret void
904 declare ptr @llvm.launder.invariant.group.p0(ptr)
905 declare ptr @llvm.strip.invariant.group.p0(ptr)