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 @@ -209,7 +209,7 @@ ReadsMemory |= I->mayReadFromMemory(); } - if (WritesMemory) { + if (WritesMemory) { if (!ReadsMemory) return MAK_WriteOnly; else @@ -1241,35 +1241,6 @@ return true; } -static bool addNoRecurseAttrs(const SCCNodeSet &SCCNodes) { - // Try and identify functions that do not recurse. - - // If the SCC contains multiple nodes we know for sure there is recursion. - if (SCCNodes.size() != 1) - return false; - - Function *F = *SCCNodes.begin(); - if (!F || F->isDeclaration() || F->doesNotRecurse()) - return false; - - // If all of the calls in F are identifiable and are to norecurse functions, F - // is norecurse. This check also detects self-recursion as F is not currently - // marked norecurse, so any called from F to F will not be marked norecurse. - for (auto &BB : *F) - for (auto &I : BB.instructionsWithoutDebug()) - if (auto CS = CallSite(&I)) { - Function *Callee = CS.getCalledFunction(); - if (!Callee || Callee == F || !Callee->doesNotRecurse()) - // Function calls a potentially recursive function. - return false; - } - - // Every call was to a non-recursive function other than this function, and - // we have no indirect recursion as the SCC size is one. This function cannot - // recurse. - return setDoesNotRecurse(*F); -} - template static bool deriveAttrsInPostOrder(SCCNodeSet &SCCNodes, AARGetterT &&AARGetter, bool HasUnknownCall) { @@ -1288,7 +1259,6 @@ Changed |= addNoAliasAttrs(SCCNodes); Changed |= addNonNullAttrs(SCCNodes); Changed |= inferAttrsFromFunctionBodies(SCCNodes); - Changed |= addNoRecurseAttrs(SCCNodes); } return Changed; diff --git a/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll b/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll --- a/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll +++ b/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -tbaa -basicaa -functionattrs -S | FileCheck %s +; RUN: opt < %s -tbaa -basicaa -attributor -functionattrs -S | FileCheck %s ; FunctionAttrs should make use of TBAA. @@ -43,13 +43,13 @@ ; This is unusual, since the function is memcpy, but as above, this ; isn't necessarily invalid. -; CHECK: define void @test2_yes(i8* nocapture %p, i8* nocapture %q, i64 %n) #4 { +; CHECK: define void @test2_yes(i8* nocapture %p, i8* nocapture %q, i64 %n) #0 { define void @test2_yes(i8* %p, i8* %q, i64 %n) nounwind { call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 %n, i1 false), !tbaa !1 ret void } -; CHECK: define void @test2_no(i8* nocapture %p, i8* nocapture readonly %q, i64 %n) #3 { +; CHECK: define void @test2_no(i8* nocapture %p, i8* nocapture readonly %q, i64 %n) #4 { define void @test2_no(i8* %p, i8* %q, i64 %n) nounwind { call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 %n, i1 false), !tbaa !2 ret void @@ -63,7 +63,7 @@ ret i32 %t } -; CHECK: define i32 @test3_no(i8* nocapture %p) #5 { +; CHECK: define i32 @test3_no(i8* nocapture %p) #4 { define i32 @test3_no(i8* %p) nounwind { %t = va_arg i8* %p, i32, !tbaa !2 ret i32 %t @@ -76,9 +76,8 @@ ; CHECK: attributes #1 = { norecurse nounwind writeonly } ; CHECK: attributes #2 = { nounwind readonly } ; CHECK: attributes #3 = { nounwind } -; CHECK: attributes #4 = { nounwind readnone } -; CHECK: attributes #5 = { norecurse nounwind } -; CHECK: attributes #6 = { argmemonly nounwind } +; CHECK: attributes #4 = { norecurse nounwind } +; CHECK: attributes #5 = { argmemonly nounwind } ; Root note. !0 = !{ } diff --git a/llvm/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll b/llvm/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll --- a/llvm/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll +++ b/llvm/test/Transforms/FunctionAttrs/2010-10-30-volatile.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,function-attrs' -S | FileCheck %s ; PR8279 @g = constant i32 1 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 @@ -331,14 +331,8 @@ ; } ; ; Verify the maybe-redefined function is not annotated: -; BOTH: define linkonce_odr i32* @maybe_redefined_fn(i32* %r) [[NoInlineNoRecurseNoUnwindUwtable:#[0-9]*]] -; 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* %r) [[NoInlineNoRecurseNoUnwindUwtable:#[0-9]*]] +; BOTH: define linkonce_odr i32* @maybe_redefined_fn(i32* %r) [[NoInlineNoUnwindUwtable]] ; 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]] ; define linkonce_odr i32* @maybe_redefined_fn(i32* %r) #0 { entry: @@ -620,4 +614,4 @@ ; BOTH-DAG: attributes [[NoInlineNoUnwindReadnoneUwtable]] = { noinline nounwind readnone uwtable } ; BOTH-DAG: attributes [[NoInlineNoReturnNoUnwindReadonlyUwtable]] = { noinline noreturn nounwind readonly uwtable } ; BOTH-DAG: attributes [[NoInlineNoUnwindUwtable]] = { noinline nounwind uwtable } -; BOTH-DAG: attributes [[NoInlineNoRecurseNoUnwindUwtable]] = { noinline norecurse nounwind uwtable } +; ATTRIBUTOR-DAG: attributes [[NoInlineNoRecurseNoUnwindUwtable]] = { noinline norecurse nounwind uwtable } diff --git a/llvm/test/Transforms/FunctionAttrs/atomic.ll b/llvm/test/Transforms/FunctionAttrs/atomic.ll --- a/llvm/test/Transforms/FunctionAttrs/atomic.ll +++ b/llvm/test/Transforms/FunctionAttrs/atomic.ll @@ -1,5 +1,5 @@ -; RUN: opt -basicaa -functionattrs -S < %s | FileCheck %s -; RUN: opt -aa-pipeline=basic-aa -passes=function-attrs -S < %s | FileCheck %s +; RUN: opt -basicaa -attributor -functionattrs -S < %s | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='attributor,function-attrs' -S < %s | FileCheck %s ; Atomic load/store to local doesn't affect whether a function is ; readnone/readonly. diff --git a/llvm/test/Transforms/FunctionAttrs/norecurse.ll b/llvm/test/Transforms/FunctionAttrs/norecurse.ll --- a/llvm/test/Transforms/FunctionAttrs/norecurse.ll +++ b/llvm/test/Transforms/FunctionAttrs/norecurse.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -basicaa -functionattrs -rpo-functionattrs -S | FileCheck %s -; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs),rpo-functionattrs' -S | FileCheck %s +; RUN: opt < %s -basicaa -attributor -functionattrs -rpo-functionattrs -S | FileCheck %s +; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(attributor,function-attrs),rpo-functionattrs' -S | FileCheck %s ; CHECK: Function Attrs ; CHECK-SAME: norecurse nounwind readnone diff --git a/llvm/test/Transforms/FunctionAttrs/optnone.ll b/llvm/test/Transforms/FunctionAttrs/optnone.ll --- a/llvm/test/Transforms/FunctionAttrs/optnone.ll +++ b/llvm/test/Transforms/FunctionAttrs/optnone.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,function-attrs' -S | FileCheck %s @x = global i32 0