1 ; RUN: opt -functionattrs --disable-nofree-inference=false -S < %s | FileCheck %s --check-prefix=FNATTR
2 ; RUN: opt -attributor --attributor-disable=false -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.
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 {
25 ; TEST 2 (negative case)
27 ; void only_free(char* p) {
31 ; FNATTR: Function Attrs: noinline nounwind uwtable
32 ; FNATTR-NEXT: define void @only_free(i8* nocapture) local_unnamed_addr
33 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
34 ; ATTRIBUTOR-NOT: nofree
35 ; ATTRIBUTOR-NEXT: define void @only_free(i8* nocapture) local_unnamed_addr #1
36 define void @only_free(i8* nocapture) local_unnamed_addr #0 {
37 tail call void @free(i8* %0) #1
42 ; TEST 3 (negative case)
43 ; Free occurs in same scc.
44 ; void free_in_scc1(char*p){
47 ; void free_in_scc2(char*p){
53 ; FNATTR: Function Attrs: noinline nounwind uwtable
54 ; FNATTR-NEXT: define void @free_in_scc1(i8* nocapture) local_unnamed_addr
55 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
56 ; ATTRIBUTOR-NOT: nofree
57 ; ATTRIBUTOR-NEXT :define void @free_in_scc1(i8* nocapture) local_unnamed_addr
58 define void @free_in_scc1(i8* nocapture) local_unnamed_addr #0 {
59 tail call void @free_in_scc2(i8* %0) #1
64 ; FNATTR: Function Attrs: noinline nounwind uwtable
65 ; FNATTR-NEXT: define void @free_in_scc2(i8* nocapture) local_unnamed_addr
66 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
67 ; ATTRIBUTOR-NOT: nofree
68 ; ATTRIBUTOR: define void @free_in_scc2(i8* nocapture) local_unnamed_addr
69 define void @free_in_scc2(i8* nocapture) local_unnamed_addr #0 {
70 tail call void @free_in_scc1(i8* %0)
71 tail call void @free(i8* %0) #1
76 ; TEST 4 (positive case)
78 ; void mutual_recursion1(){
79 ; mutual_recursion2();
81 ; void mutual_recursion2(){
82 ; mutual_recursion1();
86 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
87 ; FNATTR-NEXT: define void @mutual_recursion1()
88 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
89 ; ATTRIBUTOR-NEXT: define void @mutual_recursion1()
90 define void @mutual_recursion1() #0 {
91 call void @mutual_recursion2()
95 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
96 ; FNATTR-NEXT: define void @mutual_recursion2()
97 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
98 ; ATTRIBUTOR-NEXT: define void @mutual_recursion2()
99 define void @mutual_recursion2() #0 {
100 call void @mutual_recursion1()
106 ; C++ delete operation (negative case)
107 ; void delete_op (char p[]){
111 ; FNATTR: Function Attrs: noinline nounwind uwtable
112 ; FNATTR-NEXT: define void @_Z9delete_opPc(i8*) local_unnamed_addr
113 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
114 ; ATTRIBUTOR-NOT: nofree
115 ; ATTRIBUTOR-NEXT: define void @_Z9delete_opPc(i8*) local_unnamed_addr #1
116 define void @_Z9delete_opPc(i8*) local_unnamed_addr #0 {
117 %2 = icmp eq i8* %0, null
118 br i1 %2, label %4, label %3
120 ; <label>:3: ; preds = %1
121 tail call void @_ZdaPv(i8* nonnull %0) #2
124 ; <label>:4: ; preds = %3, %1
129 ; TEST 6 (negative case)
131 ; FNATTR: Function Attrs: noinline nounwind uwtable
132 ; FNATTR-NEXT: define noalias i8* @call_realloc(i8* nocapture, i64) local_unnamed_addr
133 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
134 ; ATTRIBUTOR-NOT: nofree
135 ; ATTRIBUTOR-NEXT: define noalias i8* @call_realloc(i8* nocapture, i64) local_unnamed_addr
136 define noalias i8* @call_realloc(i8* nocapture, i64) local_unnamed_addr #0 {
137 %ret = tail call i8* @realloc(i8* %0, i64 %1) #2
142 ; TEST 7 (positive case)
143 ; Call function declaration with "nofree"
146 ; FNATTR: Function Attrs: nofree noinline nounwind readnone uwtable
147 ; FNATTR-NEXT: declare void @nofree_function()
148 ; ATTRIBUTOR: Function Attrs: nofree noinline nounwind readnone uwtable
149 ; ATTRIBUTOR-NEXT: declare void @nofree_function()
150 declare void @nofree_function() nofree readnone #0
152 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
153 ; FNATTR-NEXT: define void @call_nofree_function()
154 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
155 ; ATTRIBUTOR-NEXT: define void @call_nofree_function()
156 define void @call_nofree_function() #0 {
157 tail call void @nofree_function()
161 ; TEST 8 (negative case)
162 ; Call function declaration without "nofree"
165 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
166 ; ATTRIBUTOR-NEXT: declare void @maybe_free()
167 declare void @maybe_free() #0
170 ; FNATTR: Function Attrs: noinline nounwind uwtable
171 ; FNATTR: define void @call_maybe_free()
172 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
173 ; ATTRIBUTOR-NOT: nofree
174 ; ATTRIBUTOR-NEXT: define void @call_maybe_free()
175 define void @call_maybe_free() #0 {
176 tail call void @maybe_free()
181 ; TEST 9 (negative case)
182 ; Call both of above functions
184 ; FNATTR: Function Attrs: noinline nounwind uwtable
185 ; FNATTR-NEXT: define void @call_both()
186 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
187 ; ATTRIBUTOR-NOT: nofree
188 ; ATTRIBUTOR-NEXT: define void @call_both()
189 define void @call_both() #0 {
190 tail call void @maybe_free()
191 tail call void @nofree_function()
196 ; TEST 10 (positive case)
197 ; Call intrinsic function
198 ; FNATTRS: Function Attrs: noinline readnone speculatable
199 ; FNATTRS-NEXT: declare float @llvm.floor.f32(float)
200 ; ATTRIBUTOR: Function Attrs: nounwind readnone speculatable
201 ; ATTRIBUTOR-NEXT: declare float @llvm.floor.f32(float)
202 declare float @llvm.floor.f32(float)
204 ; FNATTRS: Function Attrs: noinline nounwind uwtable
205 ; FNATTRS-NEXT: define void @call_floor(float %a)
206 ; FIXME: missing nofree
207 ; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
208 ; ATTRIBUTOR-NEXT: define void @call_floor(float %a)
210 define void @call_floor(float %a) #0 {
211 tail call float @llvm.floor.f32(float %a)
215 ; TEST 11 (positive case)
218 ; FNATTRS: Function Attrs: noinline nounwind uwtable
219 ; FNATTRS-NEXT: define void @f1()
220 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
221 ; ATTRIBUTOR-NEXT: define void @f1()
222 define void @f1() #0 {
223 tail call void @nofree_function()
227 ; FNATTRS: Function Attrs: noinline nounwind uwtable
228 ; FNATTRS-NEXT: define void @f2()
229 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
230 ; ATTRIBUTOR-NEXT: define void @f2()
231 define void @f2() #0 {
237 attributes #0 = { nounwind uwtable noinline }
238 attributes #1 = { nounwind }
239 attributes #2 = { nobuiltin nounwind }