diff options
author | Justin Lebar <jlebar@google.com> | 2016-02-22 17:51:35 +0000 |
---|---|---|
committer | Justin Lebar <jlebar@google.com> | 2016-02-22 17:51:35 +0000 |
commit | 7bf9187abbdbe5c789528bc4961a56baed2eb303 (patch) | |
tree | 8c176fadbfe52f6d854c4edb03fc9dfa8112164e /llvm/lib/Transforms/IPO/FunctionAttrs.cpp | |
parent | f62b165a0403434999cf77e265ce3dafce8dddcc (diff) | |
download | bcm5719-llvm-7bf9187abbdbe5c789528bc4961a56baed2eb303.tar.gz bcm5719-llvm-7bf9187abbdbe5c789528bc4961a56baed2eb303.zip |
[attrs] Handle convergent CallSites.
Summary:
Previously we had a notion of convergent functions but not of convergent
calls. This is insufficient to correctly analyze calls where the target
is unknown, e.g. indirect calls.
Now a call is convergent if it targets a known-convergent function, or
if it's explicitly marked as convergent. As usual, we can remove
convergent where we can prove that no convergent operations are
performed in the call.
Reviewers: chandlerc, jingyue
Subscribers: hfinkel, jhen, tra, llvm-commits
Differential Revision: http://reviews.llvm.org/D17317
llvm-svn: 261544
Diffstat (limited to 'llvm/lib/Transforms/IPO/FunctionAttrs.cpp')
-rw-r--r-- | llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 62 |
1 files changed, 25 insertions, 37 deletions
diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 2eec4381a90..c321afb8aae 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -903,49 +903,37 @@ static bool addNonNullAttrs(const SCCNodeSet &SCCNodes, return MadeChange; } -/// Removes convergent attributes where we can prove that none of the SCC's -/// callees are themselves convergent. Returns true if successful at removing -/// the attribute. +/// Remove the convergent attribute from all functions in the SCC if every +/// callsite within the SCC is not convergent (except for calls to functions +/// within the SCC). Returns true if changes were made. static bool removeConvergentAttrs(const SCCNodeSet &SCCNodes) { - // Determines whether a function can be made non-convergent, ignoring all - // other functions in SCC. (A function can *actually* be made non-convergent - // only if all functions in its SCC can be made convergent.) - auto CanRemoveConvergent = [&](Function *F) { - if (!F->isConvergent()) - return true; - - // Can't remove convergent from declarations. - if (F->isDeclaration()) - return false; - - for (Instruction &I : instructions(*F)) - if (auto CS = CallSite(&I)) { - // Can't remove convergent if any of F's callees -- ignoring functions - // in the SCC itself -- are convergent. This needs to consider both - // function calls and intrinsic calls. We also assume indirect calls - // might call a convergent function. - // FIXME: We should revisit this when we put convergent onto calls - // instead of functions so that indirect calls which should be - // convergent are required to be marked as such. - Function *Callee = CS.getCalledFunction(); - if (!Callee || (SCCNodes.count(Callee) == 0 && Callee->isConvergent())) - return false; - } - - return true; - }; + // No point checking if none of SCCNodes is convergent. + if (!llvm::any_of(SCCNodes, [](Function *F) { return F->isConvergent(); })) + return false; - // We can remove the convergent attr from functions in the SCC if they all - // can be made non-convergent (because they call only non-convergent - // functions, other than each other). - if (!llvm::all_of(SCCNodes, CanRemoveConvergent)) + // Can't remove convergent from function declarations. + if (llvm::any_of(SCCNodes, [](Function *F) { return F->isDeclaration(); })) return false; - // If we got here, all of the SCC's callees are non-convergent. Therefore all - // of the SCC's functions can be marked as non-convergent. + // Can't remove convergent if any of our functions has a convergent call to a + // function not in the SCC. + for (Function *F : SCCNodes) + for (Instruction &I : instructions(*F)) { + CallSite CS(&I); + // Bail if is CS a convergent call to a function not in the SCC. + if (CS && CS.isConvergent() && + SCCNodes.count(CS.getCalledFunction()) == 0) + return false; + } + + // If we got here, all of the calls the SCC makes to functions not in the SCC + // are non-convergent. Therefore all of the SCC's functions can also be made + // non-convergent. We'll remove the attr from the callsites in + // InstCombineCalls. for (Function *F : SCCNodes) { if (F->isConvergent()) - DEBUG(dbgs() << "Removing convergent attr from " << F->getName() << "\n"); + DEBUG(dbgs() << "Removing convergent attr from fn " << F->getName() + << "\n"); F->setNotConvergent(); } return true; |