diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-03-05 14:16:17 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-05-14 11:46:11 +0000 |
commit | d781ede639f2289ccf0889dd138169e1194b656b (patch) | |
tree | fb34a940b224dca9f5e7bdb8eb503e6acbd22b0f /contrib/llvm-project/llvm/lib/Transforms/IPO/FunctionAttrs.cpp | |
parent | d56accc7c3dcc897489b6a07834763a03b9f3d68 (diff) | |
parent | 1ff3a73c1ece7a0a4b7a8457eb4d5c47334b1526 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/IPO/FunctionAttrs.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/contrib/llvm-project/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 213a998d5bba..e2f1944cee63 100644 --- a/contrib/llvm-project/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/contrib/llvm-project/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -1614,6 +1614,26 @@ static bool basicBlockCanReturn(BasicBlock &BB) { return none_of(BB, instructionDoesNotReturn); } +// FIXME: this doesn't handle recursion. +static bool canReturn(Function &F) { + SmallVector<BasicBlock *, 16> Worklist; + SmallPtrSet<BasicBlock *, 16> Visited; + + Visited.insert(&F.front()); + Worklist.push_back(&F.front()); + + do { + BasicBlock *BB = Worklist.pop_back_val(); + if (basicBlockCanReturn(*BB)) + return true; + for (BasicBlock *Succ : successors(BB)) + if (Visited.insert(Succ).second) + Worklist.push_back(Succ); + } while (!Worklist.empty()); + + return false; +} + // Set the noreturn function attribute if possible. static void addNoReturnAttrs(const SCCNodeSet &SCCNodes, SmallSet<Function *, 8> &Changed) { @@ -1622,9 +1642,7 @@ static void addNoReturnAttrs(const SCCNodeSet &SCCNodes, F->doesNotReturn()) continue; - // The function can return if any basic blocks can return. - // FIXME: this doesn't handle recursion or unreachable blocks. - if (none_of(*F, basicBlockCanReturn)) { + if (!canReturn(*F)) { F->setDoesNotReturn(); Changed.insert(F); } |