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 @@ -38,6 +38,7 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/InstrTypes.h" @@ -1622,9 +1623,12 @@ 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)) { + const DominatorTree DT(*F); + if (none_of(*F, [&DT](BasicBlock &BB) { + // FIXME: this doesn't handle recursion or infinite loops. + return DT.isReachableFromEntry(DT.getNode(&BB)) && + basicBlockCanReturn(BB); + })) { F->setDoesNotReturn(); Changed.insert(F); } diff --git a/llvm/test/Transforms/FunctionAttrs/noreturn.ll b/llvm/test/Transforms/FunctionAttrs/noreturn.ll --- a/llvm/test/Transforms/FunctionAttrs/noreturn.ll +++ b/llvm/test/Transforms/FunctionAttrs/noreturn.ll @@ -40,9 +40,8 @@ ret i32 %c } -; CHECK-NOT: Function Attrs: {{.*}}noreturn +; CHECK: Function Attrs: {{.*}}noreturn ; CHECK: @caller5() -; We currently don't handle unreachable blocks. define i32 @caller5() { entry: %c = call i32 @noreturn() @@ -87,4 +86,4 @@ } declare token @llvm.coro.id.retcon.once(i32 %size, i32 %align, i8* %buffer, i8* %prototype, i8* %alloc, i8* %free) -declare i1 @llvm.coro.end(i8*, i1) \ No newline at end of file +declare i1 @llvm.coro.end(i8*, i1)