[llvm] r365924 - [Attributor] Deduce "nofree" function attribute
Hideto Ueno via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 12 10:38:51 PDT 2019
Author: uenoku
Date: Fri Jul 12 10:38:51 2019
New Revision: 365924
URL: http://llvm.org/viewvc/llvm-project?rev=365924&view=rev
Log:
[Attributor] Deduce "nofree" function attribute
Summary: Deduce "nofree" function attribute. A more concise description of "nofree" is on D49165.
Reviewers: jdoerfert
Reviewed By: jdoerfert
Subscribers: homerdin, hfinkel, lebedev.ri, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62687
Modified:
llvm/trunk/lib/Transforms/IPO/Attributor.cpp
llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll
llvm/trunk/test/Transforms/FunctionAttrs/fn_noreturn.ll
llvm/trunk/test/Transforms/FunctionAttrs/nofree-attributor.ll
llvm/trunk/test/Transforms/FunctionAttrs/nosync.ll
llvm/trunk/test/Transforms/FunctionAttrs/nounwind.ll
Modified: llvm/trunk/lib/Transforms/IPO/Attributor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Attributor.cpp?rev=365924&r1=365923&r2=365924&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Attributor.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Attributor.cpp Fri Jul 12 10:38:51 2019
@@ -50,6 +50,7 @@ STATISTIC(NumFnKnownReturns, "Number of
STATISTIC(NumFnArgumentReturned,
"Number of function arguments marked returned");
STATISTIC(NumFnNoSync, "Number of functions marked nosync");
+STATISTIC(NumFnNoFree, "Number of functions marked nofree");
// TODO: Determine a good default value.
//
@@ -104,6 +105,9 @@ static void bookkeeping(AbstractAttribut
case Attribute::NoSync:
NumFnNoSync++;
break;
+ case Attribute::NoFree:
+ NumFnNoFree++;
+ break;
default:
return;
}
@@ -909,6 +913,69 @@ ChangeStatus AANoSyncFunction::updateImp
return ChangeStatus::UNCHANGED;
}
+/// ------------------------ No-Free Attributes ----------------------------
+
+struct AANoFreeFunction : AbstractAttribute, BooleanState {
+
+ /// See AbstractAttribute::AbstractAttribute(...).
+ AANoFreeFunction(Function &F, InformationCache &InfoCache)
+ : AbstractAttribute(F, InfoCache) {}
+
+ /// See AbstractAttribute::getState()
+ ///{
+ AbstractState &getState() override { return *this; }
+ const AbstractState &getState() const override { return *this; }
+ ///}
+
+ /// See AbstractAttribute::getManifestPosition().
+ ManifestPosition getManifestPosition() const override { return MP_FUNCTION; }
+
+ /// See AbstractAttribute::getAsStr().
+ const std::string getAsStr() const override {
+ return getAssumed() ? "nofree" : "may-free";
+ }
+
+ /// See AbstractAttribute::updateImpl(...).
+ ChangeStatus updateImpl(Attributor &A) override;
+
+ /// See AbstractAttribute::getAttrKind().
+ Attribute::AttrKind getAttrKind() const override { return ID; }
+
+ /// Return true if "nofree" is assumed.
+ bool isAssumedNoFree() const { return getAssumed(); }
+
+ /// Return true if "nofree" is known.
+ bool isKnownNoFree() const { return getKnown(); }
+
+ /// The identifier used by the Attributor for this class of attributes.
+ static constexpr Attribute::AttrKind ID = Attribute::NoFree;
+};
+
+ChangeStatus AANoFreeFunction::updateImpl(Attributor &A) {
+ Function &F = getAnchorScope();
+
+ // The map from instruction opcodes to those instructions in the function.
+ auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
+
+ for (unsigned Opcode :
+ {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
+ (unsigned)Instruction::Call}) {
+ for (Instruction *I : OpcodeInstMap[Opcode]) {
+
+ auto ICS = ImmutableCallSite(I);
+ auto *NoFreeAA = A.getAAFor<AANoFreeFunction>(*this, *I);
+
+ if ((!NoFreeAA || !NoFreeAA->isValidState() ||
+ !NoFreeAA->isAssumedNoFree()) &&
+ !ICS.hasFnAttr(Attribute::NoFree)) {
+ indicatePessimisticFixpoint();
+ return ChangeStatus::CHANGED;
+ }
+ }
+ }
+ return ChangeStatus::UNCHANGED;
+}
+
/// ----------------------------------------------------------------------------
/// Attributor
/// ----------------------------------------------------------------------------
@@ -1057,6 +1124,9 @@ void Attributor::identifyDefaultAbstract
// Every function might be marked "nosync"
registerAA(*new AANoSyncFunction(F, InfoCache));
+ // Every function might be "no-free".
+ registerAA(*new AANoFreeFunction(F, InfoCache));
+
// Return attributes are only appropriate if the return type is non void.
Type *ReturnType = F.getReturnType();
if (!ReturnType->isVoidTy()) {
Modified: llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll?rev=365924&r1=365923&r2=365924&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll Fri Jul 12 10:38:51 2019
@@ -8,13 +8,13 @@
; TEST SCC test returning an integer value argument
;
-; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define i32 @sink_r0(i32 returned %r)
-; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define i32 @scc_r1(i32 %a, i32 returned %r, i32 %b)
-; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define i32 @scc_r2(i32 %a, i32 %b, i32 returned %r)
-; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define i32 @scc_rX(i32 %a, i32 %b, i32 %r)
;
; FNATTR: define i32 @sink_r0(i32 returned %r)
@@ -159,22 +159,22 @@ return:
; TEST SCC test returning a pointer value argument
;
-; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ptr_sink_r0(double* readnone returned %r)
-; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ptr_scc_r1(double* %a, double* readnone returned %r, double* nocapture readnone %b)
-; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ptr_scc_r2(double* readnone %a, double* readnone %b, double* readnone returned %r)
;
; FNATTR: define double* @ptr_sink_r0(double* readnone returned %r)
; FNATTR: define double* @ptr_scc_r1(double* %a, double* readnone %r, double* nocapture readnone %b)
; FNATTR: define double* @ptr_scc_r2(double* readnone %a, double* readnone %b, double* readnone %r)
;
-; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define double* @ptr_sink_r0(double* returned %r)
-; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define double* @ptr_scc_r1(double* %a, double* returned %r, double* %b)
-; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define double* @ptr_scc_r2(double* %a, double* %b, double* returned %r)
;
; double* ptr_scc_r1(double* a, double* b, double* r);
@@ -261,7 +261,7 @@ return:
;
; FIXME: no-return missing
; FNATTR: define i32* @rt0(i32* readonly %a)
-; BOTH: Function Attrs: noinline nosync nounwind readonly uwtable
+; BOTH: Function Attrs: nofree noinline nosync nounwind readonly uwtable
; BOTH-NEXT: define i32* @rt0(i32* readonly returned %a)
define i32* @rt0(i32* %a) #0 {
entry:
@@ -280,7 +280,7 @@ entry:
;
; FIXME: no-return missing
; FNATTR: define noalias i32* @rt1(i32* nocapture readonly %a)
-; BOTH: Function Attrs: noinline nosync nounwind readonly uwtable
+; BOTH: Function Attrs: nofree noinline nosync nounwind readonly uwtable
; BOTH-NEXT: define noalias i32* @rt1(i32* nocapture readonly %a)
define i32* @rt1(i32* %a) #0 {
entry:
@@ -441,11 +441,11 @@ entry:
; return b == 0? b : x;
; }
;
-; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double @select_and_phi(double returned %b)
;
; FNATTR: define double @select_and_phi(double %b)
-; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define double @select_and_phi(double returned %b)
define double @select_and_phi(double %b) #0 {
entry:
@@ -472,12 +472,12 @@ if.end:
; return b == 0? b : x;
; }
;
-; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define double @recursion_select_and_phi(i32 %a, double returned %b)
;
; FNATTR: define double @recursion_select_and_phi(i32 %a, double %b)
;
-; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define double @recursion_select_and_phi(i32 %a, double returned %b)
define double @recursion_select_and_phi(i32 %a, double %b) #0 {
entry:
@@ -503,12 +503,12 @@ if.end:
; return (double*)b;
; }
;
-; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @bitcast(i32* readnone returned %b)
;
; FNATTR: define double* @bitcast(i32* readnone %b)
;
-; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define double* @bitcast(i32* returned %b)
define double* @bitcast(i32* %b) #0 {
entry:
@@ -526,12 +526,12 @@ entry:
; return b != 0 ? b : x;
; }
;
-; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @bitcasts_select_and_phi(i32* readnone returned %b)
;
; FNATTR: define double* @bitcasts_select_and_phi(i32* readnone %b)
;
-; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define double* @bitcasts_select_and_phi(i32* returned %b)
define double* @bitcasts_select_and_phi(i32* %b) #0 {
entry:
@@ -564,12 +564,12 @@ if.end:
; /* return undef */
; }
;
-; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ret_arg_arg_undef(i32* readnone returned %b)
;
; FNATTR: define double* @ret_arg_arg_undef(i32* readnone %b)
;
-; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define double* @ret_arg_arg_undef(i32* returned %b)
define double* @ret_arg_arg_undef(i32* %b) #0 {
entry:
@@ -602,12 +602,12 @@ ret_undef:
; /* return undef */
; }
;
-; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ret_undef_arg_arg(i32* readnone returned %b)
;
; FNATTR: define double* @ret_undef_arg_arg(i32* readnone %b)
;
-; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define double* @ret_undef_arg_arg(i32* returned %b)
define double* @ret_undef_arg_arg(i32* %b) #0 {
entry:
@@ -640,7 +640,7 @@ ret_arg1:
; /* return undef */
; }
;
-; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ret_undef_arg_undef(i32* readnone returned %b)
;
; FNATTR: define double* @ret_undef_arg_undef(i32* readnone %b)
@@ -744,8 +744,8 @@ unreachableblock2:
attributes #0 = { noinline nounwind uwtable }
; BOTH-NOT: attributes #
-; BOTH-DAG: attributes #{{[0-9]*}} = { noinline norecurse nosync nounwind readnone uwtable }
-; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nosync nounwind readnone uwtable }
-; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nosync nounwind readonly uwtable }
+; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline norecurse nosync nounwind readnone uwtable }
+; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline nosync nounwind readnone uwtable }
+; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline nosync nounwind readonly uwtable }
; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nounwind uwtable }
; BOTH-NOT: attributes #
Modified: llvm/trunk/test/Transforms/FunctionAttrs/fn_noreturn.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/fn_noreturn.ll?rev=365924&r1=365923&r2=365924&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/fn_noreturn.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/fn_noreturn.ll Fri Jul 12 10:38:51 2019
@@ -20,7 +20,7 @@ target datalayout = "e-m:e-i64:64-f80:12
; }
;
; FIXME: no-return missing
-; CHECK: Function Attrs: noinline nosync nounwind readnone uwtable
+; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable
; CHECK: define void @srec0()
;
define void @srec0() #0 {
@@ -37,7 +37,7 @@ entry:
; }
;
; FIXME: no-return missing
-; CHECK: Function Attrs: noinline nosync nounwind readnone uwtable
+; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable
; CHECK: define i32 @srec16(i32 %a)
;
define i32 @srec16(i32 %a) #0 {
@@ -69,7 +69,7 @@ entry:
; }
;
; FIXME: no-return missing
-; CHECK: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
; CHECK: define i32 @endless_loop(i32 %a)
;
define i32 @endless_loop(i32 %a) #0 {
@@ -89,7 +89,7 @@ while.body:
; }
;
; FIXME: no-return missing
-; CHECK: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
; CHECK: define i32 @dead_return(i32 returned %a)
;
define i32 @dead_return(i32 %a) #0 {
@@ -111,7 +111,7 @@ return:
; }
;
; FIXME: no-return missing
-; CHECK: Function Attrs: noinline nosync nounwind readnone uwtable
+; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable
; CHECK: define i32 @multiple_noreturn_calls(i32 %a)
;
define i32 @multiple_noreturn_calls(i32 %a) #0 {
Modified: llvm/trunk/test/Transforms/FunctionAttrs/nofree-attributor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nofree-attributor.ll?rev=365924&r1=365923&r2=365924&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nofree-attributor.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nofree-attributor.ll Fri Jul 12 10:38:51 2019
@@ -1,4 +1,6 @@
-; RUN: opt -functionattrs --disable-nofree-inference=false -S < %s | FileCheck %s
+; RUN: opt -functionattrs --disable-nofree-inference=false -S < %s | FileCheck %s --check-prefix=FNATTR
+; RUN: opt -attributor --attributor-disable=false -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; Test cases specifically designed for the "nofree" function attribute.
@@ -11,29 +13,33 @@ declare void @_ZdaPv(i8*) local_unnamed_
; TEST 1 (positive case)
-; FIXME: missing "nofree"
-; CHECK: Function Attrs: noinline norecurse nounwind readnone uwtable
-; CHECK: define void @only_return()
+; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
+; FNATTR-NEXT: define void @only_return()
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @only_return()
define void @only_return() #0 {
ret void
}
-; TEST 2 (nagative case)
+; TEST 2 (negative 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
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR-NEXT: define void @only_free(i8* nocapture) local_unnamed_addr
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT: define void @only_free(i8* nocapture) local_unnamed_addr #1
define void @only_free(i8* nocapture) local_unnamed_addr #0 {
tail call void @free(i8* %0) #1
ret void
}
-; TEST 3 (nagative case)
+; TEST 3 (negative case)
; Free occurs in same scc.
; void free_in_scc1(char*p){
; free_in_scc2(p);
@@ -44,17 +50,23 @@ define void @only_free(i8* nocapture) lo
; }
-; CHECK: Function Attrs: noinline nounwind uwtable
-; CHECK: define void @free_in_scc1(i8* nocapture) local_unnamed_addr
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR-NEXT: define void @free_in_scc1(i8* nocapture) local_unnamed_addr
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT :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 {
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR-NEXT: define void @free_in_scc2(i8* nocapture) local_unnamed_addr
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR: define void @free_in_scc2(i8* nocapture) local_unnamed_addr
+define void @free_in_scc2(i8* nocapture) local_unnamed_addr #0 {
tail call void @free_in_scc1(i8* %0)
tail call void @free(i8* %0) #1
ret void
@@ -71,17 +83,19 @@ define void @free_in_scc2(i8*) local_unn
; }
-; FIXME: missing "nofree"
-; CHECK: Function Attrs: noinline nounwind readnone uwtable
-; CHECK: define void @mutual_recursion1()
+; FNATTR: Function Attrs: noinline nounwind readnone uwtable
+; FNATTR-NEXT: define void @mutual_recursion1()
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: 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()
+; FNATTR: Function Attrs: noinline nounwind readnone uwtable
+; FNATTR-NEXT: define void @mutual_recursion2()
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @mutual_recursion2()
define void @mutual_recursion2() #0 {
call void @mutual_recursion1()
ret void
@@ -89,13 +103,16 @@ define void @mutual_recursion2() #0 {
; TEST 5
-; C++ delete operation (nagative case)
+; C++ delete operation (negative case)
; void delete_op (char p[]){
; delete [] p;
; }
-; CHECK: Function Attrs: noinline nounwind uwtable
-; CHECK: define void @_Z9delete_opPc(i8*) local_unnamed_addr
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR-NEXT: define void @_Z9delete_opPc(i8*) local_unnamed_addr
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT: define void @_Z9delete_opPc(i8*) local_unnamed_addr #1
define void @_Z9delete_opPc(i8*) local_unnamed_addr #0 {
%2 = icmp eq i8* %0, null
br i1 %2, label %4, label %3
@@ -111,9 +128,12 @@ define void @_Z9delete_opPc(i8*) local_u
; TEST 6 (negative case)
; Call realloc
-; CHECK: Function Attrs: noinline nounwind uwtable
-; CHECK: define noalias i8* @call_realloc(i8* nocapture, i64) local_unnamed_addr
-define noalias i8* @call_realloc(i8*nocapture, i64) local_unnamed_addr #0 {
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR-NEXT: define noalias i8* @call_realloc(i8* nocapture, i64) local_unnamed_addr
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT: define noalias i8* @call_realloc(i8* nocapture, i64) local_unnamed_addr
+define noalias i8* @call_realloc(i8* nocapture, i64) local_unnamed_addr #0 {
%ret = tail call i8* @realloc(i8* %0, i64 %1) #2
ret i8* %ret
}
@@ -122,41 +142,97 @@ define noalias i8* @call_realloc(i8*noca
; TEST 7 (positive case)
; Call function declaration with "nofree"
+
+; FNATTR: Function Attrs: nofree noinline nounwind readnone uwtable
+; FNATTR-NEXT: declare void @nofree_function()
+; ATTRIBUTOR: Function Attrs: nofree noinline nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: declare void @nofree_function()
declare void @nofree_function() nofree readnone #0
-; FIXME: missing "nofree"
-; Function Attrs: noinline nounwind readnone uwtable
-; CHECK: define void @call_nofree_function()
+; FNATTR: Function Attrs: noinline nounwind readnone uwtable
+; FNATTR-NEXT: define void @call_nofree_function()
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @call_nofree_function()
define void @call_nofree_function() #0 {
tail call void @nofree_function()
ret void
}
-; TEST 8 (nagative case)
+; TEST 8 (negative case)
; Call function declaration without "nofree"
+
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NEXT: declare void @maybe_free()
declare void @maybe_free() #0
-; CHECK: Function Attrs: noinline nounwind uwtable
-; CHECK: define void @call_maybe_free()
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR: define void @call_maybe_free()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT: define void @call_maybe_free()
define void @call_maybe_free() #0 {
tail call void @maybe_free()
ret void
}
-; TEST 9 (nagative case)
+; TEST 9 (negative case)
; Call both of above functions
-; CHECK: Function Attrs: noinline nounwind uwtable
-; CHECK: define void @call_both()
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR-NEXT: define void @call_both()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT: define void @call_both()
define void @call_both() #0 {
tail call void @maybe_free()
tail call void @nofree_function()
ret void
}
+
+; TEST 10 (positive case)
+; Call intrinsic function
+; FNATTRS: Function Attrs: noinline readnone speculatable
+; FNATTRS-NEXT: declare float @llvm.floor.f32(float)
+; ATTRIBUTOR: Function Attrs: nounwind readnone speculatable
+; ATTRIBUTOR-NEXT: declare float @llvm.floor.f32(float)
+declare float @llvm.floor.f32(float)
+
+; FNATTRS: Function Attrs: noinline nounwind uwtable
+; FNATTRS-NEXT: define void @call_floor(float %a)
+; FIXME: missing nofree
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @call_floor(float %a)
+
+define void @call_floor(float %a) #0 {
+ tail call float @llvm.floor.f32(float %a)
+ ret void
+}
+
+; TEST 11 (positive case)
+; Check propagation.
+
+; FNATTRS: Function Attrs: noinline nounwind uwtable
+; FNATTRS-NEXT: define void @f1()
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @f1()
+define void @f1() #0 {
+ tail call void @nofree_function()
+ ret void
+}
+
+; FNATTRS: Function Attrs: noinline nounwind uwtable
+; FNATTRS-NEXT: define void @f2()
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @f2()
+define void @f2() #0 {
+ tail call void @f1()
+ ret void
+}
+
attributes #0 = { nounwind uwtable noinline }
attributes #1 = { nounwind }
Modified: llvm/trunk/test/Transforms/FunctionAttrs/nosync.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nosync.ll?rev=365924&r1=365923&r2=365924&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nosync.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nosync.ll Fri Jul 12 10:38:51 2019
@@ -27,7 +27,7 @@ target datalayout = "e-m:e-i64:64-f80:12
; FNATTR: Function Attrs: norecurse nounwind optsize readnone ssp uwtable
; FNATTR-NEXT: define nonnull i32* @foo(%struct.ST* readnone %s)
-; ATTRIBUTOR: Function Attrs: nosync nounwind optsize readnone ssp uwtable
+; ATTRIBUTOR: Function Attrs: nofree nosync nounwind optsize readnone ssp uwtable
; ATTRIBUTOR-NEXT: define i32* @foo(%struct.ST* %s)
define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {
entry:
@@ -44,7 +44,7 @@ entry:
; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
; FNATTR-NEXT: define i32 @load_monotonic(i32* nocapture readonly)
-; ATTRIBUTOR: Function Attrs: norecurse nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define i32 @load_monotonic(i32* nocapture readonly)
define i32 @load_monotonic(i32* nocapture readonly) norecurse nounwind uwtable {
%2 = load atomic i32, i32* %0 monotonic, align 4
@@ -60,7 +60,7 @@ define i32 @load_monotonic(i32* nocaptur
; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
; FNATTR-NEXT: define void @store_monotonic(i32* nocapture)
-; ATTRIBUTOR: Function Attrs: norecurse nosync nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define void @store_monotonic(i32* nocapture)
define void @store_monotonic(i32* nocapture) norecurse nounwind uwtable {
store atomic i32 10, i32* %0 monotonic, align 4
@@ -76,7 +76,7 @@ define void @store_monotonic(i32* nocapt
; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
; FNATTR-NEXT: define i32 @load_acquire(i32* nocapture readonly)
-; ATTRIBUTOR: Function Attrs: norecurse nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
; ATTRIBUTOR-NOT: nosync
; ATTRIBUTOR-NEXT: define i32 @load_acquire(i32* nocapture readonly)
define i32 @load_acquire(i32* nocapture readonly) norecurse nounwind uwtable {
@@ -92,7 +92,7 @@ define i32 @load_acquire(i32* nocapture
; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
; FNATTR-NEXT: define void @load_release(i32* nocapture)
-; ATTRIBUTOR: Function Attrs: norecurse nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
; ATTRIBUTOR-NOT: nosync
; ATTRIBUTOR-NEXT: define void @load_release(i32* nocapture)
define void @load_release(i32* nocapture) norecurse nounwind uwtable {
@@ -104,7 +104,7 @@ define void @load_release(i32* nocapture
; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
; FNATTR-NEXT: define void @load_volatile_release(i32* nocapture)
-; ATTRIBUTOR: Function Attrs: norecurse nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
; ATTRIBUTOR-NOT: nosync
; ATTRIBUTOR-NEXT: define void @load_volatile_release(i32* nocapture)
define void @load_volatile_release(i32* nocapture) norecurse nounwind uwtable {
@@ -120,7 +120,7 @@ define void @load_volatile_release(i32*
; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
; FNATTR-NEXT: define void @volatile_store(i32*)
-; ATTRIBUTOR: Function Attrs: norecurse nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
; ATTRIBUTOR-NOT: nosync
; ATTRIBUTOR-NEXT: define void @volatile_store(i32*)
define void @volatile_store(i32*) norecurse nounwind uwtable {
@@ -137,7 +137,7 @@ define void @volatile_store(i32*) norecu
; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
; FNATTR-NEXT: define i32 @volatile_load(i32*)
-; ATTRIBUTOR: Function Attrs: norecurse nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
; ATTRIBUTOR-NOT: nosync
; ATTRIBUTOR-NEXT: define i32 @volatile_load(i32*)
define i32 @volatile_load(i32*) norecurse nounwind uwtable {
@@ -185,7 +185,7 @@ define void @call_might_sync() nounwind
; FNATTR: Function Attrs: nofree noinline nounwind uwtable
; FNATTR-NEXT: define i32 @scc1(i32*)
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nounwind uwtable
; ATTRIBUTOR-NOT: nosync
; ATTRIBUTOR-NEXT: define i32 @scc1(i32*)
define i32 @scc1(i32*) noinline nounwind uwtable {
@@ -196,7 +196,7 @@ define i32 @scc1(i32*) noinline nounwind
; FNATTR: Function Attrs: nofree noinline nounwind uwtable
; FNATTR-NEXT: define void @scc2(i32*)
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR: Function Attrs: nofree noinline nounwind uwtable
; ATTRIBUTOR-NOT: nosync
; ATTRIBUTOR-NEXT: define void @scc2(i32*)
define void @scc2(i32*) noinline nounwind uwtable {
@@ -257,7 +257,7 @@ define void @bar(i32 *, %"struct.std::at
; TEST 13 - Fence syncscope("singlethread") seq_cst
; FNATTR: Function Attrs: nofree norecurse nounwind
; FNATTR-NEXT: define void @foo1_singlethread(i32* nocapture, %"struct.std::atomic"* nocapture)
-; ATTRIBUTOR: Function Attrs: nosync
+; ATTRIBUTOR: Function Attrs: nofree nosync
; ATTRIBUTOR: define void @foo1_singlethread(i32*, %"struct.std::atomic"*)
define void @foo1_singlethread(i32*, %"struct.std::atomic"*) {
store i32 100, i32* %0, align 4
@@ -269,7 +269,7 @@ define void @foo1_singlethread(i32*, %"s
; FNATTR: Function Attrs: nofree norecurse nounwind
; FNATTR-NEXT: define void @bar_singlethread(i32* nocapture readnone, %"struct.std::atomic"* nocapture readonly)
-; ATTRIBUTOR: Function Attrs: nosync
+; ATTRIBUTOR: Function Attrs: nofree nosync
; ATTRIBUTOR: define void @bar_singlethread(i32*, %"struct.std::atomic"*)
define void @bar_singlethread(i32 *, %"struct.std::atomic"*) {
%3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
Modified: llvm/trunk/test/Transforms/FunctionAttrs/nounwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nounwind.ll?rev=365924&r1=365923&r2=365924&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nounwind.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nounwind.ll Fri Jul 12 10:38:51 2019
@@ -4,7 +4,7 @@
; TEST 1
; CHECK: Function Attrs: norecurse nounwind readnone
; CHECK-NEXT: define i32 @foo1()
-; ATTRIBUTOR: Function Attrs: nosync nounwind
+; ATTRIBUTOR: Function Attrs: nofree nosync nounwind
; ATTRIBUTOR-NEXT: define i32 @foo1()
define i32 @foo1() {
ret i32 1
@@ -13,7 +13,7 @@ define i32 @foo1() {
; TEST 2
; CHECK: Function Attrs: nounwind readnone
; CHECK-NEXT: define i32 @scc1_foo()
-; ATTRIBUTOR: Function Attrs: nosync nounwind
+; ATTRIBUTOR: Function Attrs: nofree nosync nounwind
; ATTRIBUTOR-NEXT: define i32 @scc1_foo()
define i32 @scc1_foo() {
%1 = call i32 @scc1_bar()
@@ -24,7 +24,7 @@ define i32 @scc1_foo() {
; TEST 3
; CHECK: Function Attrs: nounwind readnone
; CHECK-NEXT: define i32 @scc1_bar()
-; ATTRIBUTOR: Function Attrs: nosync nounwind
+; ATTRIBUTOR: Function Attrs: nofree nosync nounwind
; ATTRIBUTOR-NEXT: define i32 @scc1_bar()
define i32 @scc1_bar() {
%1 = call i32 @scc1_foo()
More information about the llvm-commits
mailing list