diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -68,7 +68,6 @@ STATISTIC(NumReadOnly, "Number of functions marked readonly"); STATISTIC(NumWriteOnly, "Number of functions marked writeonly"); STATISTIC(NumNoCapture, "Number of arguments marked nocapture"); -STATISTIC(NumReturned, "Number of arguments marked returned"); STATISTIC(NumReadNoneArg, "Number of arguments marked readnone"); STATISTIC(NumReadOnlyArg, "Number of arguments marked readonly"); STATISTIC(NumNoAlias, "Number of function returns marked noalias"); @@ -562,56 +561,6 @@ return IsRead ? Attribute::ReadOnly : Attribute::ReadNone; } -/// Deduce returned attributes for the SCC. -static bool addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes) { - bool Changed = false; - - // Check each function in turn, determining if an argument is always returned. - for (Function *F : SCCNodes) { - // We can infer and propagate function attributes only when we know that the - // definition we'll get at link time is *exactly* the definition we see now. - // For more details, see GlobalValue::mayBeDerefined. - if (!F->hasExactDefinition()) - continue; - - if (F->getReturnType()->isVoidTy()) - continue; - - // There is nothing to do if an argument is already marked as 'returned'. - if (llvm::any_of(F->args(), - [](const Argument &Arg) { return Arg.hasReturnedAttr(); })) - continue; - - auto FindRetArg = [&]() -> Value * { - Value *RetArg = nullptr; - for (BasicBlock &BB : *F) - if (auto *Ret = dyn_cast(BB.getTerminator())) { - // Note that stripPointerCasts should look through functions with - // returned arguments. - Value *RetVal = Ret->getReturnValue()->stripPointerCasts(); - if (!isa(RetVal) || RetVal->getType() != F->getReturnType()) - return nullptr; - - if (!RetArg) - RetArg = RetVal; - else if (RetArg != RetVal) - return nullptr; - } - - return RetArg; - }; - - if (Value *RetArg = FindRetArg()) { - auto *A = cast(RetArg); - A->addAttr(Attribute::Returned); - ++NumReturned; - Changed = true; - } - } - - return Changed; -} - /// If a callsite has arguments that are also arguments to the parent function, /// try to propagate attributes from the callsite's arguments to the parent's /// arguments. This may be important because inlining can cause information loss @@ -1330,7 +1279,6 @@ if (SCCNodes.empty()) return Changed; - Changed |= addArgumentReturnedAttrs(SCCNodes); Changed |= addReadAttrs(SCCNodes, AARGetter); Changed |= addArgumentAttrs(SCCNodes); diff --git a/llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll b/llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll --- a/llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll +++ b/llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -functionattrs -S | FileCheck %s -; RUN: opt < %s -passes=function-attrs -S | FileCheck %s +; RUN: opt < %s -attributor -functionattrs -S | FileCheck %s +; RUN: opt < %s -passes='attributor,cgscc(function-attrs)' -S | FileCheck %s ; CHECK: define i32* @a(i32** nocapture readonly %p) define i32* @a(i32** %p) { diff --git a/llvm/test/Transforms/FunctionAttrs/arg_returned.ll b/llvm/test/Transforms/FunctionAttrs/arg_returned.ll --- a/llvm/test/Transforms/FunctionAttrs/arg_returned.ll +++ b/llvm/test/Transforms/FunctionAttrs/arg_returned.ll @@ -29,7 +29,7 @@ ; BOTH: define dso_local i32 @scc_r2(i32 %a, i32 %b, i32 returned %r) [[NoInlineNoUnwindReadnoneUwtable]] ; BOTH: define dso_local i32 @scc_rX(i32 %a, i32 %b, i32 %r) [[NoInlineNoUnwindReadnoneUwtable]] ; -; FNATTR: define dso_local i32 @sink_r0(i32 returned %r) [[NoInlineNoRecurseNoUnwindReadnoneUwtable:#[0-9]]] +; FNATTR: define dso_local i32 @sink_r0(i32 %r) [[NoInlineNoRecurseNoUnwindReadnoneUwtable:#[0-9]]] ; FNATTR: define dso_local i32 @scc_r1(i32 %a, i32 %r, i32 %b) [[NoInlineNoUnwindReadnoneUwtable:#[0-9]]] ; FNATTR: define dso_local i32 @scc_r2(i32 %a, i32 %b, i32 %r) [[NoInlineNoUnwindReadnoneUwtable]] ; FNATTR: define dso_local i32 @scc_rX(i32 %a, i32 %b, i32 %r) [[NoInlineNoUnwindReadnoneUwtable]] @@ -176,7 +176,7 @@ ; BOTH: define dso_local double* @ptr_scc_r1(double* %a, double* readnone returned %r, double* nocapture readnone %b) [[NoInlineNoUnwindReadnoneUwtable]] ; BOTH: define dso_local double* @ptr_scc_r2(double* readnone %a, double* readnone %b, double* readnone returned %r) [[NoInlineNoUnwindReadnoneUwtable]] ; -; FNATTR: define dso_local double* @ptr_sink_r0(double* readnone returned %r) [[NoInlineNoRecurseNoUnwindReadnoneUwtable]] +; FNATTR: define dso_local double* @ptr_sink_r0(double* readnone %r) [[NoInlineNoRecurseNoUnwindReadnoneUwtable]] ; FNATTR: define dso_local double* @ptr_scc_r1(double* %a, double* readnone %r, double* nocapture readnone %b) [[NoInlineNoUnwindReadnoneUwtable]] ; FNATTR: define dso_local double* @ptr_scc_r2(double* readnone %a, double* readnone %b, double* readnone %r) [[NoInlineNoUnwindReadnoneUwtable]] ; @@ -308,7 +308,7 @@ ; BOTH: declare void @unknown_fn(i32* (i32*)*) [[NoInlineNoUnwindUwtable:#[0-9]*]] ; ; BOTH: define dso_local i32* @calls_unknown_fn(i32* readnone returned %r) [[NoInlineNoUnwindUwtable]] -; FNATTR: define dso_local i32* @calls_unknown_fn(i32* readnone returned %r) [[NoInlineNoUnwindUwtable:#[0-9]*]] +; FNATTR: define dso_local i32* @calls_unknown_fn(i32* readnone %r) [[NoInlineNoUnwindUwtable:#[0-9]*]] ; ATTRIBUTOR: define dso_local i32* @calls_unknown_fn(i32* returned %r) [[NoInlineNoUnwindUwtable:#[0-9]*]] ; declare void @unknown_fn(i32* (i32*)*) #0 @@ -335,7 +335,7 @@ ; FIXME: We should not derive norecurse for potentially redefined functions! ; define linkonce_odr i32* @maybe_redefined_fn(i32* %r) [[NoInlineNoUnwindUwtable]] ; -; FNATTR: define dso_local i32* @calls_maybe_redefined_fn(i32* returned %r) [[NoInlineNoRecurseNoUnwindUwtable:#[0-9]*]] +; FNATTR: define dso_local i32* @calls_maybe_redefined_fn(i32* %r) [[NoInlineNoRecurseNoUnwindUwtable:#[0-9]*]] ; ATTRIBUTOR: define dso_local i32* @calls_maybe_redefined_fn(i32* returned %r) [[NoInlineNoUnwindUwtable]] ; FIXME: We should not derive norecurse for potentially redefined functions! ; define dso_local i32* @calls_maybe_redefined_fn(i32* returned %r) [[NoInlineNoUnwindUwtable]] diff --git a/llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll b/llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll --- a/llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll +++ b/llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll @@ -1,5 +1,5 @@ -; RUN: opt -S -o - -functionattrs %s | FileCheck %s -; RUN: opt -S -o - -passes=function-attrs %s | FileCheck %s +; RUN: opt < %s -attributor -functionattrs -S | FileCheck %s +; RUN: opt < %s -passes='attributor,cgscc(function-attrs)' -S | FileCheck %s ; Verify we remove argmemonly/inaccessiblememonly/inaccessiblemem_or_argmemonly ; function attributes when we derive readnone. diff --git a/llvm/test/Transforms/FunctionAttrs/nocapture.ll b/llvm/test/Transforms/FunctionAttrs/nocapture.ll --- a/llvm/test/Transforms/FunctionAttrs/nocapture.ll +++ b/llvm/test/Transforms/FunctionAttrs/nocapture.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -functionattrs -S | FileCheck %s -; RUN: opt < %s -passes=function-attrs -S | FileCheck %s +; RUN: opt < %s -attributor -functionattrs -S | FileCheck %s +; RUN: opt < %s -passes='attributor,cgscc(function-attrs)' -S | FileCheck %s @g = global i32* null ; [#uses=1] diff --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll --- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll +++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -functionattrs -S | FileCheck %s -; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs)' -S | FileCheck %s +; RUN: opt < %s -attributor -functionattrs -S | FileCheck %s +; RUN: opt < %s -aa-pipeline=basic-aa -passes='attributor,cgscc(function-attrs)' -S | FileCheck %s @x = global i32 0 declare void @test1_1(i8* %x1_1, i8* readonly %y1_1, ...)