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 @@ -210,7 +210,7 @@ ReadsMemory |= I->mayReadFromMemory(); } - if (WritesMemory) { + if (WritesMemory) { if (!ReadsMemory) return MAK_WriteOnly; else @@ -1292,35 +1292,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) { @@ -1340,7 +1311,6 @@ Changed |= addNoAliasAttrs(SCCNodes); Changed |= addNonNullAttrs(SCCNodes); Changed |= inferAttrsFromFunctionBodies(SCCNodes); - Changed |= addNoRecurseAttrs(SCCNodes); } return Changed; 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 @@ -308,17 +308,11 @@ ; ; Verify the maybe-redefined function is not annotated: ; -; CHECK: Function Attrs: noinline norecurse nounwind uwtable +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK: define linkonce_odr i32* @maybe_redefined_fn(i32* %r) -; FIXME: We should not derive norecurse for potentially redefined functions! -; Function Attrs: noinline nounwind uwtable -; define linkonce_odr i32* @maybe_redefined_fn(i32* %r) ; -; CHECK: Function Attrs: noinline norecurse nounwind uwtable +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK: define i32* @calls_maybe_redefined_fn(i32* returned %r) -; FIXME: We should not derive norecurse for potentially redefined functions! -; Function Attrs: noinline nounwind uwtable -; define i32* @calls_maybe_redefined_fn(i32* returned %r) define linkonce_odr i32* @maybe_redefined_fn(i32* %r) #0 { entry: ret i32* %r 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 @@ -90,8 +90,9 @@ ret void } -; FIXME: This test exposes a bug: https://llvm.org/PR41336 -; CHECK: Function Attrs: norecurse +; PR41336 +; CHECK: Function Attrs: +; CHECK-NOT: norecurse ; CHECK-NEXT: define i32 @leaf_redefinable() define linkonce_odr i32 @leaf_redefinable() { ret i32 1