From 632d208c78cf7214a0baedd541c133eede30e7df Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sat, 13 Feb 2016 08:47:51 +0000 Subject: [attrs] Move the norecurse deduction to operate on the node set rather than the SCC object, and have it scan the instruction stream directly rather than relying on call records. This makes the behavior of this routine consistent between libc routines and LLVM intrinsics for libc routines. We can go and start teaching it about those being norecurse, but we should behave the same for the intrinsic and the libc routine rather than differently. I chatted with James Molloy and the inconsistency doesn't seem intentional and likely is due to intrinsic calls not being modelled in the call graph analyses. This also fixes a bug where we would deduce norecurse on optnone functions, when generally we try to handle optnone functions as-if they were replaceable and thus unanalyzable. llvm-svn: 260813 --- llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'llvm/lib/Transforms/IPO/FunctionAttrs.cpp') diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 3c0e7ae799f..0cd9b88ea92 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -991,31 +991,32 @@ static bool setDoesNotRecurse(Function &F) { return true; } -static bool addNoRecurseAttrs(const CallGraphSCC &SCC) { +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 (!SCC.isSingular()) + if (SCCNodes.size() != 1) return false; - const CallGraphNode *CGN = *SCC.begin(); - Function *F = CGN->getFunction(); + 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. - if (std::all_of(CGN->begin(), CGN->end(), - [](const CallGraphNode::CallRecord &CR) { - Function *F = CR.second->getFunction(); - return F && F->doesNotRecurse(); - })) - // Function calls a potentially recursive function. - return setDoesNotRecurse(*F); - - // Nothing else we can deduce usefully during the postorder traversal. - return false; + for (Instruction &I : instructions(*F)) + 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); } bool PostOrderFunctionAttrs::runOnSCC(CallGraphSCC &SCC) { @@ -1060,9 +1061,9 @@ bool PostOrderFunctionAttrs::runOnSCC(CallGraphSCC &SCC) { Changed |= addNoAliasAttrs(SCCNodes); Changed |= addNonNullAttrs(SCCNodes, *TLI); Changed |= removeConvergentAttrs(SCCNodes); + Changed |= addNoRecurseAttrs(SCCNodes); } - Changed |= addNoRecurseAttrs(SCC); return Changed; } -- cgit v1.2.3