[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-05 Thread Heejin Ahn via cfe-commits

https://github.com/aheejin closed 
https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-05 Thread Heejin Ahn via cfe-commits


@@ -95,57 +92,4 @@ define i32 @missing_ret_noreturn_unreachable() {
 ; CHECK-NEXT:end_function
   call void @ext_never_return()
   unreachable
-}
-
-; We could emit no instructions at all for the llvm unreachables in these next
-; three tests, as the signatures match and reaching llvm unreachable is
-; undefined behaviour. But currently, wasm unreachable is emitted for them.
-
-define void @void_sig_match_unreachable() {
-; CHECK-LABEL: void_sig_match_unreachable:
-; CHECK: .functype void_sig_match_unreachable () -> ()
-; CHECK-NEXT:  # %bb.0:
-; CHECK-NEXT:call ext_func
-; CHECK-NEXT:unreachable
-; CHECK-NEXT:end_function
-  call void @ext_func()
-  unreachable
-}
-
-define i32 @i32_sig_match_unreachable() {
-; CHECK-LABEL: i32_sig_match_unreachable:
-; CHECK: .functype i32_sig_match_unreachable () -> (i32)
-; CHECK-NEXT:  # %bb.0:
-; CHECK-NEXT:call ext_func_i32
-; CHECK-NEXT:drop
-; CHECK-NEXT:unreachable
-; CHECK-NEXT:end_function
-  call i32 @ext_func_i32()
-  unreachable
-}
-
-define void @void_sig_match_noreturn_unreachable() {
-; CHECK-LABEL: void_sig_match_noreturn_unreachable:
-; CHECK: .functype void_sig_match_noreturn_unreachable () -> ()
-; CHECK-NEXT:  # %bb.0:
-; CHECK-NEXT:call ext_never_return
-; CHECK-NEXT:unreachable
-; CHECK-NEXT:end_function
-  call void @ext_never_return()
-  unreachable
-}
-
-; This function currently doesn't emit wasm unreachable, even though the final
-; "ret void" instruction is dead code and could be replaced with an llvm
-; unreachable. Compare and contrast with the above function,
-; @void_sig_match_noreturn_unreachable().
-define void @void_sig_match_noreturn_ret() {
-; CHECK-LABEL: void_sig_match_noreturn_ret:
-; CHECK: .functype void_sig_match_noreturn_ret () -> ()
-; CHECK-NEXT:  # %bb.0:
-; CHECK-NEXT:call ext_never_return
-; CHECK-NEXT:# fallthrough-return
-; CHECK-NEXT:end_function
-  call void @ext_never_return()
-  ret void
-}
+}

aheejin wrote:

No newline at the end

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-05 Thread Heejin Ahn via cfe-commits


@@ -6,12 +6,8 @@
 ; "end_function" lines intact when you commit.
 
 
-; --trap-unreachable and --no-trap-after-noreturn are sensitive and bug-prone
-; options for the WebAssembly back-end as, unlike in many other target
-; architechtures, unreachable code being compiled to a trap instruction (i.e.
-; WebAssembly "unreachable" instruction) is often necessary for the code to
-; pass wasm's validation step. We test that various combinations of
-; these options produce the expected output.
+; The --trap-unreachable and --no-trap-after-noreturn options are ignored, and
+; should have no effect.

aheejin wrote:

```suggestion
; Wasm, to generate valid code, always internally sets `--trap-unreachable` to 1
; and `--no-trap-after-noreturn` to 0, and these command lines options, if
; explicitly given, are ignored. Various combinations of these options should
; have no effect and should not generate invalid code.
```

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-04 Thread Matt Harding via cfe-commits

https://github.com/majaha updated 
https://github.com/llvm/llvm-project/pull/65876

>From 7c43c803764bf9e0256d4e3e9f497d2622bb8f69 Mon Sep 17 00:00:00 2001
From: Matt Harding 
Date: Fri, 25 Aug 2023 06:19:14 +0100
Subject: [PATCH 01/13] Add no-trap-after-noreturn flag and wasm tests

Add the command line flag --no-trap-after-noreturn.
Add and improve tests related to WebAssembly's unreachable instruction.
Also fix various typos.
---
 llvm/include/llvm/CodeGen/MachineFunction.h   |   2 +-
 llvm/include/llvm/CodeGen/MachineInstr.h  |   2 +-
 llvm/lib/CodeGen/LLVMTargetMachine.cpp|   7 +
 .../WebAssembly/WebAssemblyCFGStackify.cpp|   2 +-
 llvm/test/CodeGen/WebAssembly/unreachable.ll  | 178 +++---
 5 files changed, 167 insertions(+), 24 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h 
b/llvm/include/llvm/CodeGen/MachineFunction.h
index 6c2da626ea54b4d..8f1651c2958e591 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -266,7 +266,7 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
   // RegInfo - Information about each register in use in the function.
   MachineRegisterInfo *RegInfo;
 
-  // Used to keep track of target-specific per-machine function information for
+  // Used to keep track of target-specific per-machine-function information for
   // the target implementation.
   MachineFunctionInfo *MFInfo;
 
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h 
b/llvm/include/llvm/CodeGen/MachineInstr.h
index 03fb15f77c65cbb..8367f999fcc76d3 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1276,7 +1276,7 @@ class MachineInstr
   /// eraseFromBundle() to erase individual bundled instructions.
   void eraseFromParent();
 
-  /// Unlink 'this' form its basic block and delete it.
+  /// Unlink 'this' from its basic block and delete it.
   ///
   /// If the instruction is part of a bundle, the other instructions in the
   /// bundle remain bundled.
diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp 
b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
index d02ec1db1165d41..aadc3709b85bfb7 100644
--- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
@@ -37,6 +37,11 @@ static cl::opt
 EnableTrapUnreachable("trap-unreachable", cl::Hidden,
   cl::desc("Enable generating trap for unreachable"));
 
+static cl::opt
+EnableNoTrapAfterNoreturn("no-trap-after-noreturn", cl::Hidden,
+  cl::desc("Do not emit a trap instruction for 
'unreachable' IR instructions "
+  "after noreturn calls, even if 
--trap-unreachable is set."));
+
 void LLVMTargetMachine::initAsmInfo() {
   MRI.reset(TheTarget.createMCRegInfo(getTargetTriple().str()));
   assert(MRI && "Unable to create reg info");
@@ -95,6 +100,8 @@ LLVMTargetMachine::LLVMTargetMachine(const Target ,
 
   if (EnableTrapUnreachable)
 this->Options.TrapUnreachable = true;
+  if (EnableNoTrapAfterNoreturn)
+this->Options.NoTrapAfterNoreturn = true;
 }
 
 TargetTransformInfo
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index 131e99c66fa2e5a..d8cbddf74545da6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -667,7 +667,7 @@ void 
WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction ) {
 
   // When there is an unconditional branch right before a catch instruction and
   // it branches to the end of end_try marker, we don't need the branch, 
because
-  // it there is no exception, the control flow transfers to that point anyway.
+  // if there is no exception, the control flow transfers to that point anyway.
   // bb0:
   //   try
   // ...
diff --git a/llvm/test/CodeGen/WebAssembly/unreachable.ll 
b/llvm/test/CodeGen/WebAssembly/unreachable.ll
index ad1c90090ac58bf..1bac30b842e1e05 100644
--- a/llvm/test/CodeGen/WebAssembly/unreachable.ll
+++ b/llvm/test/CodeGen/WebAssembly/unreachable.ll
@@ -1,33 +1,169 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s --check-prefixes 
CHECK,NORMAL
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s --check-prefixes CHECK,NORMAL
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s 
--check-prefixes CHECK,NORMAL
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s --check-prefixes CHECK,NORMAL
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s 

[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-04 Thread Matt Harding via cfe-commits

https://github.com/majaha updated 
https://github.com/llvm/llvm-project/pull/65876

>From 7c43c803764bf9e0256d4e3e9f497d2622bb8f69 Mon Sep 17 00:00:00 2001
From: Matt Harding 
Date: Fri, 25 Aug 2023 06:19:14 +0100
Subject: [PATCH 01/12] Add no-trap-after-noreturn flag and wasm tests

Add the command line flag --no-trap-after-noreturn.
Add and improve tests related to WebAssembly's unreachable instruction.
Also fix various typos.
---
 llvm/include/llvm/CodeGen/MachineFunction.h   |   2 +-
 llvm/include/llvm/CodeGen/MachineInstr.h  |   2 +-
 llvm/lib/CodeGen/LLVMTargetMachine.cpp|   7 +
 .../WebAssembly/WebAssemblyCFGStackify.cpp|   2 +-
 llvm/test/CodeGen/WebAssembly/unreachable.ll  | 178 +++---
 5 files changed, 167 insertions(+), 24 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h 
b/llvm/include/llvm/CodeGen/MachineFunction.h
index 6c2da626ea54b4d..8f1651c2958e591 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -266,7 +266,7 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
   // RegInfo - Information about each register in use in the function.
   MachineRegisterInfo *RegInfo;
 
-  // Used to keep track of target-specific per-machine function information for
+  // Used to keep track of target-specific per-machine-function information for
   // the target implementation.
   MachineFunctionInfo *MFInfo;
 
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h 
b/llvm/include/llvm/CodeGen/MachineInstr.h
index 03fb15f77c65cbb..8367f999fcc76d3 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1276,7 +1276,7 @@ class MachineInstr
   /// eraseFromBundle() to erase individual bundled instructions.
   void eraseFromParent();
 
-  /// Unlink 'this' form its basic block and delete it.
+  /// Unlink 'this' from its basic block and delete it.
   ///
   /// If the instruction is part of a bundle, the other instructions in the
   /// bundle remain bundled.
diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp 
b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
index d02ec1db1165d41..aadc3709b85bfb7 100644
--- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
@@ -37,6 +37,11 @@ static cl::opt
 EnableTrapUnreachable("trap-unreachable", cl::Hidden,
   cl::desc("Enable generating trap for unreachable"));
 
+static cl::opt
+EnableNoTrapAfterNoreturn("no-trap-after-noreturn", cl::Hidden,
+  cl::desc("Do not emit a trap instruction for 
'unreachable' IR instructions "
+  "after noreturn calls, even if 
--trap-unreachable is set."));
+
 void LLVMTargetMachine::initAsmInfo() {
   MRI.reset(TheTarget.createMCRegInfo(getTargetTriple().str()));
   assert(MRI && "Unable to create reg info");
@@ -95,6 +100,8 @@ LLVMTargetMachine::LLVMTargetMachine(const Target ,
 
   if (EnableTrapUnreachable)
 this->Options.TrapUnreachable = true;
+  if (EnableNoTrapAfterNoreturn)
+this->Options.NoTrapAfterNoreturn = true;
 }
 
 TargetTransformInfo
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index 131e99c66fa2e5a..d8cbddf74545da6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -667,7 +667,7 @@ void 
WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction ) {
 
   // When there is an unconditional branch right before a catch instruction and
   // it branches to the end of end_try marker, we don't need the branch, 
because
-  // it there is no exception, the control flow transfers to that point anyway.
+  // if there is no exception, the control flow transfers to that point anyway.
   // bb0:
   //   try
   // ...
diff --git a/llvm/test/CodeGen/WebAssembly/unreachable.ll 
b/llvm/test/CodeGen/WebAssembly/unreachable.ll
index ad1c90090ac58bf..1bac30b842e1e05 100644
--- a/llvm/test/CodeGen/WebAssembly/unreachable.ll
+++ b/llvm/test/CodeGen/WebAssembly/unreachable.ll
@@ -1,33 +1,169 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s --check-prefixes 
CHECK,NORMAL
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s --check-prefixes CHECK,NORMAL
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s 
--check-prefixes CHECK,NORMAL
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s --check-prefixes CHECK,NORMAL
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s 

[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-04 Thread Heejin Ahn via cfe-commits

https://github.com/aheejin edited 
https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-04 Thread Heejin Ahn via cfe-commits

https://github.com/aheejin edited 
https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-04 Thread Heejin Ahn via cfe-commits


@@ -1,33 +1,151 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
+; The assertions in this file were autogenerated by
+; utils/update_llc_test_checks.py, but were hand-edited to add the
+; "end_function" lines to prevent the tests from passing when there
+; are superfluous instructions at the end of a function.
+; You can run update_llc_test_checks.py again, but please keep the
+; "end_function" lines intact when you commit.
 
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+
+; --trap-unreachable and --no-trap-after-noreturn are sensitive and bug-prone
+; options for the WebAssembly back-end as, unlike in many other target
+; architechtures, unreachable code being compiled to a trap instruction (i.e.
+; WebAssembly "unreachable" instruction) is often necessary for the code to
+; pass wasm's validation step. We test that various combinations of
+; these options produce the expected output.
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to wasm
+; unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @debugtrap_ret_void() {
+; CHECK-LABEL: debugtrap_ret_void:
+; CHECK: .functype debugtrap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.debugtrap()
   ret void
 }
+
+; LLVM trap followed by LLVM unreachable could become exactly one wasm
+; unreachable, but two are emitted currently.
+define void @trap_unreacheable() {
+; CHECK-LABEL: trap_unreacheable:
+; CHECK: .functype trap_unreacheable () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @llvm.trap()
+  unreachable
+}
+
+
+; Test that LLVM unreachable instruction is lowered to wasm unreachable when
+; necessary to fulfill the wasm operand stack requirements.
+
+declare void @ext_func()
+declare i32 @ext_func_i32()
+declare void @ext_never_return() noreturn
+
+; This test emits wasm unreachable to fill in for the missing i32 return value,
+; which is necessary for the function to pass wasm validation.
+define i32 @missing_ret_unreach() {
+; CHECK-LABEL: missing_ret_unreach:
+; CHECK: .functype missing_ret_unreach () -> (i32)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_func
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @ext_func()
+  unreachable
+}
+
+; This is similar to the above test, but ensures wasm unreachable is emitted
+; even after a noreturn call.

aheejin wrote:

We can be more direct by saying that there is a LLVM optimization that omits 
`unreachable` if that comes after a `noreturn` function, but because we always 
set `--no-trap-after-noreturn`  internally, we emit the `unreachable`.

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-04 Thread Heejin Ahn via cfe-commits


@@ -1,33 +1,151 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
+; The assertions in this file were autogenerated by
+; utils/update_llc_test_checks.py, but were hand-edited to add the
+; "end_function" lines to prevent the tests from passing when there
+; are superfluous instructions at the end of a function.
+; You can run update_llc_test_checks.py again, but please keep the
+; "end_function" lines intact when you commit.
 
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+
+; --trap-unreachable and --no-trap-after-noreturn are sensitive and bug-prone
+; options for the WebAssembly back-end as, unlike in many other target
+; architechtures, unreachable code being compiled to a trap instruction (i.e.
+; WebAssembly "unreachable" instruction) is often necessary for the code to
+; pass wasm's validation step. We test that various combinations of
+; these options produce the expected output.
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to wasm
+; unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @debugtrap_ret_void() {
+; CHECK-LABEL: debugtrap_ret_void:
+; CHECK: .functype debugtrap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.debugtrap()
   ret void
 }
+
+; LLVM trap followed by LLVM unreachable could become exactly one wasm
+; unreachable, but two are emitted currently.
+define void @trap_unreacheable() {
+; CHECK-LABEL: trap_unreacheable:
+; CHECK: .functype trap_unreacheable () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @llvm.trap()
+  unreachable
+}
+
+
+; Test that LLVM unreachable instruction is lowered to wasm unreachable when
+; necessary to fulfill the wasm operand stack requirements.
+
+declare void @ext_func()
+declare i32 @ext_func_i32()
+declare void @ext_never_return() noreturn
+
+; This test emits wasm unreachable to fill in for the missing i32 return value,
+; which is necessary for the function to pass wasm validation.
+define i32 @missing_ret_unreach() {
+; CHECK-LABEL: missing_ret_unreach:
+; CHECK: .functype missing_ret_unreach () -> (i32)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_func
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @ext_func()
+  unreachable
+}
+
+; This is similar to the above test, but ensures wasm unreachable is emitted
+; even after a noreturn call.
+define i32 @missing_ret_noreturn_unreach() {
+; CHECK-LABEL: missing_ret_noreturn_unreach:
+; CHECK: .functype missing_ret_noreturn_unreach () -> (i32)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_never_return
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @ext_never_return()
+  unreachable
+}
+
+; We could emit no instructions at all for the llvm unreachables in these next
+; three tests, as the signatures match and reaching llvm unreachable is
+; undefined behaviour. But currently, wasm unreachable is emitted for them.
+
+define void @void_sig_match_unreach() {
+; CHECK-LABEL: void_sig_match_unreach:
+; CHECK: .functype void_sig_match_unreach () -> ()

aheejin wrote:

```suggestion
define void @void_sig_match_unreachable() {
; CHECK-LABEL: void_sig_match_unreachable:
; CHECK: .functype void_sig_match_uanreachable () -> ()
```

https://github.com/llvm/llvm-project/pull/65876

[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-04 Thread Heejin Ahn via cfe-commits


@@ -1,33 +1,151 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
+; The assertions in this file were autogenerated by
+; utils/update_llc_test_checks.py, but were hand-edited to add the
+; "end_function" lines to prevent the tests from passing when there
+; are superfluous instructions at the end of a function.
+; You can run update_llc_test_checks.py again, but please keep the
+; "end_function" lines intact when you commit.
 
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+
+; --trap-unreachable and --no-trap-after-noreturn are sensitive and bug-prone
+; options for the WebAssembly back-end as, unlike in many other target
+; architechtures, unreachable code being compiled to a trap instruction (i.e.
+; WebAssembly "unreachable" instruction) is often necessary for the code to
+; pass wasm's validation step. We test that various combinations of
+; these options produce the expected output.
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to wasm
+; unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @debugtrap_ret_void() {
+; CHECK-LABEL: debugtrap_ret_void:
+; CHECK: .functype debugtrap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.debugtrap()
   ret void
 }
+
+; LLVM trap followed by LLVM unreachable could become exactly one wasm
+; unreachable, but two are emitted currently.
+define void @trap_unreacheable() {
+; CHECK-LABEL: trap_unreacheable:
+; CHECK: .functype trap_unreacheable () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @llvm.trap()
+  unreachable
+}
+
+
+; Test that LLVM unreachable instruction is lowered to wasm unreachable when
+; necessary to fulfill the wasm operand stack requirements.
+
+declare void @ext_func()
+declare i32 @ext_func_i32()
+declare void @ext_never_return() noreturn
+
+; This test emits wasm unreachable to fill in for the missing i32 return value,
+; which is necessary for the function to pass wasm validation.
+define i32 @missing_ret_unreach() {
+; CHECK-LABEL: missing_ret_unreach:
+; CHECK: .functype missing_ret_unreach () -> (i32)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_func
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @ext_func()
+  unreachable
+}
+
+; This is similar to the above test, but ensures wasm unreachable is emitted
+; even after a noreturn call.
+define i32 @missing_ret_noreturn_unreach() {
+; CHECK-LABEL: missing_ret_noreturn_unreach:
+; CHECK: .functype missing_ret_noreturn_unreach () -> (i32)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_never_return
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @ext_never_return()
+  unreachable
+}
+
+; We could emit no instructions at all for the llvm unreachables in these next

aheejin wrote:

I don't think tests below this line are really necessary. They are not related 
to the bug you are fixing.

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-04 Thread Heejin Ahn via cfe-commits


@@ -1,33 +1,151 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
+; The assertions in this file were autogenerated by
+; utils/update_llc_test_checks.py, but were hand-edited to add the
+; "end_function" lines to prevent the tests from passing when there
+; are superfluous instructions at the end of a function.
+; You can run update_llc_test_checks.py again, but please keep the
+; "end_function" lines intact when you commit.
 
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+
+; --trap-unreachable and --no-trap-after-noreturn are sensitive and bug-prone
+; options for the WebAssembly back-end as, unlike in many other target
+; architechtures, unreachable code being compiled to a trap instruction (i.e.
+; WebAssembly "unreachable" instruction) is often necessary for the code to
+; pass wasm's validation step. We test that various combinations of
+; these options produce the expected output.
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to wasm
+; unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @debugtrap_ret_void() {
+; CHECK-LABEL: debugtrap_ret_void:
+; CHECK: .functype debugtrap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.debugtrap()
   ret void
 }
+
+; LLVM trap followed by LLVM unreachable could become exactly one wasm
+; unreachable, but two are emitted currently.
+define void @trap_unreacheable() {
+; CHECK-LABEL: trap_unreacheable:
+; CHECK: .functype trap_unreacheable () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @llvm.trap()
+  unreachable
+}
+
+
+; Test that LLVM unreachable instruction is lowered to wasm unreachable when
+; necessary to fulfill the wasm operand stack requirements.
+
+declare void @ext_func()
+declare i32 @ext_func_i32()
+declare void @ext_never_return() noreturn
+
+; This test emits wasm unreachable to fill in for the missing i32 return value,
+; which is necessary for the function to pass wasm validation.
+define i32 @missing_ret_unreach() {
+; CHECK-LABEL: missing_ret_unreach:
+; CHECK: .functype missing_ret_unreach () -> (i32)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_func
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @ext_func()
+  unreachable
+}
+
+; This is similar to the above test, but ensures wasm unreachable is emitted
+; even after a noreturn call.
+define i32 @missing_ret_noreturn_unreach() {
+; CHECK-LABEL: missing_ret_noreturn_unreach:
+; CHECK: .functype missing_ret_noreturn_unreach () -> (i32)

aheejin wrote:

```suggestion
define i32 @missing_ret_noreturn_unreachable() {
; CHECK-LABEL: missing_ret_noreturn_unreachable:
; CHECK: .functype missing_ret_noreturn_unreachable () -> (i32)
```

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-04 Thread Heejin Ahn via cfe-commits


@@ -1,33 +1,151 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
+; The assertions in this file were autogenerated by
+; utils/update_llc_test_checks.py, but were hand-edited to add the
+; "end_function" lines to prevent the tests from passing when there
+; are superfluous instructions at the end of a function.
+; You can run update_llc_test_checks.py again, but please keep the
+; "end_function" lines intact when you commit.
 
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+
+; --trap-unreachable and --no-trap-after-noreturn are sensitive and bug-prone
+; options for the WebAssembly back-end as, unlike in many other target
+; architechtures, unreachable code being compiled to a trap instruction (i.e.
+; WebAssembly "unreachable" instruction) is often necessary for the code to
+; pass wasm's validation step. We test that various combinations of
+; these options produce the expected output.
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to wasm
+; unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @debugtrap_ret_void() {
+; CHECK-LABEL: debugtrap_ret_void:
+; CHECK: .functype debugtrap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.debugtrap()
   ret void
 }
+
+; LLVM trap followed by LLVM unreachable could become exactly one wasm
+; unreachable, but two are emitted currently.
+define void @trap_unreacheable() {
+; CHECK-LABEL: trap_unreacheable:
+; CHECK: .functype trap_unreacheable () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @llvm.trap()
+  unreachable
+}
+
+
+; Test that LLVM unreachable instruction is lowered to wasm unreachable when
+; necessary to fulfill the wasm operand stack requirements.
+
+declare void @ext_func()
+declare i32 @ext_func_i32()
+declare void @ext_never_return() noreturn
+
+; This test emits wasm unreachable to fill in for the missing i32 return value,
+; which is necessary for the function to pass wasm validation.

aheejin wrote:

As I said before, I think this comment is confusing. We don't emit 
`unreachable` to "fill in for the missing i32 return value". We emit 
`unreachable` because there is LLVM `unreachable`.

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-10-01 Thread Matt Harding via cfe-commits

https://github.com/majaha updated 
https://github.com/llvm/llvm-project/pull/65876

>From 7c43c803764bf9e0256d4e3e9f497d2622bb8f69 Mon Sep 17 00:00:00 2001
From: Matt Harding 
Date: Fri, 25 Aug 2023 06:19:14 +0100
Subject: [PATCH 01/10] Add no-trap-after-noreturn flag and wasm tests

Add the command line flag --no-trap-after-noreturn.
Add and improve tests related to WebAssembly's unreachable instruction.
Also fix various typos.
---
 llvm/include/llvm/CodeGen/MachineFunction.h   |   2 +-
 llvm/include/llvm/CodeGen/MachineInstr.h  |   2 +-
 llvm/lib/CodeGen/LLVMTargetMachine.cpp|   7 +
 .../WebAssembly/WebAssemblyCFGStackify.cpp|   2 +-
 llvm/test/CodeGen/WebAssembly/unreachable.ll  | 178 +++---
 5 files changed, 167 insertions(+), 24 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h 
b/llvm/include/llvm/CodeGen/MachineFunction.h
index 6c2da626ea54b4d..8f1651c2958e591 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -266,7 +266,7 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
   // RegInfo - Information about each register in use in the function.
   MachineRegisterInfo *RegInfo;
 
-  // Used to keep track of target-specific per-machine function information for
+  // Used to keep track of target-specific per-machine-function information for
   // the target implementation.
   MachineFunctionInfo *MFInfo;
 
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h 
b/llvm/include/llvm/CodeGen/MachineInstr.h
index 03fb15f77c65cbb..8367f999fcc76d3 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1276,7 +1276,7 @@ class MachineInstr
   /// eraseFromBundle() to erase individual bundled instructions.
   void eraseFromParent();
 
-  /// Unlink 'this' form its basic block and delete it.
+  /// Unlink 'this' from its basic block and delete it.
   ///
   /// If the instruction is part of a bundle, the other instructions in the
   /// bundle remain bundled.
diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp 
b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
index d02ec1db1165d41..aadc3709b85bfb7 100644
--- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
@@ -37,6 +37,11 @@ static cl::opt
 EnableTrapUnreachable("trap-unreachable", cl::Hidden,
   cl::desc("Enable generating trap for unreachable"));
 
+static cl::opt
+EnableNoTrapAfterNoreturn("no-trap-after-noreturn", cl::Hidden,
+  cl::desc("Do not emit a trap instruction for 
'unreachable' IR instructions "
+  "after noreturn calls, even if 
--trap-unreachable is set."));
+
 void LLVMTargetMachine::initAsmInfo() {
   MRI.reset(TheTarget.createMCRegInfo(getTargetTriple().str()));
   assert(MRI && "Unable to create reg info");
@@ -95,6 +100,8 @@ LLVMTargetMachine::LLVMTargetMachine(const Target ,
 
   if (EnableTrapUnreachable)
 this->Options.TrapUnreachable = true;
+  if (EnableNoTrapAfterNoreturn)
+this->Options.NoTrapAfterNoreturn = true;
 }
 
 TargetTransformInfo
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index 131e99c66fa2e5a..d8cbddf74545da6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -667,7 +667,7 @@ void 
WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction ) {
 
   // When there is an unconditional branch right before a catch instruction and
   // it branches to the end of end_try marker, we don't need the branch, 
because
-  // it there is no exception, the control flow transfers to that point anyway.
+  // if there is no exception, the control flow transfers to that point anyway.
   // bb0:
   //   try
   // ...
diff --git a/llvm/test/CodeGen/WebAssembly/unreachable.ll 
b/llvm/test/CodeGen/WebAssembly/unreachable.ll
index ad1c90090ac58bf..1bac30b842e1e05 100644
--- a/llvm/test/CodeGen/WebAssembly/unreachable.ll
+++ b/llvm/test/CodeGen/WebAssembly/unreachable.ll
@@ -1,33 +1,169 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s --check-prefixes 
CHECK,NORMAL
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s --check-prefixes CHECK,NORMAL
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s 
--check-prefixes CHECK,NORMAL
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s --check-prefixes CHECK,NORMAL
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s 

[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-27 Thread Matt Harding via cfe-commits

https://github.com/majaha edited https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-27 Thread Matt Harding via cfe-commits


@@ -1,33 +1,133 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to
+; wasm unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @dtrap_ret_void() {
+; CHECK-LABEL: dtrap_ret_void:
+; CHECK: .functype dtrap_ret_void () -> ()

majaha wrote:

 sounds good

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-27 Thread Matt Harding via cfe-commits


@@ -1,33 +1,133 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to
+; wasm unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @dtrap_ret_void() {
+; CHECK-LABEL: dtrap_ret_void:
+; CHECK: .functype dtrap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.debugtrap()
   ret void
 }
+
+; LLVM trap followed by LLVM unreachable could become exactly one
+; wasm unreachable, but two are emitted currently.
+define void @trap_unreach() {
+; CHECK-LABEL: trap_unreach:
+; CHECK: .functype trap_unreach () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @llvm.trap()
+  unreachable
+}
+
+
+; Test that LLVM unreachable instruction is lowered to wasm unreachable when
+; necessary to fulfill the wasm operand stack requirements.
+
+declare void @ext_func()
+declare i32 @ext_func_i32()
+declare void @ext_never_return() noreturn
+
+; This test emits wasm unreachable to fill in for the missing i32 return value.

majaha wrote:

In the low-level specifics of the compiler, yes.

But at the higher level of what the wasm specification requires, this wasm 
`unreachable` fulfils the typing requirements of the code block, "filling in" 
for the i32 value that wasm validation expects to be at the top of the operand 
stack, by virtue of being stack polymorphic.

We could in theory emit an `i32.const 42` instruction, or anything else that 
fills in for the missing return value because reaching llvm `unreachable` is 
undefined behaviour. But wasm `unreachable` has a single byte encoding, and it 
traps as the most sensible form of UB.

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-27 Thread Matt Harding via cfe-commits


@@ -1,33 +1,133 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to
+; wasm unreachable.

majaha wrote:

Yeah, I just liked it better when "wasm unreachable" was all together on one 
line. We can change it if you like.

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-27 Thread Heejin Ahn via cfe-commits

https://github.com/aheejin edited 
https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-27 Thread Heejin Ahn via cfe-commits


@@ -1,33 +1,133 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to
+; wasm unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @dtrap_ret_void() {
+; CHECK-LABEL: dtrap_ret_void:
+; CHECK: .functype dtrap_ret_void () -> ()

aheejin wrote:

```suggestion
define void @debugtrap_ret_void() {
; CHECK-LABEL: debugtrap_ret_void:
; CHECK: .functype debugtrap_ret_void () -> ()
```
Nit: Not shortening it sounds clearer to me

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-27 Thread Heejin Ahn via cfe-commits


@@ -1,33 +1,133 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to
+; wasm unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @dtrap_ret_void() {
+; CHECK-LABEL: dtrap_ret_void:
+; CHECK: .functype dtrap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.debugtrap()
   ret void
 }
+
+; LLVM trap followed by LLVM unreachable could become exactly one
+; wasm unreachable, but two are emitted currently.
+define void @trap_unreach() {
+; CHECK-LABEL: trap_unreach:
+; CHECK: .functype trap_unreach () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @llvm.trap()
+  unreachable
+}
+
+
+; Test that LLVM unreachable instruction is lowered to wasm unreachable when
+; necessary to fulfill the wasm operand stack requirements.
+
+declare void @ext_func()
+declare i32 @ext_func_i32()
+declare void @ext_never_return() noreturn
+
+; This test emits wasm unreachable to fill in for the missing i32 return value.

aheejin wrote:

This confuses me. Wasm `unreachable` is not emitted to fill in for the missing 
`i32`. It is emitted because there's LLVM `unreachable` in the bitcode.

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-27 Thread Heejin Ahn via cfe-commits


@@ -1,33 +1,133 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to
+; wasm unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @dtrap_ret_void() {
+; CHECK-LABEL: dtrap_ret_void:
+; CHECK: .functype dtrap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.debugtrap()
   ret void
 }
+
+; LLVM trap followed by LLVM unreachable could become exactly one
+; wasm unreachable, but two are emitted currently.

aheejin wrote:

```suggestion
; LLVM trap followed by LLVM unreachable could become exactly one wasm
; unreachable, but two are emitted currently.
```

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-27 Thread Heejin Ahn via cfe-commits


@@ -1,33 +1,133 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable --no-trap-after-noreturn | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
-declare void @llvm.trap()
-declare void @llvm.debugtrap()
-declare void @abort()
 
-; CHECK-LABEL: f1:
-; CHECK: call abort{{$}}
-; CHECK: unreachable
-define i32 @f1() {
-  call void @abort()
-  unreachable
-}
+; Test that the LLVM trap and debug trap intrinsics are lowered to
+; wasm unreachable.
+
+declare void @llvm.trap() cold noreturn nounwind
+declare void @llvm.debugtrap() nounwind
 
-; CHECK-LABEL: f2:
-; CHECK: unreachable
-define void @f2() {
+define void @trap_ret_void() {
+; CHECK-LABEL: trap_ret_void:
+; CHECK: .functype trap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.trap()
   ret void
 }
 
-; CHECK-LABEL: f3:
-; CHECK: unreachable
-define void @f3() {
+define void @dtrap_ret_void() {
+; CHECK-LABEL: dtrap_ret_void:
+; CHECK: .functype dtrap_ret_void () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:# fallthrough-return
+; CHECK-NEXT:end_function
   call void @llvm.debugtrap()
   ret void
 }
+
+; LLVM trap followed by LLVM unreachable could become exactly one
+; wasm unreachable, but two are emitted currently.
+define void @trap_unreach() {
+; CHECK-LABEL: trap_unreach:
+; CHECK: .functype trap_unreach () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @llvm.trap()
+  unreachable
+}
+
+
+; Test that LLVM unreachable instruction is lowered to wasm unreachable when
+; necessary to fulfill the wasm operand stack requirements.
+
+declare void @ext_func()
+declare i32 @ext_func_i32()
+declare void @ext_never_return() noreturn
+
+; This test emits wasm unreachable to fill in for the missing i32 return value.
+define i32 @missing_ret_unreach() {
+; CHECK-LABEL: missing_ret_unreach:
+; CHECK: .functype missing_ret_unreach () -> (i32)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_func
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @ext_func()
+  unreachable
+}
+
+; This is similar to the above test, but ensures wasm unreachable is emitted
+; even after a noreturn call.
+define i32 @missing_ret_noreturn_unreach() {
+; CHECK-LABEL: missing_ret_noreturn_unreach:
+; CHECK: .functype missing_ret_noreturn_unreach () -> (i32)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_never_return
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @ext_never_return()
+  unreachable
+}
+
+; We could emit no instructions at all for the llvm unreachables in these next
+; three tests, as the signatures match and reaching llvm unreachable is
+; undefined behaviour. But wasm unreachable is emitted for the time being.
+
+define void @void_sig_match_unreach() {
+; CHECK-LABEL: void_sig_match_unreach:
+; CHECK: .functype void_sig_match_unreach () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_func
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @ext_func()
+  unreachable
+}
+
+define i32 @i32_sig_match_unreach() {
+; CHECK-LABEL: i32_sig_match_unreach:
+; CHECK: .functype i32_sig_match_unreach () -> (i32)
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_func_i32
+; CHECK-NEXT:drop
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call i32 @ext_func_i32()
+  unreachable
+}
+
+define void @void_sig_match_noreturn_unreach() {
+; CHECK-LABEL: void_sig_match_noreturn_unreach:
+; CHECK: .functype void_sig_match_noreturn_unreach () -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:call ext_never_return
+; CHECK-NEXT:unreachable
+; CHECK-NEXT:end_function
+  call void @ext_never_return()
+  unreachable
+}
+
+; This function currently doesn't emit unreachable.

aheejin wrote:

That's because... there's no unreachable in the IR in the first place. Why do 
we need this test?

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list

[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-27 Thread Sam Clegg via cfe-commits

sbc100 wrote:

> But `--no-trap-after-noreturn` didn't exist before, so there was no way to 
> specify that from the command line. You _created_ it, originally in this PR, 
> and then the split-off PR in #67051. If this is a bugfix, it sounds like you 
> are fixing a bug of your own making.

I think perhaps the misunderstanding here is that `NoTrapAfterNoreturn` was 
usable/settable by compilers such as rust via the LLVM API, even though 
`--no-trap-after-noreturn` didn't exist in llvm itself?

So adding this option just allows us to test something that wasn't testable, 
but was exposed via the API?  Is that right?

https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-24 Thread Heejin Ahn via cfe-commits

aheejin wrote:

> > Can you point out what are the unsupported options here?
> 
> All of them, they are all options that translate to TargetOptions, and they 
> do nothing for a wasm target triple: ` --trap-unreachable=false 
> --xcoff-traceback-table=true --relax-elf-relocations=false --vec-extabi=true`

I don't think these options are the same case as this PR. These are just 
non-wasm options, so they mean nothing to wasm. Wasm simply doesn't do anything 
with respect to these options and wasm is not _overriding_ them. But with this 
PR, even if a user gives `--no-trap-after-noreturn` in the command line, they 
wouldn't know that their request was silently rejected/overridden.

To say it another way, the difference is, Wasm doesn't understand 
`--xcoff-traceback-table=true` and will do nothing with respect to it. But Wasm 
understands `--no-trap-after-noreturn` and will silently reject it after this 
PR.

> > I'm suggesting a warning only when an incompatible option is explicitly 
> > given in the command line.
> 
> I'm just trying to fix a bug and match how it currently works. If you want to 
> change the behaviour to give more warnings, and especially only when an 
> option is given on the command line, that's a more involved change that 
> belongs in a separate issue.

I have been kind of confused by your characterization of this as "bugfix", 
given that this does not change anything functionality-wise. I agree this PR 
can be an improvement being a failsafe mechanism if someone chooses to override 
the default option or explicitly chooses to override it in the command line. 
But I think, at least in the latter case, the user should be informed that even 
though they requested `--no-trap-after-noreturn`, we will do 
`--no-trap-after-noreturn=0` regardless.

So I'm not sure if I agree that this PR is a bugfix. I consider this as an 
improvement adding a failsafe mechanism.

> > If you grep with report_fatal_error in all target's ***TargetMachine.cpp, 
> > there are many instances of reporting that some options are not supported. 
> > (I'm not necessarily suggesting erroring out though)
> 
> Most of these are hard errors, where there's a real contradiction between two 
> requested features. Not so with TrapUnreachable and NoTrapAfterNoreturn, they 
> are more like hints or suggestions, and can be ignored without breaking 
> anything.

Didn't you provide a counterexample that `--no-trap-after-noreturn` produces 
invalid code? Then don't we have "a real contradiction"? What's your 
distinction criteria for "real contradiction" and "hints or suggestions"?


https://github.com/llvm/llvm-project/pull/65876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Ensure NoTrapAfterNoreturn is false for the wasm backend (PR #65876)

2023-09-24 Thread Matt Harding via cfe-commits

https://github.com/majaha updated 
https://github.com/llvm/llvm-project/pull/65876

>From 7c43c803764bf9e0256d4e3e9f497d2622bb8f69 Mon Sep 17 00:00:00 2001
From: Matt Harding 
Date: Fri, 25 Aug 2023 06:19:14 +0100
Subject: [PATCH 1/8] Add no-trap-after-noreturn flag and wasm tests

Add the command line flag --no-trap-after-noreturn.
Add and improve tests related to WebAssembly's unreachable instruction.
Also fix various typos.
---
 llvm/include/llvm/CodeGen/MachineFunction.h   |   2 +-
 llvm/include/llvm/CodeGen/MachineInstr.h  |   2 +-
 llvm/lib/CodeGen/LLVMTargetMachine.cpp|   7 +
 .../WebAssembly/WebAssemblyCFGStackify.cpp|   2 +-
 llvm/test/CodeGen/WebAssembly/unreachable.ll  | 178 +++---
 5 files changed, 167 insertions(+), 24 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h 
b/llvm/include/llvm/CodeGen/MachineFunction.h
index 6c2da626ea54b4d..8f1651c2958e591 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -266,7 +266,7 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
   // RegInfo - Information about each register in use in the function.
   MachineRegisterInfo *RegInfo;
 
-  // Used to keep track of target-specific per-machine function information for
+  // Used to keep track of target-specific per-machine-function information for
   // the target implementation.
   MachineFunctionInfo *MFInfo;
 
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h 
b/llvm/include/llvm/CodeGen/MachineInstr.h
index 03fb15f77c65cbb..8367f999fcc76d3 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1276,7 +1276,7 @@ class MachineInstr
   /// eraseFromBundle() to erase individual bundled instructions.
   void eraseFromParent();
 
-  /// Unlink 'this' form its basic block and delete it.
+  /// Unlink 'this' from its basic block and delete it.
   ///
   /// If the instruction is part of a bundle, the other instructions in the
   /// bundle remain bundled.
diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp 
b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
index d02ec1db1165d41..aadc3709b85bfb7 100644
--- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
@@ -37,6 +37,11 @@ static cl::opt
 EnableTrapUnreachable("trap-unreachable", cl::Hidden,
   cl::desc("Enable generating trap for unreachable"));
 
+static cl::opt
+EnableNoTrapAfterNoreturn("no-trap-after-noreturn", cl::Hidden,
+  cl::desc("Do not emit a trap instruction for 
'unreachable' IR instructions "
+  "after noreturn calls, even if 
--trap-unreachable is set."));
+
 void LLVMTargetMachine::initAsmInfo() {
   MRI.reset(TheTarget.createMCRegInfo(getTargetTriple().str()));
   assert(MRI && "Unable to create reg info");
@@ -95,6 +100,8 @@ LLVMTargetMachine::LLVMTargetMachine(const Target ,
 
   if (EnableTrapUnreachable)
 this->Options.TrapUnreachable = true;
+  if (EnableNoTrapAfterNoreturn)
+this->Options.NoTrapAfterNoreturn = true;
 }
 
 TargetTransformInfo
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index 131e99c66fa2e5a..d8cbddf74545da6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -667,7 +667,7 @@ void 
WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction ) {
 
   // When there is an unconditional branch right before a catch instruction and
   // it branches to the end of end_try marker, we don't need the branch, 
because
-  // it there is no exception, the control flow transfers to that point anyway.
+  // if there is no exception, the control flow transfers to that point anyway.
   // bb0:
   //   try
   // ...
diff --git a/llvm/test/CodeGen/WebAssembly/unreachable.ll 
b/llvm/test/CodeGen/WebAssembly/unreachable.ll
index ad1c90090ac58bf..1bac30b842e1e05 100644
--- a/llvm/test/CodeGen/WebAssembly/unreachable.ll
+++ b/llvm/test/CodeGen/WebAssembly/unreachable.ll
@@ -1,33 +1,169 @@
-; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 
-verify-machineinstrs | FileCheck %s
-
-; Test that LLVM unreachable instruction and trap intrinsic are lowered to
-; wasm unreachable
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s --check-prefixes 
CHECK,NORMAL
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs | 
FileCheck %s --check-prefixes CHECK,NORMAL
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable | FileCheck %s 
--check-prefixes CHECK,NORMAL
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -verify-machineinstrs 
--trap-unreachable | FileCheck %s --check-prefixes CHECK,NORMAL
+; RUN: llc < %s -verify-machineinstrs --trap-unreachable 
--no-trap-after-noreturn | FileCheck %s