Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / FunctionAttrs / nofree-attributor.ll
blobed5534a24cbe8342c79fb8f1492dd675b646df22
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
2 ; RUN: opt -passes=function-attrs --aa-pipeline=basic-aa --disable-nofree-inference=false -S < %s | FileCheck %s --check-prefix=FNATTR
4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
6 ; Test cases specifically designed for the "nofree" function attribute.
7 ; We use FIXME's to indicate problems and missing attributes.
9 ; Free functions
10 declare void @free(ptr nocapture) local_unnamed_addr #1
11 declare noalias ptr @realloc(ptr nocapture, i64) local_unnamed_addr #0
12 declare void @_ZdaPv(ptr) local_unnamed_addr #2
15 ; TEST 1 (positive case)
16 define void @only_return() #0 {
17 ; FNATTR: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
18 ; FNATTR-LABEL: define {{[^@]+}}@only_return
19 ; FNATTR-SAME: () #[[ATTR3:[0-9]+]] {
20 ; FNATTR-NEXT:    ret void
22   ret void
26 ; TEST 2 (negative case)
27 ; Only free
28 ; void only_free(char* p) {
29 ;    free(p);
30 ; }
32 define void @only_free(ptr nocapture %0) local_unnamed_addr #0 {
33 ; FNATTR: Function Attrs: noinline nounwind uwtable
34 ; FNATTR-LABEL: define {{[^@]+}}@only_free
35 ; FNATTR-SAME: (ptr nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
36 ; FNATTR-NEXT:    tail call void @free(ptr [[TMP0]]) #[[ATTR0:[0-9]+]]
37 ; FNATTR-NEXT:    ret void
39   tail call void @free(ptr %0) #1
40   ret void
44 ; TEST 3 (negative case)
45 ; Free occurs in same scc.
46 ; void free_in_scc1(char*p){
47 ;    free_in_scc2(p);
48 ; }
49 ; void free_in_scc2(char*p){
50 ;    free_in_scc1(p);
51 ;    free(p);
52 ; }
54 define void @free_in_scc1(ptr nocapture %0) local_unnamed_addr #0 {
55 ; FNATTR: Function Attrs: noinline nounwind uwtable
56 ; FNATTR-LABEL: define {{[^@]+}}@free_in_scc1
57 ; FNATTR-SAME: (ptr nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
58 ; FNATTR-NEXT:    tail call void @free_in_scc2(ptr [[TMP0]]) #[[ATTR0]]
59 ; FNATTR-NEXT:    ret void
61   tail call void @free_in_scc2(ptr %0) #1
62   ret void
65 define void @free_in_scc2(ptr nocapture %0) local_unnamed_addr #0 {
66 ; FNATTR: Function Attrs: noinline nounwind uwtable
67 ; FNATTR-LABEL: define {{[^@]+}}@free_in_scc2
68 ; FNATTR-SAME: (ptr nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
69 ; FNATTR-NEXT:    [[CMP:%.*]] = icmp eq ptr [[TMP0]], null
70 ; FNATTR-NEXT:    br i1 [[CMP]], label [[REC:%.*]], label [[CALL:%.*]]
71 ; FNATTR:       call:
72 ; FNATTR-NEXT:    tail call void @free(ptr [[TMP0]]) #[[ATTR0]]
73 ; FNATTR-NEXT:    br label [[END:%.*]]
74 ; FNATTR:       rec:
75 ; FNATTR-NEXT:    tail call void @free_in_scc1(ptr [[TMP0]])
76 ; FNATTR-NEXT:    br label [[END]]
77 ; FNATTR:       end:
78 ; FNATTR-NEXT:    ret void
80   %cmp = icmp eq ptr %0, null
81   br i1 %cmp, label %rec, label %call
82 call:
83   tail call void @free(ptr %0) #1
84   br label %end
85 rec:
86   tail call void @free_in_scc1(ptr %0)
87   br label %end
88 end:
89   ret void
93 ; TEST 4 (positive case)
94 ; Free doesn't occur.
95 ; void mutual_recursion1(){
96 ;    mutual_recursion2();
97 ; }
98 ; void mutual_recursion2(){
99 ;     mutual_recursion1();
100 ; }
103 define void @mutual_recursion1() #0 {
104 ; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
105 ; FNATTR-LABEL: define {{[^@]+}}@mutual_recursion1
106 ; FNATTR-SAME: () #[[ATTR4:[0-9]+]] {
107 ; FNATTR-NEXT:    call void @mutual_recursion2()
108 ; FNATTR-NEXT:    ret void
110   call void @mutual_recursion2()
111   ret void
114 define void @mutual_recursion2() #0 {
115 ; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
116 ; FNATTR-LABEL: define {{[^@]+}}@mutual_recursion2
117 ; FNATTR-SAME: () #[[ATTR4]] {
118 ; FNATTR-NEXT:    call void @mutual_recursion1()
119 ; FNATTR-NEXT:    ret void
121   call void @mutual_recursion1()
122   ret void
126 ; TEST 5
127 ; C++ delete operation (negative case)
128 ; void delete_op (char p[]){
129 ;     delete [] p;
130 ; }
132 define void @_Z9delete_opPc(ptr %0) local_unnamed_addr #0 {
133 ; FNATTR: Function Attrs: noinline nounwind uwtable
134 ; FNATTR-LABEL: define {{[^@]+}}@_Z9delete_opPc
135 ; FNATTR-SAME: (ptr [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] {
136 ; FNATTR-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
137 ; FNATTR-NEXT:    br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
138 ; FNATTR:       3:
139 ; FNATTR-NEXT:    tail call void @_ZdaPv(ptr nonnull [[TMP0]]) #[[ATTR2:[0-9]+]]
140 ; FNATTR-NEXT:    br label [[TMP4]]
141 ; FNATTR:       4:
142 ; FNATTR-NEXT:    ret void
144   %2 = icmp eq ptr %0, null
145   br i1 %2, label %4, label %3
147 ; <label>:3:                                      ; preds = %1
148   tail call void @_ZdaPv(ptr nonnull %0) #2
149   br label %4
151 ; <label>:4:                                      ; preds = %3, %1
152   ret void
156 ; TEST 6 (negative case)
157 ; Call realloc
158 define noalias ptr @call_realloc(ptr nocapture %0, i64 %1) local_unnamed_addr #0 {
159 ; FNATTR: Function Attrs: noinline nounwind uwtable
160 ; FNATTR-LABEL: define {{[^@]+}}@call_realloc
161 ; FNATTR-SAME: (ptr nocapture [[TMP0:%.*]], i64 [[TMP1:%.*]]) local_unnamed_addr #[[ATTR1]] {
162 ; FNATTR-NEXT:    [[RET:%.*]] = tail call ptr @realloc(ptr [[TMP0]], i64 [[TMP1]]) #[[ATTR2]]
163 ; FNATTR-NEXT:    ret ptr [[RET]]
165   %ret = tail call ptr @realloc(ptr %0, i64 %1) #2
166   ret ptr %ret
170 ; TEST 7 (positive case)
171 ; Call function declaration with "nofree"
174 declare void @nofree_function() nofree readnone #0
176 define void @call_nofree_function() #0 {
177 ; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
178 ; FNATTR-LABEL: define {{[^@]+}}@call_nofree_function
179 ; FNATTR-SAME: () #[[ATTR4]] {
180 ; FNATTR-NEXT:    tail call void @nofree_function()
181 ; FNATTR-NEXT:    ret void
183   tail call void @nofree_function()
184   ret void
187 ; TEST 8 (negative case)
188 ; Call function declaration without "nofree"
191 declare void @maybe_free() #0
194 define void @call_maybe_free() #0 {
195 ; FNATTR: Function Attrs: noinline nounwind uwtable
196 ; FNATTR-LABEL: define {{[^@]+}}@call_maybe_free
197 ; FNATTR-SAME: () #[[ATTR1]] {
198 ; FNATTR-NEXT:    tail call void @maybe_free()
199 ; FNATTR-NEXT:    ret void
201   tail call void @maybe_free()
202   ret void
206 ; TEST 9 (negative case)
207 ; Call both of above functions
209 define void @call_both() #0 {
210 ; FNATTR: Function Attrs: noinline nounwind uwtable
211 ; FNATTR-LABEL: define {{[^@]+}}@call_both
212 ; FNATTR-SAME: () #[[ATTR1]] {
213 ; FNATTR-NEXT:    tail call void @maybe_free()
214 ; FNATTR-NEXT:    tail call void @nofree_function()
215 ; FNATTR-NEXT:    ret void
217   tail call void @maybe_free()
218   tail call void @nofree_function()
219   ret void
223 ; TEST 10 (positive case)
224 ; Call intrinsic function
225 declare float @llvm.floor.f32(float)
227 define void @call_floor(float %a) #0 {
228 ; FNATTR: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
229 ; FNATTR-LABEL: define {{[^@]+}}@call_floor
230 ; FNATTR-SAME: (float [[A:%.*]]) #[[ATTR3]] {
231 ; FNATTR-NEXT:    [[TMP1:%.*]] = tail call float @llvm.floor.f32(float [[A]])
232 ; FNATTR-NEXT:    ret void
234   tail call float @llvm.floor.f32(float %a)
235   ret void
238 ; TEST 11 (positive case)
239 ; Check propagation.
241 define void @f1() #0 {
242 ; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
243 ; FNATTR-LABEL: define {{[^@]+}}@f1
244 ; FNATTR-SAME: () #[[ATTR4]] {
245 ; FNATTR-NEXT:    tail call void @nofree_function()
246 ; FNATTR-NEXT:    ret void
248   tail call void @nofree_function()
249   ret void
252 define void @f2() #0 {
253 ; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
254 ; FNATTR-LABEL: define {{[^@]+}}@f2
255 ; FNATTR-SAME: () #[[ATTR4]] {
256 ; FNATTR-NEXT:    tail call void @f1()
257 ; FNATTR-NEXT:    ret void
259   tail call void @f1()
260   ret void
264 declare noalias ptr @malloc(i64)
266 attributes #0 = { nounwind uwtable noinline }
267 attributes #1 = { nounwind }
268 attributes #2 = { nobuiltin nounwind }