diff --git a/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp b/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp index 92b90e2559154..a289d35f9b3f1 100644 --- a/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp @@ -110,17 +110,24 @@ StringRef NVPTXLowerUnreachable::getPassName() const { } // ============================================================================= -// Returns whether a `trap` intrinsic should be emitted before I. +// Returns whether a `trap` intrinsic would be emitted before I. // // This is a copy of the logic in SelectionDAGBuilder::visitUnreachable(). // ============================================================================= bool NVPTXLowerUnreachable::isLoweredToTrap(const UnreachableInst &I) const { - if (!TrapUnreachable) - return false; - if (!NoTrapAfterNoreturn) - return true; - const CallInst *Call = dyn_cast_or_null(I.getPrevNode()); - return Call && Call->doesNotReturn(); + if (const auto *Call = dyn_cast_or_null(I.getPrevNode())) { + // We've already emitted a non-continuable trap. + if (Call->isNonContinuableTrap()) + return true; + + // No traps are emitted for calls that do not return + // when this option is enabled. + if (NoTrapAfterNoreturn && Call->doesNotReturn()) + return false; + } + + // In all other cases, we will generate a trap if TrapUnreachable is set. + return TrapUnreachable; } // ============================================================================= diff --git a/llvm/test/CodeGen/NVPTX/unreachable.ll b/llvm/test/CodeGen/NVPTX/unreachable.ll index 011497c4e2340..f9118900cb737 100644 --- a/llvm/test/CodeGen/NVPTX/unreachable.ll +++ b/llvm/test/CodeGen/NVPTX/unreachable.ll @@ -1,18 +1,23 @@ -; RUN: llc < %s -march=nvptx -mcpu=sm_20 -verify-machineinstrs \ +; RUN: llc < %s -march=nvptx -mcpu=sm_20 -verify-machineinstrs -trap-unreachable=false \ ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOTRAP -; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 -verify-machineinstrs \ +; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 -verify-machineinstrs -trap-unreachable=false \ ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOTRAP -; RUN: llc < %s -march=nvptx -mcpu=sm_20 -verify-machineinstrs -trap-unreachable \ +; RUN: llc < %s -march=nvptx -mcpu=sm_20 -verify-machineinstrs -trap-unreachable -no-trap-after-noreturn \ +; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOTRAP +; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 -verify-machineinstrs -trap-unreachable -no-trap-after-noreturn \ +; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOTRAP +; RUN: llc < %s -march=nvptx -mcpu=sm_20 -verify-machineinstrs -trap-unreachable -no-trap-after-noreturn=false \ ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-TRAP -; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 -verify-machineinstrs -trap-unreachable \ +; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 -verify-machineinstrs -trap-unreachable -no-trap-after-noreturn=false \ ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-TRAP ; RUN: %if ptxas && !ptxas-12.0 %{ llc < %s -march=nvptx -mcpu=sm_20 -verify-machineinstrs | %ptxas-verify %} ; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mcpu=sm_20 -verify-machineinstrs | %ptxas-verify %} ; CHECK: .extern .func throw declare void @throw() #0 +declare void @llvm.trap() #0 -; CHECK: .entry kernel_func +; CHECK-LABEL: .entry kernel_func define void @kernel_func() { ; CHECK: call.uni ; CHECK: throw, @@ -24,6 +29,17 @@ define void @kernel_func() { unreachable } +; CHECK-LABEL: kernel_func_2 +define void @kernel_func_2() { +; CHECK: trap; exit; + call void @llvm.trap() + +;; Make sure we avoid emitting two trap instructions. +; CHECK-NOT: trap; +; CHECK-NOT: exit; + unreachable +} + attributes #0 = { noreturn }