[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / test / Transforms / Attributor / nofree.ll
blobeafb16823fdf1434af55af3beda4eab9fa93ea25
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
5 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7 ; Test cases specifically designed for the "nofree" function attribute.
8 ; We use FIXME's to indicate problems and missing attributes.
10 ; Free functions
11 declare void @free(ptr nocapture) local_unnamed_addr #1
12 declare noalias ptr @realloc(ptr nocapture, i64) local_unnamed_addr #0
13 declare void @_ZdaPv(ptr) local_unnamed_addr #2
16 ; TEST 1 (positive case)
17 define void @only_return() #0 {
18 ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
19 ; CHECK-LABEL: define {{[^@]+}}@only_return
20 ; CHECK-SAME: () #[[ATTR3:[0-9]+]] {
21 ; CHECK-NEXT:    ret void
23   ret void
27 ; TEST 2 (negative case)
28 ; Only free
29 ; void only_free(char* p) {
30 ;    free(p);
31 ; }
33 define void @only_free(ptr nocapture %0) local_unnamed_addr #0 {
34 ; CHECK: Function Attrs: noinline nounwind uwtable
35 ; CHECK-LABEL: define {{[^@]+}}@only_free
36 ; CHECK-SAME: (ptr nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
37 ; CHECK-NEXT:    tail call void @free(ptr nocapture [[TMP0]]) #[[ATTR0:[0-9]+]]
38 ; CHECK-NEXT:    ret void
40   tail call void @free(ptr %0) #1
41   ret void
45 ; TEST 3 (negative case)
46 ; Free occurs in same scc.
47 ; void free_in_scc1(char*p){
48 ;    free_in_scc2(p);
49 ; }
50 ; void free_in_scc2(char*p){
51 ;    free_in_scc1(p);
52 ;    free(p);
53 ; }
56 define void @free_in_scc1(ptr nocapture %0) local_unnamed_addr #0 {
57 ; CHECK: Function Attrs: noinline nounwind uwtable
58 ; CHECK-LABEL: define {{[^@]+}}@free_in_scc1
59 ; CHECK-SAME: (ptr nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
60 ; CHECK-NEXT:    tail call void @free_in_scc2(ptr nocapture [[TMP0]]) #[[ATTR0]]
61 ; CHECK-NEXT:    ret void
63   tail call void @free_in_scc2(ptr %0) #1
64   ret void
68 define void @free_in_scc2(ptr nocapture %0) local_unnamed_addr #0 {
69 ; CHECK: Function Attrs: noinline nounwind uwtable
70 ; CHECK-LABEL: define {{[^@]+}}@free_in_scc2
71 ; CHECK-SAME: (ptr nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
72 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[TMP0]], null
73 ; CHECK-NEXT:    br i1 [[CMP]], label [[REC:%.*]], label [[CALL:%.*]]
74 ; CHECK:       call:
75 ; CHECK-NEXT:    tail call void @free(ptr nocapture nonnull [[TMP0]]) #[[ATTR0]]
76 ; CHECK-NEXT:    br label [[END:%.*]]
77 ; CHECK:       rec:
78 ; CHECK-NEXT:    tail call void @free_in_scc1(ptr nocapture [[TMP0]]) #[[ATTR0]]
79 ; CHECK-NEXT:    br label [[END]]
80 ; CHECK:       end:
81 ; CHECK-NEXT:    ret void
83   %cmp = icmp eq ptr %0, null
84   br i1 %cmp, label %rec, label %call
85 call:
86   tail call void @free(ptr %0) #1
87   br label %end
88 rec:
89   tail call void @free_in_scc1(ptr %0)
90   br label %end
91 end:
92   ret void
96 ; TEST 4 (positive case)
97 ; Free doesn't occur.
98 ; void mutual_recursion1(){
99 ;    mutual_recursion2();
100 ; }
101 ; void mutual_recursion2(){
102 ;     mutual_recursion1();
103 ; }
106 define void @mutual_recursion1() #0 {
107 ; TUNIT: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
108 ; TUNIT-LABEL: define {{[^@]+}}@mutual_recursion1
109 ; TUNIT-SAME: () #[[ATTR4:[0-9]+]] {
110 ; TUNIT-NEXT:    ret void
112 ; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
113 ; CGSCC-LABEL: define {{[^@]+}}@mutual_recursion1
114 ; CGSCC-SAME: () #[[ATTR3]] {
115 ; CGSCC-NEXT:    ret void
117   call void @mutual_recursion2()
118   ret void
121 define void @mutual_recursion2() #0 {
122 ; TUNIT: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
123 ; TUNIT-LABEL: define {{[^@]+}}@mutual_recursion2
124 ; TUNIT-SAME: () #[[ATTR4]] {
125 ; TUNIT-NEXT:    ret void
127 ; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
128 ; CGSCC-LABEL: define {{[^@]+}}@mutual_recursion2
129 ; CGSCC-SAME: () #[[ATTR3]] {
130 ; CGSCC-NEXT:    ret void
132   call void @mutual_recursion1()
133   ret void
137 ; TEST 5
138 ; C++ delete operation (negative case)
139 ; void delete_op (char p[]){
140 ;     delete [] p;
141 ; }
143 define void @_Z9delete_opPc(ptr %0) local_unnamed_addr #0 {
144 ; CHECK: Function Attrs: noinline nounwind uwtable
145 ; CHECK-LABEL: define {{[^@]+}}@_Z9delete_opPc
146 ; CHECK-SAME: (ptr [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
147 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
148 ; CHECK-NEXT:    br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
149 ; CHECK:       3:
150 ; CHECK-NEXT:    tail call void @_ZdaPv(ptr nonnull [[TMP0]]) #[[ATTR2:[0-9]+]]
151 ; CHECK-NEXT:    br label [[TMP4]]
152 ; CHECK:       4:
153 ; CHECK-NEXT:    ret void
155   %2 = icmp eq ptr %0, null
156   br i1 %2, label %4, label %3
158 ; <label>:3:                                      ; preds = %1
159   tail call void @_ZdaPv(ptr nonnull %0) #2
160   br label %4
162 ; <label>:4:                                      ; preds = %3, %1
163   ret void
167 ; TEST 6 (negative case)
168 ; Call realloc
169 define noalias ptr @call_realloc(ptr nocapture %0, i64 %1) local_unnamed_addr #0 {
170 ; CHECK: Function Attrs: noinline nounwind uwtable
171 ; CHECK-LABEL: define {{[^@]+}}@call_realloc
172 ; CHECK-SAME: (ptr nocapture [[TMP0:%.*]], i64 [[TMP1:%.*]]) local_unnamed_addr #[[ATTR1]] {
173 ; CHECK-NEXT:    [[RET:%.*]] = tail call ptr @realloc(ptr nocapture [[TMP0]], i64 [[TMP1]]) #[[ATTR2]]
174 ; CHECK-NEXT:    ret ptr [[RET]]
176   %ret = tail call ptr @realloc(ptr %0, i64 %1) #2
177   ret ptr %ret
181 ; TEST 7 (positive case)
182 ; Call function declaration with "nofree"
185 ; CHECK: Function Attrs:  nofree noinline nounwind memory(none) uwtable
186 ; CHECK-NEXT: declare void @nofree_function()
187 declare void @nofree_function() nofree readnone #0
189 define void @call_nofree_function() #0 {
190 ; TUNIT: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
191 ; TUNIT-LABEL: define {{[^@]+}}@call_nofree_function
192 ; TUNIT-SAME: () #[[ATTR4]] {
193 ; TUNIT-NEXT:    ret void
195 ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
196 ; CGSCC-LABEL: define {{[^@]+}}@call_nofree_function
197 ; CGSCC-SAME: () #[[ATTR5:[0-9]+]] {
198 ; CGSCC-NEXT:    ret void
200   tail call void @nofree_function()
201   ret void
204 ; TEST 8 (negative case)
205 ; Call function declaration without "nofree"
208 ; CHECK: Function Attrs: noinline nounwind uwtable
209 ; CHECK-NEXT: declare void @maybe_free()
210 declare void @maybe_free() #0
213 define void @call_maybe_free() #0 {
214 ; CHECK: Function Attrs: noinline nounwind uwtable
215 ; CHECK-LABEL: define {{[^@]+}}@call_maybe_free
216 ; CHECK-SAME: () #[[ATTR1]] {
217 ; CHECK-NEXT:    tail call void @maybe_free() #[[ATTR0]]
218 ; CHECK-NEXT:    ret void
220   tail call void @maybe_free()
221   ret void
225 ; TEST 9 (negative case)
226 ; Call both of above functions
228 define void @call_both() #0 {
229 ; CHECK: Function Attrs: noinline nounwind uwtable
230 ; CHECK-LABEL: define {{[^@]+}}@call_both
231 ; CHECK-SAME: () #[[ATTR1]] {
232 ; CHECK-NEXT:    tail call void @maybe_free() #[[ATTR0]]
233 ; CHECK-NEXT:    ret void
235   tail call void @maybe_free()
236   tail call void @nofree_function()
237   ret void
241 ; TEST 10 (positive case)
242 ; Call intrinsic function
243 ; CHECK: Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
244 ; CHECK-NEXT: declare float @llvm.floor.f32(float)
245 declare float @llvm.floor.f32(float)
247 define void @call_floor(float %a) #0 {
248 ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
249 ; CHECK-LABEL: define {{[^@]+}}@call_floor
250 ; CHECK-SAME: (float [[A:%.*]]) #[[ATTR3]] {
251 ; CHECK-NEXT:    ret void
253   tail call float @llvm.floor.f32(float %a)
254   ret void
257 define float @call_floor2(float %a) #0 {
258 ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
259 ; CHECK-LABEL: define {{[^@]+}}@call_floor2
260 ; CHECK-SAME: (float nofpclass(sub) [[A:%.*]]) #[[ATTR3]] {
261 ; CHECK-NEXT:    [[C:%.*]] = tail call nofpclass(sub) float @llvm.floor.f32(float nofpclass(sub) [[A]]) #[[ATTR14:[0-9]+]]
262 ; CHECK-NEXT:    ret float [[C]]
264   %c = tail call float @llvm.floor.f32(float %a)
265   ret float %c
268 ; TEST 11 (positive case)
269 ; Check propagation.
271 define void @f1() #0 {
272 ; TUNIT: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
273 ; TUNIT-LABEL: define {{[^@]+}}@f1
274 ; TUNIT-SAME: () #[[ATTR4]] {
275 ; TUNIT-NEXT:    ret void
277 ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
278 ; CGSCC-LABEL: define {{[^@]+}}@f1
279 ; CGSCC-SAME: () #[[ATTR5]] {
280 ; CGSCC-NEXT:    ret void
282   tail call void @nofree_function()
283   ret void
286 define void @f2() #0 {
287 ; TUNIT: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
288 ; TUNIT-LABEL: define {{[^@]+}}@f2
289 ; TUNIT-SAME: () #[[ATTR4]] {
290 ; TUNIT-NEXT:    ret void
292 ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
293 ; CGSCC-LABEL: define {{[^@]+}}@f2
294 ; CGSCC-SAME: () #[[ATTR5]] {
295 ; CGSCC-NEXT:    ret void
297   tail call void @f1()
298   ret void
301 ; TEST 12 NoFree argument - positive.
302 define double @test12(ptr nocapture readonly %a) {
303 ; CHECK: Function Attrs: nofree nounwind
304 ; CHECK-LABEL: define {{[^@]+}}@test12
305 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR7:[0-9]+]] {
306 ; CHECK-NEXT:  entry:
307 ; CHECK-NEXT:    [[TMP0:%.*]] = load double, ptr [[A]], align 8
308 ; CHECK-NEXT:    [[CALL:%.*]] = tail call double @cos(double [[TMP0]]) #[[ATTR8:[0-9]+]]
309 ; CHECK-NEXT:    ret double [[CALL]]
311 entry:
312   %0 = load double, ptr %a, align 8
313   %call = tail call double @cos(double %0) #2
314   ret double %call
317 declare double @cos(double) nobuiltin nounwind nofree
319 ; FIXME: %a should be nofree.
320 ; TEST 13 NoFree argument - positive.
321 define noalias ptr @test13(ptr nocapture readonly %a) {
322 ; CHECK: Function Attrs: nounwind
323 ; CHECK-LABEL: define {{[^@]+}}@test13
324 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR0]] {
325 ; CHECK-NEXT:  entry:
326 ; CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr [[A]], align 8
327 ; CHECK-NEXT:    [[CALL:%.*]] = tail call noalias ptr @malloc(i64 [[TMP0]]) #[[ATTR2]]
328 ; CHECK-NEXT:    ret ptr [[CALL]]
330 entry:
331   %0 = load i64, ptr %a, align 8
332   %call = tail call noalias ptr @malloc(i64 %0) #2
333   ret ptr %call
336 define void @test14(ptr nocapture %0, ptr nocapture %1) {
337 ; CHECK: Function Attrs: nounwind
338 ; CHECK-LABEL: define {{[^@]+}}@test14
339 ; CHECK-SAME: (ptr nocapture [[TMP0:%.*]], ptr nocapture nofree readnone [[TMP1:%.*]]) #[[ATTR0]] {
340 ; CHECK-NEXT:    tail call void @free(ptr nocapture [[TMP0]]) #[[ATTR0]]
341 ; CHECK-NEXT:    ret void
343   tail call void @free(ptr %0) #1
344   ret void
347 ; UTC_ARGS: --enable
349 define void @nonnull_assume_pos(ptr %arg1, ptr %arg2, ptr %arg3, ptr %arg4) {
350 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_pos
351 ; ATTRIBUTOR-SAME: (ptr nofree [[ARG1:%.*]], ptr [[ARG2:%.*]], ptr nofree [[ARG3:%.*]], ptr [[ARG4:%.*]])
352 ; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) #11 [ "nofree"(ptr [[ARG1]]), "nofree"(ptr [[ARG3]]) ]
353 ; ATTRIBUTOR-NEXT:    call void @unknown(ptr nofree [[ARG1]], ptr [[ARG2]], ptr nofree [[ARG3]], ptr [[ARG4]])
354 ; ATTRIBUTOR-NEXT:    ret void
356 ; CHECK-LABEL: define {{[^@]+}}@nonnull_assume_pos
357 ; CHECK-SAME: (ptr nofree [[ARG1:%.*]], ptr [[ARG2:%.*]], ptr nofree [[ARG3:%.*]], ptr [[ARG4:%.*]]) {
358 ; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR15:[0-9]+]] [ "nofree"(ptr [[ARG1]]), "nofree"(ptr [[ARG3]]) ]
359 ; CHECK-NEXT:    call void @unknown(ptr nofree [[ARG1]], ptr [[ARG2]], ptr nofree [[ARG3]], ptr [[ARG4]])
360 ; CHECK-NEXT:    ret void
362   call void @llvm.assume(i1 true) ["nofree"(ptr %arg1), "nofree"(ptr %arg3)]
363   call void @unknown(ptr %arg1, ptr %arg2, ptr %arg3, ptr %arg4)
364   ret void
366 define void @nonnull_assume_neg(ptr %arg1, ptr %arg2, ptr %arg3, ptr %arg4) {
367 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_neg
368 ; ATTRIBUTOR-SAME: (ptr [[ARG1:%.*]], ptr [[ARG2:%.*]], ptr [[ARG3:%.*]], ptr [[ARG4:%.*]])
369 ; ATTRIBUTOR-NEXT:    call void @unknown(ptr [[ARG1]], ptr [[ARG2]], ptr [[ARG3]], ptr [[ARG4]])
370 ; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) [ "nofree"(ptr [[ARG1]]), "nofree"(ptr [[ARG3]]) ]
371 ; ATTRIBUTOR-NEXT:    ret void
373 ; CHECK-LABEL: define {{[^@]+}}@nonnull_assume_neg
374 ; CHECK-SAME: (ptr [[ARG1:%.*]], ptr [[ARG2:%.*]], ptr [[ARG3:%.*]], ptr [[ARG4:%.*]]) {
375 ; CHECK-NEXT:    call void @unknown(ptr [[ARG1]], ptr [[ARG2]], ptr [[ARG3]], ptr [[ARG4]])
376 ; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) [ "nofree"(ptr [[ARG1]]), "nofree"(ptr [[ARG3]]) ]
377 ; CHECK-NEXT:    ret void
379   call void @unknown(ptr %arg1, ptr %arg2, ptr %arg3, ptr %arg4)
380   call void @llvm.assume(i1 true) ["nofree"(ptr %arg1), "nofree"(ptr %arg3)]
381   ret void
383 define void @nonnull_assume_call(ptr %arg1, ptr %arg2, ptr %arg3, ptr %arg4) {
384 ; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_call
385 ; ATTRIBUTOR-SAME: (ptr [[ARG1:%.*]], ptr [[ARG2:%.*]], ptr [[ARG3:%.*]], ptr [[ARG4:%.*]])
386 ; ATTRIBUTOR-NEXT:    call void @unknown(ptr [[ARG1]], ptr [[ARG2]], ptr [[ARG3]], ptr [[ARG4]])
387 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(ptr noalias readnone [[ARG1]])
388 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(ptr noalias readnone [[ARG2]])
389 ; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) [ "nofree"(ptr [[ARG1]]), "nofree"(ptr [[ARG3]]) ]
390 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(ptr noalias nofree readnone [[ARG3]])
391 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(ptr noalias readnone [[ARG4]])
392 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr_ret(ptr noalias nofree readnone [[ARG1]])
393 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr_ret(ptr noalias readnone [[ARG2]])
394 ; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) [ "nofree"(ptr [[ARG1]]), "nofree"(ptr [[ARG4]]) ]
395 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr_ret(ptr noalias nofree readnone [[ARG3]])
396 ; ATTRIBUTOR-NEXT:    call void @use_i8_ptr_ret(ptr noalias nofree readnone [[ARG4]])
397 ; ATTRIBUTOR-NEXT:    ret void
399 ; CHECK-LABEL: define {{[^@]+}}@nonnull_assume_call
400 ; CHECK-SAME: (ptr [[ARG1:%.*]], ptr [[ARG2:%.*]], ptr [[ARG3:%.*]], ptr [[ARG4:%.*]]) {
401 ; CHECK-NEXT:    call void @unknown(ptr [[ARG1]], ptr [[ARG2]], ptr [[ARG3]], ptr [[ARG4]])
402 ; CHECK-NEXT:    call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[ARG1]]) #[[ATTR0]]
403 ; CHECK-NEXT:    call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[ARG2]]) #[[ATTR0]]
404 ; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) [ "nofree"(ptr [[ARG1]]), "nofree"(ptr [[ARG3]]) ]
405 ; CHECK-NEXT:    call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[ARG3]]) #[[ATTR0]]
406 ; CHECK-NEXT:    call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[ARG4]]) #[[ATTR0]]
407 ; CHECK-NEXT:    call void @use_i8_ptr_ret(ptr noalias nocapture nofree readnone [[ARG1]]) #[[ATTR0]]
408 ; CHECK-NEXT:    call void @use_i8_ptr_ret(ptr noalias nocapture nofree readnone [[ARG2]]) #[[ATTR0]]
409 ; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) [ "nofree"(ptr [[ARG1]]), "nofree"(ptr [[ARG4]]) ]
410 ; CHECK-NEXT:    call void @use_i8_ptr_ret(ptr noalias nocapture nofree readnone [[ARG3]]) #[[ATTR0]]
411 ; CHECK-NEXT:    call void @use_i8_ptr_ret(ptr noalias nocapture nofree readnone [[ARG4]]) #[[ATTR0]]
412 ; CHECK-NEXT:    ret void
414   call void @unknown(ptr %arg1, ptr %arg2, ptr %arg3, ptr %arg4)
415   call void @use_i8_ptr(ptr %arg1)
416   call void @use_i8_ptr(ptr %arg2)
417   call void @llvm.assume(i1 true) ["nofree"(ptr %arg1), "nofree"(ptr %arg3)]
418   call void @use_i8_ptr(ptr %arg3)
419   call void @use_i8_ptr(ptr %arg4)
420   call void @use_i8_ptr_ret(ptr %arg1)
421   call void @use_i8_ptr_ret(ptr %arg2)
422   call void @llvm.assume(i1 true) ["nofree"(ptr %arg1), "nofree"(ptr %arg4)]
423   call void @use_i8_ptr_ret(ptr %arg3)
424   call void @use_i8_ptr_ret(ptr %arg4)
425   ret void
428 ; FIXME: function is nofree
429 define weak void @implied_nofree1() readnone {
430 ; CHECK: Function Attrs: nosync memory(none)
431 ; CHECK-LABEL: define {{[^@]+}}@implied_nofree1
432 ; CHECK-SAME: () #[[ATTR9:[0-9]+]] {
433 ; CHECK-NEXT:    ret void
435   ret void
437 ; FIXME: function is nofree
438 define weak void @implied_nofree2() readonly {
439 ; CHECK: Function Attrs: nosync memory(read)
440 ; CHECK-LABEL: define {{[^@]+}}@implied_nofree2
441 ; CHECK-SAME: () #[[ATTR10:[0-9]+]] {
442 ; CHECK-NEXT:    ret void
444   ret void
446 define weak void @implied_nofree3(ptr readnone %a) {
447 ; CHECK-LABEL: define {{[^@]+}}@implied_nofree3
448 ; CHECK-SAME: (ptr nofree readnone [[A:%.*]]) {
449 ; CHECK-NEXT:    ret void
451   ret void
453 define weak void @implied_nofree4(ptr readonly %a) {
454 ; CHECK-LABEL: define {{[^@]+}}@implied_nofree4
455 ; CHECK-SAME: (ptr nofree readonly [[A:%.*]]) {
456 ; CHECK-NEXT:    ret void
458   ret void
460 ; FIXME: %a is nofree
461 define weak void @implied_nofree5(ptr %a) readonly {
462 ; CHECK: Function Attrs: nosync memory(read)
463 ; CHECK-LABEL: define {{[^@]+}}@implied_nofree5
464 ; CHECK-SAME: (ptr [[A:%.*]]) #[[ATTR10]] {
465 ; CHECK-NEXT:    ret void
467   ret void
469 define weak void @implied_nofree6(ptr %a) nofree {
470 ; CHECK: Function Attrs: nofree
471 ; CHECK-LABEL: define {{[^@]+}}@implied_nofree6
472 ; CHECK-SAME: (ptr nofree [[A:%.*]]) #[[ATTR11:[0-9]+]] {
473 ; CHECK-NEXT:    ret void
475   ret void
478 declare void @llvm.assume(i1)
479 declare void @unknown(ptr, ptr, ptr, ptr)
480 declare void @use_i8_ptr(ptr nocapture readnone) nounwind
481 declare void @use_i8_ptr_ret(ptr nocapture readnone) nounwind willreturn
483 declare noalias ptr @malloc(i64)
485 attributes #0 = { nounwind uwtable noinline }
486 attributes #1 = { nounwind }
487 attributes #2 = { nobuiltin nounwind }
489 ; TUNIT: attributes #[[ATTR0]] = { nounwind }
490 ; TUNIT: attributes #[[ATTR1]] = { noinline nounwind uwtable }
491 ; TUNIT: attributes #[[ATTR2]] = { nobuiltin nounwind }
492 ; TUNIT: attributes #[[ATTR3]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable }
493 ; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable }
494 ; TUNIT: attributes #[[ATTR5:[0-9]+]] = { nofree noinline nounwind memory(none) uwtable }
495 ; TUNIT: attributes #[[ATTR6:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
496 ; TUNIT: attributes #[[ATTR7]] = { nofree nounwind }
497 ; TUNIT: attributes #[[ATTR8]] = { nobuiltin nofree nounwind }
498 ; TUNIT: attributes #[[ATTR9]] = { nosync memory(none) }
499 ; TUNIT: attributes #[[ATTR10]] = { nosync memory(read) }
500 ; TUNIT: attributes #[[ATTR11]] = { nofree }
501 ; TUNIT: attributes #[[ATTR12:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
502 ; TUNIT: attributes #[[ATTR13:[0-9]+]] = { nounwind willreturn }
503 ; TUNIT: attributes #[[ATTR14]] = { nofree nosync willreturn }
504 ; TUNIT: attributes #[[ATTR15]] = { nofree willreturn memory(write) }
506 ; CGSCC: attributes #[[ATTR0]] = { nounwind }
507 ; CGSCC: attributes #[[ATTR1]] = { noinline nounwind uwtable }
508 ; CGSCC: attributes #[[ATTR2]] = { nobuiltin nounwind }
509 ; CGSCC: attributes #[[ATTR3]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable }
510 ; CGSCC: attributes #[[ATTR4:[0-9]+]] = { nofree noinline nounwind memory(none) uwtable }
511 ; CGSCC: attributes #[[ATTR5]] = { mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable }
512 ; CGSCC: attributes #[[ATTR6:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
513 ; CGSCC: attributes #[[ATTR7]] = { nofree nounwind }
514 ; CGSCC: attributes #[[ATTR8]] = { nobuiltin nofree nounwind }
515 ; CGSCC: attributes #[[ATTR9]] = { nosync memory(none) }
516 ; CGSCC: attributes #[[ATTR10]] = { nosync memory(read) }
517 ; CGSCC: attributes #[[ATTR11]] = { nofree }
518 ; CGSCC: attributes #[[ATTR12:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
519 ; CGSCC: attributes #[[ATTR13:[0-9]+]] = { nounwind willreturn }
520 ; CGSCC: attributes #[[ATTR14]] = { nofree nosync willreturn }
521 ; CGSCC: attributes #[[ATTR15]] = { nofree willreturn memory(write) }