Mercurial > hg > CbC > CbC_llvm
view llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll @ 266:00f31e85ec16 default tip
Added tag current for changeset 31d058e83c98
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 14 Oct 2023 10:13:55 +0900 |
parents | 1f2b6ac9f198 |
children |
line wrap: on
line source
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes ; RUN: opt -passes=function-attrs --aa-pipeline=basic-aa --disable-nofree-inference=false -S < %s | FileCheck %s --check-prefix=FNATTR target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; Test cases specifically designed for the "nofree" function attribute. ; We use FIXME's to indicate problems and missing attributes. ; Free functions declare void @free(ptr nocapture) local_unnamed_addr #1 declare noalias ptr @realloc(ptr nocapture, i64) local_unnamed_addr #0 declare void @_ZdaPv(ptr) local_unnamed_addr #2 ; TEST 1 (positive case) define void @only_return() #0 { ; FNATTR: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@only_return ; FNATTR-SAME: () #[[ATTR3:[0-9]+]] { ; FNATTR-NEXT: ret void ; ret void } ; TEST 2 (negative case) ; Only free ; void only_free(char* p) { ; free(p); ; } define void @only_free(ptr nocapture %0) local_unnamed_addr #0 { ; FNATTR: Function Attrs: noinline nounwind uwtable ; FNATTR-LABEL: define {{[^@]+}}@only_free ; FNATTR-SAME: (ptr nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { ; FNATTR-NEXT: tail call void @free(ptr [[TMP0]]) #[[ATTR0:[0-9]+]] ; FNATTR-NEXT: ret void ; tail call void @free(ptr %0) #1 ret void } ; TEST 3 (negative case) ; Free occurs in same scc. ; void free_in_scc1(char*p){ ; free_in_scc2(p); ; } ; void free_in_scc2(char*p){ ; free_in_scc1(p); ; free(p); ; } define void @free_in_scc1(ptr nocapture %0) local_unnamed_addr #0 { ; FNATTR: Function Attrs: noinline nounwind uwtable ; FNATTR-LABEL: define {{[^@]+}}@free_in_scc1 ; FNATTR-SAME: (ptr nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; FNATTR-NEXT: tail call void @free_in_scc2(ptr [[TMP0]]) #[[ATTR0]] ; FNATTR-NEXT: ret void ; tail call void @free_in_scc2(ptr %0) #1 ret void } define void @free_in_scc2(ptr nocapture %0) local_unnamed_addr #0 { ; FNATTR: Function Attrs: noinline nounwind uwtable ; FNATTR-LABEL: define {{[^@]+}}@free_in_scc2 ; FNATTR-SAME: (ptr nocapture [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; FNATTR-NEXT: [[CMP:%.*]] = icmp eq ptr [[TMP0]], null ; FNATTR-NEXT: br i1 [[CMP]], label [[REC:%.*]], label [[CALL:%.*]] ; FNATTR: call: ; FNATTR-NEXT: tail call void @free(ptr [[TMP0]]) #[[ATTR0]] ; FNATTR-NEXT: br label [[END:%.*]] ; FNATTR: rec: ; FNATTR-NEXT: tail call void @free_in_scc1(ptr [[TMP0]]) ; FNATTR-NEXT: br label [[END]] ; FNATTR: end: ; FNATTR-NEXT: ret void ; %cmp = icmp eq ptr %0, null br i1 %cmp, label %rec, label %call call: tail call void @free(ptr %0) #1 br label %end rec: tail call void @free_in_scc1(ptr %0) br label %end end: ret void } ; TEST 4 (positive case) ; Free doesn't occur. ; void mutual_recursion1(){ ; mutual_recursion2(); ; } ; void mutual_recursion2(){ ; mutual_recursion1(); ; } define void @mutual_recursion1() #0 { ; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@mutual_recursion1 ; FNATTR-SAME: () #[[ATTR4:[0-9]+]] { ; FNATTR-NEXT: call void @mutual_recursion2() ; FNATTR-NEXT: ret void ; call void @mutual_recursion2() ret void } define void @mutual_recursion2() #0 { ; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@mutual_recursion2 ; FNATTR-SAME: () #[[ATTR4]] { ; FNATTR-NEXT: call void @mutual_recursion1() ; FNATTR-NEXT: ret void ; call void @mutual_recursion1() ret void } ; TEST 5 ; C++ delete operation (negative case) ; void delete_op (char p[]){ ; delete [] p; ; } define void @_Z9delete_opPc(ptr %0) local_unnamed_addr #0 { ; FNATTR: Function Attrs: noinline nounwind uwtable ; FNATTR-LABEL: define {{[^@]+}}@_Z9delete_opPc ; FNATTR-SAME: (ptr [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; FNATTR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null ; FNATTR-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]] ; FNATTR: 3: ; FNATTR-NEXT: tail call void @_ZdaPv(ptr nonnull [[TMP0]]) #[[ATTR2:[0-9]+]] ; FNATTR-NEXT: br label [[TMP4]] ; FNATTR: 4: ; FNATTR-NEXT: ret void ; %2 = icmp eq ptr %0, null br i1 %2, label %4, label %3 ; <label>:3: ; preds = %1 tail call void @_ZdaPv(ptr nonnull %0) #2 br label %4 ; <label>:4: ; preds = %3, %1 ret void } ; TEST 6 (negative case) ; Call realloc define noalias ptr @call_realloc(ptr nocapture %0, i64 %1) local_unnamed_addr #0 { ; FNATTR: Function Attrs: noinline nounwind uwtable ; FNATTR-LABEL: define {{[^@]+}}@call_realloc ; FNATTR-SAME: (ptr nocapture [[TMP0:%.*]], i64 [[TMP1:%.*]]) local_unnamed_addr #[[ATTR1]] { ; FNATTR-NEXT: [[RET:%.*]] = tail call ptr @realloc(ptr [[TMP0]], i64 [[TMP1]]) #[[ATTR2]] ; FNATTR-NEXT: ret ptr [[RET]] ; %ret = tail call ptr @realloc(ptr %0, i64 %1) #2 ret ptr %ret } ; TEST 7 (positive case) ; Call function declaration with "nofree" declare void @nofree_function() nofree readnone #0 define void @call_nofree_function() #0 { ; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@call_nofree_function ; FNATTR-SAME: () #[[ATTR4]] { ; FNATTR-NEXT: tail call void @nofree_function() ; FNATTR-NEXT: ret void ; tail call void @nofree_function() ret void } ; TEST 8 (negative case) ; Call function declaration without "nofree" declare void @maybe_free() #0 define void @call_maybe_free() #0 { ; FNATTR: Function Attrs: noinline nounwind uwtable ; FNATTR-LABEL: define {{[^@]+}}@call_maybe_free ; FNATTR-SAME: () #[[ATTR1]] { ; FNATTR-NEXT: tail call void @maybe_free() ; FNATTR-NEXT: ret void ; tail call void @maybe_free() ret void } ; TEST 9 (negative case) ; Call both of above functions define void @call_both() #0 { ; FNATTR: Function Attrs: noinline nounwind uwtable ; FNATTR-LABEL: define {{[^@]+}}@call_both ; FNATTR-SAME: () #[[ATTR1]] { ; FNATTR-NEXT: tail call void @maybe_free() ; FNATTR-NEXT: tail call void @nofree_function() ; FNATTR-NEXT: ret void ; tail call void @maybe_free() tail call void @nofree_function() ret void } ; TEST 10 (positive case) ; Call intrinsic function declare float @llvm.floor.f32(float) define void @call_floor(float %a) #0 { ; FNATTR: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@call_floor ; FNATTR-SAME: (float [[A:%.*]]) #[[ATTR7:[0-9]+]] { ; FNATTR-NEXT: [[TMP1:%.*]] = tail call float @llvm.floor.f32(float [[A]]) ; FNATTR-NEXT: ret void ; tail call float @llvm.floor.f32(float %a) ret void } ; TEST 11 (positive case) ; Check propagation. define void @f1() #0 { ; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@f1 ; FNATTR-SAME: () #[[ATTR4]] { ; FNATTR-NEXT: tail call void @nofree_function() ; FNATTR-NEXT: ret void ; tail call void @nofree_function() ret void } define void @f2() #0 { ; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@f2 ; FNATTR-SAME: () #[[ATTR4]] { ; FNATTR-NEXT: tail call void @f1() ; FNATTR-NEXT: ret void ; tail call void @f1() ret void } declare noalias ptr @malloc(i64) attributes #0 = { nounwind uwtable noinline } attributes #1 = { nounwind } attributes #2 = { nobuiltin nounwind }