diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index eede879e7e80d..d5551758c073e 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1851,11 +1851,19 @@ bool FastISel::selectOperator(const User *I, unsigned Opcode) { return false; } - case Instruction::Unreachable: - if (TM.Options.TrapUnreachable) + case Instruction::Unreachable: { + if (TM.Options.TrapUnreachable) { + if (TM.Options.NoTrapAfterNoreturn) { + const auto *Call = + dyn_cast_or_null(cast(I)->getPrevNode()); + if (Call && Call->doesNotReturn()) + return true; + } + return fastEmit_(MVT::Other, MVT::Other, ISD::TRAP) != 0; - else - return true; + } + return true; + } case Instruction::Alloca: // FunctionLowering has the static-sized case covered. diff --git a/llvm/test/CodeGen/X86/no-trap-after-noreturn-fastisel.ll b/llvm/test/CodeGen/X86/no-trap-after-noreturn-fastisel.ll new file mode 100644 index 0000000000000..5149209f79d15 --- /dev/null +++ b/llvm/test/CodeGen/X86/no-trap-after-noreturn-fastisel.ll @@ -0,0 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O0 -trap-unreachable -no-trap-after-noreturn -fast-isel-abort=3 < %s | FileCheck %s + +declare void @foo() + +define void @noreturn_unreachable() nounwind { +; CHECK-LABEL: noreturn_unreachable: +; CHECK: # %bb.0: +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo@PLT + call void @foo() noreturn + unreachable +}