Index: llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll @@ -0,0 +1,163 @@ +; RUN: opt -functionattrs --disable-nofree-inference=false -S < %s | FileCheck %s +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(i8* nocapture) local_unnamed_addr #1 +declare noalias i8* @realloc(i8* nocapture, i64) local_unnamed_addr #0 +declare void @_ZdaPv(i8*) local_unnamed_addr #2 + + +; TEST 1 (positive case) +; FIXME: missing "nofree" +; CHECK: Function Attrs: noinline norecurse nounwind readnone uwtable +; CHECK: define void @only_return() +define void @only_return() #0 { + ret void +} + + +; TEST 2 (nagative case) +; Only free +; void only_free(char* p) { +; free(p); +; } + +; CHECK: Function Attrs: noinline nounwind uwtable +; CHECK: define void @only_free(i8* nocapture) local_unnamed_addr +define void @only_free(i8* nocapture) local_unnamed_addr #0 { + tail call void @free(i8* %0) #1 + ret void +} + + +; TEST 3 (nagative 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); +; } + + +; CHECK: Function Attrs: noinline nounwind uwtable +; CHECK: define void @free_in_scc1(i8* nocapture) local_unnamed_addr +define void @free_in_scc1(i8* nocapture) local_unnamed_addr #0 { + tail call void @free_in_scc2(i8* %0) #1 + ret void +} + + +; CHECK: Function Attrs: noinline nounwind uwtable +; CHECK: define void @free_in_scc2(i8* nocapture) local_unnamed_addr +define void @free_in_scc2(i8*) local_unnamed_addr #0 { + tail call void @free_in_scc1(i8* %0) + tail call void @free(i8* %0) #1 + ret void +} + + +; TEST 4 (positive case) +; Free doesn't occur. +; void mutual_recursion1(){ +; mutual_recursion2(); +; } +; void mutual_recursion2(){ +; mutual_recursion1(); +; } + + +; FIXME: missing "nofree" +; CHECK: Function Attrs: noinline nounwind readnone uwtable +; CHECK: define void @mutual_recursion1() +define void @mutual_recursion1() #0 { + call void @mutual_recursion2() + ret void +} + +; FIXME: missing "nofree" +; CHECK: Function Attrs: noinline nounwind readnone uwtable +; CHECK: define void @mutual_recursion2() +define void @mutual_recursion2() #0 { + call void @mutual_recursion1() + ret void +} + + +; TEST 5 +; C++ delete operation (nagative case) +; void delete_op (char p[]){ +; delete [] p; +; } + +; CHECK: Function Attrs: noinline nounwind uwtable +; CHECK: define void @_Z9delete_opPc(i8*) local_unnamed_addr +define void @_Z9delete_opPc(i8*) local_unnamed_addr #0 { + %2 = icmp eq i8* %0, null + br i1 %2, label %4, label %3 + +;