[llvm] [FastISel] Support unreachable with NoTrapAfterNoReturn (PR #118296)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 2 05:57:04 PST 2024


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/118296

Currently FastISel triggers a fallback if there is an unreachable terminator and the TrapUnreachable option is enabled (the ISD::TRAP selection does not actually work).

Add handling for NoTrapAfterNoReturn, in which case we don't actually need to emit a trap. The test is just there to make sure there is no FastISel fallback (which is why I'm not testing the case without noreturn). We have other tests that check the actual unreachable codegen variations.

>From cf75329325900d1042afb1bb448bbcdfa9ae738e Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 2 Dec 2024 14:44:37 +0100
Subject: [PATCH] [FastISel] Support unreachable with NoTrapAfterNoReturn

Currently FastISel triggers a fallback if there is an unreachable
terminator and the TrapUnreachable option is enabled (the ISD::TRAP
selection does not actually work).

Add handling for NoTrapAfterNoReturn, in which case we don't
actually need to emit a trap. The test is just there to make sure
there is no FastISel fallback (which is why I'm not testing the
case without noreturn). We have other tests that check the actual
unreachable codegen variations.
---
 llvm/lib/CodeGen/SelectionDAG/FastISel.cpp       | 16 ++++++++++++----
 .../X86/no-trap-after-noreturn-fastisel.ll       | 13 +++++++++++++
 2 files changed, 25 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/no-trap-after-noreturn-fastisel.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
index eede879e7e80d1..d5551758c073e9 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<CallInst>(cast<Instruction>(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 00000000000000..5149209f79d156
--- /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 at PLT
+  call void @foo() noreturn
+  unreachable
+}



More information about the llvm-commits mailing list