[llvm-readobj] - Simplify stack-sizes.test test case.
[llvm-complete.git] / test / Transforms / FunctionAttrs / nofree-attributor.ll
blobf76b429aa4b33dbdb27eaeacca9090127e3b619c
1 ; RUN: opt -functionattrs --disable-nofree-inference=false -S < %s | FileCheck %s --check-prefix=FNATTR
2 ; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
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(i8* nocapture) local_unnamed_addr #1
11 declare noalias i8* @realloc(i8* nocapture, i64) local_unnamed_addr #0
12 declare void @_ZdaPv(i8*) local_unnamed_addr #2
15 ; TEST 1 (positive case)
16 ; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
17 ; FNATTR-NEXT: define void @only_return()
18 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
19 ; ATTRIBUTOR-NEXT: define void @only_return()
20 define void @only_return() #0 {
21     ret void
25 ; TEST 2 (negative case)
26 ; Only free
27 ; void only_free(char* p) {
28 ;    free(p);
29 ; }
31 ; FNATTR: Function Attrs: noinline nounwind uwtable
32 ; FNATTR-NEXT: define void @only_free(i8* nocapture %0) local_unnamed_addr
33 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
34 ; ATTRIBUTOR-NOT: nofree
35 ; ATTRIBUTOR-NEXT: define void @only_free(i8* nocapture %0) local_unnamed_addr #1
36 define void @only_free(i8* nocapture %0) local_unnamed_addr #0 {
37     tail call void @free(i8* %0) #1
38     ret void
42 ; TEST 3 (negative case)
43 ; Free occurs in same scc.
44 ; void free_in_scc1(char*p){
45 ;    free_in_scc2(p);
46 ; }
47 ; void free_in_scc2(char*p){
48 ;    free_in_scc1(p);
49 ;    free(p);
50 ; }
53 ; FNATTR: Function Attrs: noinline nounwind uwtable
54 ; FNATTR-NEXT: define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr
55 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
56 ; ATTRIBUTOR-NOT: nofree
57 ; ATTRIBUTOR-NEXT :define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr
58 define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr #0 {
59   tail call void @free_in_scc2(i8* %0) #1
60   ret void
64 ; FNATTR: Function Attrs: noinline nounwind uwtable
65 ; FNATTR-NEXT: define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr
66 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
67 ; ATTRIBUTOR-NOT: nofree
68 ; ATTRIBUTOR: define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr
69 define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr #0 {
70   %cmp = icmp eq i8* %0, null
71   br i1 %cmp, label %rec, label %call
72 call:
73   tail call void @free(i8* %0) #1
74   br label %end
75 rec:
76   tail call void @free_in_scc1(i8* %0)
77   br label %end
78 end:
79   ret void
83 ; TEST 4 (positive case)
84 ; Free doesn't occur.
85 ; void mutual_recursion1(){
86 ;    mutual_recursion2();
87 ; }
88 ; void mutual_recursion2(){
89 ;     mutual_recursion1();
90 ; }
93 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
94 ; FNATTR-NEXT: define void @mutual_recursion1()
95 ; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind uwtable
96 ; ATTRIBUTOR-NEXT: define void @mutual_recursion1()
97 define void @mutual_recursion1() #0 {
98   call void @mutual_recursion2()
99   ret void
102 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
103 ; FNATTR-NEXT: define void @mutual_recursion2()
104 ; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind uwtable
105 ; ATTRIBUTOR-NEXT: define void @mutual_recursion2()
106 define void @mutual_recursion2() #0 {
107   call void @mutual_recursion1()
108   ret void
112 ; TEST 5
113 ; C++ delete operation (negative case)
114 ; void delete_op (char p[]){
115 ;     delete [] p;
116 ; }
118 ; FNATTR: Function Attrs: noinline nounwind uwtable
119 ; FNATTR-NEXT: define void @_Z9delete_opPc(i8* %0) local_unnamed_addr
120 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
121 ; ATTRIBUTOR-NOT: nofree
122 ; ATTRIBUTOR-NEXT: define void @_Z9delete_opPc(i8* %0) local_unnamed_addr #1
123 define void @_Z9delete_opPc(i8* %0) local_unnamed_addr #0 {
124   %2 = icmp eq i8* %0, null
125   br i1 %2, label %4, label %3
127 ; <label>:3:                                      ; preds = %1
128   tail call void @_ZdaPv(i8* nonnull %0) #2
129   br label %4
131 ; <label>:4:                                      ; preds = %3, %1
132   ret void
136 ; TEST 6 (negative case)
137 ; Call realloc
138 ; FNATTR: Function Attrs: noinline nounwind uwtable
139 ; FNATTR-NEXT: define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr
140 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
141 ; ATTRIBUTOR-NOT: nofree
142 ; ATTRIBUTOR-NEXT: define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr
143 define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr #0 {
144     %ret = tail call i8* @realloc(i8* %0, i64 %1) #2
145     ret i8* %ret
149 ; TEST 7 (positive case)
150 ; Call function declaration with "nofree"
153 ; FNATTR: Function Attrs: nofree noinline nounwind readnone uwtable
154 ; FNATTR-NEXT: declare void @nofree_function()
155 ; ATTRIBUTOR: Function Attrs:  nofree noinline nounwind readnone uwtable 
156 ; ATTRIBUTOR-NEXT: declare void @nofree_function()
157 declare void @nofree_function() nofree readnone #0
159 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
160 ; FNATTR-NEXT: define void @call_nofree_function()
161 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
162 ; ATTRIBUTOR-NEXT: define void @call_nofree_function()
163 define void @call_nofree_function() #0 {
164     tail call void @nofree_function()
165     ret void
168 ; TEST 8 (negative case)
169 ; Call function declaration without "nofree"
172 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
173 ; ATTRIBUTOR-NEXT: declare void @maybe_free()
174 declare void @maybe_free() #0
177 ; FNATTR: Function Attrs: noinline nounwind uwtable
178 ; FNATTR: define void @call_maybe_free()
179 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
180 ; ATTRIBUTOR-NOT: nofree
181 ; ATTRIBUTOR-NEXT: define void @call_maybe_free()
182 define void @call_maybe_free() #0 {
183     tail call void @maybe_free()
184     ret void
188 ; TEST 9 (negative case)
189 ; Call both of above functions
191 ; FNATTR: Function Attrs: noinline nounwind uwtable
192 ; FNATTR-NEXT: define void @call_both()
193 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
194 ; ATTRIBUTOR-NOT: nofree
195 ; ATTRIBUTOR-NEXT: define void @call_both()
196 define void @call_both() #0 {
197     tail call void @maybe_free()
198     tail call void @nofree_function()
199     ret void
203 ; TEST 10 (positive case)
204 ; Call intrinsic function
205 ; FNATTRS: Function Attrs: noinline readnone speculatable
206 ; FNATTRS-NEXT: declare float @llvm.floor.f32(float %0)
207 ; ATTRIBUTOR: Function Attrs: nounwind readnone speculatable
208 ; ATTRIBUTOR-NEXT: declare float @llvm.floor.f32(float)
209 declare float @llvm.floor.f32(float)
211 ; FNATTRS: Function Attrs: noinline nounwind uwtable
212 ; FNATTRS-NEXT: define void @call_floor(float %a)
213 ; FIXME: missing nofree
214 ; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
215 ; ATTRIBUTOR-NEXT: define void @call_floor(float %a)
217 define void @call_floor(float %a) #0 {
218     tail call float @llvm.floor.f32(float %a)
219     ret void
222 ; TEST 11 (positive case)
223 ; Check propagation.
225 ; FNATTRS: Function Attrs: noinline nounwind uwtable
226 ; FNATTRS-NEXT: define void @f1()
227 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
228 ; ATTRIBUTOR-NEXT: define void @f1()
229 define void @f1() #0 {
230     tail call void @nofree_function()
231     ret void
234 ; FNATTRS: Function Attrs: noinline nounwind uwtable
235 ; FNATTRS-NEXT: define void @f2()
236 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
237 ; ATTRIBUTOR-NEXT: define void @f2()
238 define void @f2() #0 {
239     tail call void @f1()
240     ret void
244 attributes #0 = { nounwind uwtable noinline }
245 attributes #1 = { nounwind }
246 attributes #2 = { nobuiltin nounwind }