[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / FunctionAttrs / nofree-attributor.ll
blob30677976260804449b5e2318801c29122b7ae0f8
1 ; RUN: opt -enable-new-pm=1 -function-attrs --disable-nofree-inference=false -S < %s | FileCheck %s --check-prefix=FNATTR
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5 ; Test cases specifically designed for the "nofree" function attribute.
6 ; We use FIXME's to indicate problems and missing attributes.
8 ; Free functions
9 declare void @free(i8* nocapture) local_unnamed_addr #1
10 declare noalias i8* @realloc(i8* nocapture, i64) local_unnamed_addr #0
11 declare void @_ZdaPv(i8*) local_unnamed_addr #2
14 ; TEST 1 (positive case)
15 ; FNATTR: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind readnone uwtable
16 ; FNATTR-NEXT: define void @only_return()
17 define void @only_return() #0 {
18     ret void
22 ; TEST 2 (negative case)
23 ; Only free
24 ; void only_free(char* p) {
25 ;    free(p);
26 ; }
28 ; FNATTR: Function Attrs: noinline nounwind uwtable
29 ; FNATTR-NEXT: define void @only_free(i8* nocapture %0) local_unnamed_addr
30 define void @only_free(i8* nocapture %0) local_unnamed_addr #0 {
31     tail call void @free(i8* %0) #1
32     ret void
36 ; TEST 3 (negative case)
37 ; Free occurs in same scc.
38 ; void free_in_scc1(char*p){
39 ;    free_in_scc2(p);
40 ; }
41 ; void free_in_scc2(char*p){
42 ;    free_in_scc1(p);
43 ;    free(p);
44 ; }
47 ; FNATTR: Function Attrs: noinline nounwind uwtable
48 ; FNATTR-NEXT: define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr
49 define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr #0 {
50   tail call void @free_in_scc2(i8* %0) #1
51   ret void
55 ; FNATTR: Function Attrs: noinline nounwind uwtable
56 ; FNATTR-NEXT: define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr
57 define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr #0 {
58   %cmp = icmp eq i8* %0, null
59   br i1 %cmp, label %rec, label %call
60 call:
61   tail call void @free(i8* %0) #1
62   br label %end
63 rec:
64   tail call void @free_in_scc1(i8* %0)
65   br label %end
66 end:
67   ret void
71 ; TEST 4 (positive case)
72 ; Free doesn't occur.
73 ; void mutual_recursion1(){
74 ;    mutual_recursion2();
75 ; }
76 ; void mutual_recursion2(){
77 ;     mutual_recursion1();
78 ; }
81 ; FNATTR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
82 ; FNATTR-NEXT: define void @mutual_recursion1()
83 define void @mutual_recursion1() #0 {
84   call void @mutual_recursion2()
85   ret void
88 ; FNATTR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
89 ; FNATTR-NEXT: define void @mutual_recursion2()
90 define void @mutual_recursion2() #0 {
91   call void @mutual_recursion1()
92   ret void
96 ; TEST 5
97 ; C++ delete operation (negative case)
98 ; void delete_op (char p[]){
99 ;     delete [] p;
100 ; }
102 ; FNATTR: Function Attrs: noinline nounwind uwtable
103 ; FNATTR-NEXT: define void @_Z9delete_opPc(i8* %0) local_unnamed_addr
104 define void @_Z9delete_opPc(i8* %0) local_unnamed_addr #0 {
105   %2 = icmp eq i8* %0, null
106   br i1 %2, label %4, label %3
108 ; <label>:3:                                      ; preds = %1
109   tail call void @_ZdaPv(i8* nonnull %0) #2
110   br label %4
112 ; <label>:4:                                      ; preds = %3, %1
113   ret void
117 ; TEST 6 (negative case)
118 ; Call realloc
119 ; FNATTR: Function Attrs: noinline nounwind uwtable
120 ; FNATTR-NEXT: define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr
121 define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr #0 {
122     %ret = tail call i8* @realloc(i8* %0, i64 %1) #2
123     ret i8* %ret
127 ; TEST 7 (positive case)
128 ; Call function declaration with "nofree"
131 ; FNATTR: Function Attrs: nofree noinline nounwind readnone uwtable
132 ; FNATTR-NEXT: declare void @nofree_function()
133 declare void @nofree_function() nofree readnone #0
135 ; FNATTR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
136 ; FNATTR-NEXT: define void @call_nofree_function()
137 define void @call_nofree_function() #0 {
138     tail call void @nofree_function()
139     ret void
142 ; TEST 8 (negative case)
143 ; Call function declaration without "nofree"
146 declare void @maybe_free() #0
149 ; FNATTR: Function Attrs: noinline nounwind uwtable
150 ; FNATTR: define void @call_maybe_free()
151 define void @call_maybe_free() #0 {
152     tail call void @maybe_free()
153     ret void
157 ; TEST 9 (negative case)
158 ; Call both of above functions
160 ; FNATTR: Function Attrs: noinline nounwind uwtable
161 ; FNATTR-NEXT: define void @call_both()
162 define void @call_both() #0 {
163     tail call void @maybe_free()
164     tail call void @nofree_function()
165     ret void
169 ; TEST 10 (positive case)
170 ; Call intrinsic function
171 ; FNATTRS: Function Attrs: nofree noinline nosync readnone speculatable
172 ; FNATTRS-NEXT: declare float @llvm.floor.f32(float %0)
173 declare float @llvm.floor.f32(float)
175 ; FNATTRS: Function Attrs: noinline nounwind uwtable
176 ; FNATTRS-NEXT: define void @call_floor(float %a)
177 ; FIXME: missing nofree
179 define void @call_floor(float %a) #0 {
180     tail call float @llvm.floor.f32(float %a)
181     ret void
184 ; TEST 11 (positive case)
185 ; Check propagation.
187 ; FNATTRS: Function Attrs: noinline nounwind uwtable
188 ; FNATTRS-NEXT: define void @f1()
189 define void @f1() #0 {
190     tail call void @nofree_function()
191     ret void
194 ; FNATTRS: Function Attrs: noinline nounwind uwtable
195 ; FNATTRS-NEXT: define void @f2()
196 define void @f2() #0 {
197     tail call void @f1()
198     ret void
202 declare noalias i8* @malloc(i64)
204 attributes #0 = { nounwind uwtable noinline }
205 attributes #1 = { nounwind }
206 attributes #2 = { nobuiltin nounwind }