[llvm] r343833 - [WebAssembly] Saturating arithmetic intrinsics

Thomas Lively via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 4 17:45:20 PDT 2018


Author: tlively
Date: Thu Oct  4 17:45:20 2018
New Revision: 343833

URL: http://llvm.org/viewvc/llvm-project?rev=343833&view=rev
Log:
[WebAssembly] Saturating arithmetic intrinsics

Summary: Depends on D52805.

Reviewers: aheejin, dschuff

Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits

Differential Revision: https://reviews.llvm.org/D52813

Modified:
    llvm/trunk/include/llvm/IR/IntrinsicsWebAssembly.td
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyISD.def
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
    llvm/trunk/test/CodeGen/WebAssembly/simd-arith.ll
    llvm/trunk/test/CodeGen/WebAssembly/simd-intrinsics.ll
    llvm/trunk/test/MC/WebAssembly/simd-encodings.s

Modified: llvm/trunk/include/llvm/IR/IntrinsicsWebAssembly.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/IntrinsicsWebAssembly.td?rev=343833&r1=343832&r2=343833&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/IntrinsicsWebAssembly.td (original)
+++ llvm/trunk/include/llvm/IR/IntrinsicsWebAssembly.td Thu Oct  4 17:45:20 2018
@@ -91,6 +91,22 @@ def int_wasm_atomic_notify:
 // SIMD intrinsics
 //===----------------------------------------------------------------------===//
 
+def int_wasm_add_saturate_signed :
+  Intrinsic<[llvm_anyvector_ty],
+            [LLVMMatchType<0>, LLVMMatchType<0>],
+            [IntrNoMem, IntrSpeculatable]>;
+def int_wasm_add_saturate_unsigned :
+  Intrinsic<[llvm_anyvector_ty],
+            [LLVMMatchType<0>, LLVMMatchType<0>],
+            [IntrNoMem, IntrSpeculatable]>;
+def int_wasm_sub_saturate_signed :
+  Intrinsic<[llvm_anyvector_ty],
+            [LLVMMatchType<0>, LLVMMatchType<0>],
+            [IntrNoMem, IntrSpeculatable]>;
+def int_wasm_sub_saturate_unsigned :
+  Intrinsic<[llvm_anyvector_ty],
+            [LLVMMatchType<0>, LLVMMatchType<0>],
+            [IntrNoMem, IntrSpeculatable]>;
 def int_wasm_bitselect :
   Intrinsic<[llvm_anyvector_ty],
             [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISD.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISD.def?rev=343833&r1=343832&r2=343833&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISD.def (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISD.def Thu Oct  4 17:45:20 2018
@@ -25,5 +25,9 @@ HANDLE_NODETYPE(SHUFFLE)
 HANDLE_NODETYPE(ANYTRUE)
 HANDLE_NODETYPE(ALLTRUE)
 HANDLE_NODETYPE(BITSELECT)
+HANDLE_NODETYPE(ADD_SAT_S)
+HANDLE_NODETYPE(ADD_SAT_U)
+HANDLE_NODETYPE(SUB_SAT_S)
+HANDLE_NODETYPE(SUB_SAT_U)
 
 // add memory opcodes starting at ISD::FIRST_TARGET_MEMORY_OPCODE here...

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp?rev=343833&r1=343832&r2=343833&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp Thu Oct  4 17:45:20 2018
@@ -966,6 +966,32 @@ WebAssemblyTargetLowering::LowerINTRINSI
   default:
     return {}; // Don't custom lower most intrinsics.
 
+  case Intrinsic::wasm_add_saturate_signed:
+  case Intrinsic::wasm_add_saturate_unsigned:
+  case Intrinsic::wasm_sub_saturate_signed:
+  case Intrinsic::wasm_sub_saturate_unsigned: {
+    unsigned OpCode;
+    switch (IntNo) {
+    case Intrinsic::wasm_add_saturate_signed:
+      OpCode = WebAssemblyISD::ADD_SAT_S;
+      break;
+    case Intrinsic::wasm_add_saturate_unsigned:
+      OpCode = WebAssemblyISD::ADD_SAT_U;
+      break;
+    case Intrinsic::wasm_sub_saturate_signed:
+      OpCode = WebAssemblyISD::SUB_SAT_S;
+      break;
+    case Intrinsic::wasm_sub_saturate_unsigned:
+      OpCode = WebAssemblyISD::SUB_SAT_U;
+      break;
+    default:
+      llvm_unreachable("unexpected intrinsic id");
+      break;
+    }
+    return DAG.getNode(OpCode, DL, Op.getValueType(), Op.getOperand(1),
+                       Op.getOperand(2));
+  }
+
   case Intrinsic::wasm_bitselect:
     return DAG.getNode(WebAssemblyISD::BITSELECT, DL, Op.getValueType(),
                        Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td?rev=343833&r1=343832&r2=343833&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td Thu Oct  4 17:45:20 2018
@@ -20,11 +20,18 @@ def LaneIdx#SIZE : ImmLeaf<i32, "return
 
 // Custom nodes for custom operations
 def wasm_shuffle_t : SDTypeProfile<1, 18, []>;
+def wasm_saturate_t : SDTypeProfile<1, 2,
+  [SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>]
+>;
 def wasm_bitselect_t : SDTypeProfile<1, 3,
   [SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>]
 >;
 def wasm_reduce_t : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVec<1>]>;
 def wasm_shuffle : SDNode<"WebAssemblyISD::SHUFFLE", wasm_shuffle_t>;
+def wasm_add_sat_s : SDNode<"WebAssemblyISD::ADD_SAT_S", wasm_saturate_t>;
+def wasm_add_sat_u : SDNode<"WebAssemblyISD::ADD_SAT_U", wasm_saturate_t>;
+def wasm_sub_sat_s : SDNode<"WebAssemblyISD::SUB_SAT_S", wasm_saturate_t>;
+def wasm_sub_sat_u : SDNode<"WebAssemblyISD::SUB_SAT_U", wasm_saturate_t>;
 def wasm_bitselect : SDNode<"WebAssemblyISD::BITSELECT", wasm_bitselect_t>;
 def wasm_anytrue : SDNode<"WebAssemblyISD::ANYTRUE", wasm_reduce_t>;
 def wasm_alltrue : SDNode<"WebAssemblyISD::ALLTRUE", wasm_reduce_t>;
@@ -139,6 +146,10 @@ multiclass SIMDBinaryFP<SDNode node, str
   defm "" : SIMDBinary<v4f32, "f32x4", node, name, baseInst>;
   defm "" : SIMDBinary<v2f64, "f64x2", node, name, !add(baseInst, 1)>;
 }
+multiclass SIMDBinarySat<SDNode node, string name, bits<32> baseInst> {
+  defm "" : SIMDBinary<v16i8, "i8x16", node, name, baseInst>;
+  defm "" : SIMDBinary<v8i16, "i16x8", node, name, !add(baseInst, 2)>;
+}
 multiclass SIMDShift<ValueType vec_t, string vec, SDNode node, dag shift_vec,
                      string name, bits<32> simdop> {
   defm _#vec_t : SIMD_I<(outs V128:$dst), (ins V128:$vec, I32:$x),
@@ -366,10 +377,14 @@ defm ADD : SIMDBinaryInt<add, "add", 24>
 defm ADD : SIMDBinaryFP<fadd, "add", 133>;
 defm MUL : SIMDBinaryIntNoI64x2<mul, "mul", 32>;
 defm MUL : SIMDBinaryFP<fmul, "mul", 139>;
+defm ADD_SAT_S : SIMDBinarySat<wasm_add_sat_s, "add_saturate_s", 40>;
+defm ADD_SAT_U : SIMDBinarySat<wasm_add_sat_u, "add_saturate_u", 41>;
 } // isCommutable = 1
 
 defm SUB : SIMDBinaryInt<sub, "sub", 28>;
 defm SUB : SIMDBinaryFP<fsub, "sub", 135>;
+defm SUB_SAT_S : SIMDBinarySat<wasm_sub_sat_s, "sub_saturate_s", 44>;
+defm SUB_SAT_U : SIMDBinarySat<wasm_sub_sat_u, "sub_saturate_u", 45>;
 defm DIV : SIMDBinaryFP<fdiv, "div", 137>;
 
 defm "" : SIMDNegInt<v16i8, "i8x16", splat16, i32, 36>;

Modified: llvm/trunk/test/CodeGen/WebAssembly/simd-arith.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/simd-arith.ll?rev=343833&r1=343832&r2=343833&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/simd-arith.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/simd-arith.ll Thu Oct  4 17:45:20 2018
@@ -1,9 +1,9 @@
 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -wasm-enable-unimplemented-simd -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128,SIMD128-SLOW
 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -wasm-enable-unimplemented-simd -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128,SIMD128-FAST
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128-VM,SIMD128-VM-SLOW
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128-VM,SIMD128-VM-FAST
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128 | FileCheck %s --check-prefixes CHECK,NO-SIMD128,NO-SIMD128-SLOW
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,NO-SIMD128,NO-SIMD128-FAST
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128-VM
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128-VM
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128 | FileCheck %s --check-prefixes CHECK,NO-SIMD128
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,NO-SIMD128
 
 ; Test that basic SIMD128 arithmetic operations assemble as expected.
 

Modified: llvm/trunk/test/CodeGen/WebAssembly/simd-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/simd-intrinsics.ll?rev=343833&r1=343832&r2=343833&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/simd-intrinsics.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/simd-intrinsics.ll Thu Oct  4 17:45:20 2018
@@ -11,6 +11,58 @@ target triple = "wasm32-unknown-unknown"
 ; ==============================================================================
 ; 16 x i8
 ; ==============================================================================
+; CHECK-LABEL: add_sat_s_v16i8:
+; SIMD128-NEXT: .param v128, v128{{$}}
+; SIMD128-NEXT: .result v128{{$}}
+; SIMD128-NEXT: i8x16.add_saturate_s $push[[R:[0-9]+]]=, $0, $1{{$}}
+; SIMD128-NEXT: return $pop[[R]]{{$}}
+declare <16 x i8> @llvm.wasm.add.saturate.signed.v16i8(<16 x i8>, <16 x i8>)
+define <16 x i8> @add_sat_s_v16i8(<16 x i8> %x, <16 x i8> %y) {
+  %a = call <16 x i8> @llvm.wasm.add.saturate.signed.v16i8(
+    <16 x i8> %x, <16 x i8> %y
+  )
+  ret <16 x i8> %a
+}
+
+; CHECK-LABEL: add_sat_u_v16i8:
+; SIMD128-NEXT: .param v128, v128{{$}}
+; SIMD128-NEXT: .result v128{{$}}
+; SIMD128-NEXT: i8x16.add_saturate_u $push[[R:[0-9]+]]=, $0, $1{{$}}
+; SIMD128-NEXT: return $pop[[R]]{{$}}
+declare <16 x i8> @llvm.wasm.add.saturate.unsigned.v16i8(<16 x i8>, <16 x i8>)
+define <16 x i8> @add_sat_u_v16i8(<16 x i8> %x, <16 x i8> %y) {
+  %a = call <16 x i8> @llvm.wasm.add.saturate.unsigned.v16i8(
+    <16 x i8> %x, <16 x i8> %y
+  )
+  ret <16 x i8> %a
+}
+
+; CHECK-LABEL: sub_sat_s_v16i8:
+; SIMD128-NEXT: .param v128, v128{{$}}
+; SIMD128-NEXT: .result v128{{$}}
+; SIMD128-NEXT: i8x16.sub_saturate_s $push[[R:[0-9]+]]=, $0, $1{{$}}
+; SIMD128-NEXT: return $pop[[R]]{{$}}
+declare <16 x i8> @llvm.wasm.sub.saturate.signed.v16i8(<16 x i8>, <16 x i8>)
+define <16 x i8> @sub_sat_s_v16i8(<16 x i8> %x, <16 x i8> %y) {
+  %a = call <16 x i8> @llvm.wasm.sub.saturate.signed.v16i8(
+    <16 x i8> %x, <16 x i8> %y
+  )
+  ret <16 x i8> %a
+}
+
+; CHECK-LABEL: sub_sat_u_v16i8:
+; SIMD128-NEXT: .param v128, v128{{$}}
+; SIMD128-NEXT: .result v128{{$}}
+; SIMD128-NEXT: i8x16.sub_saturate_u $push[[R:[0-9]+]]=, $0, $1{{$}}
+; SIMD128-NEXT: return $pop[[R]]{{$}}
+declare <16 x i8> @llvm.wasm.sub.saturate.unsigned.v16i8(<16 x i8>, <16 x i8>)
+define <16 x i8> @sub_sat_u_v16i8(<16 x i8> %x, <16 x i8> %y) {
+  %a = call <16 x i8> @llvm.wasm.sub.saturate.unsigned.v16i8(
+    <16 x i8> %x, <16 x i8> %y
+  )
+  ret <16 x i8> %a
+}
+
 ; CHECK-LABEL: any_v16i8:
 ; SIMD128-NEXT: .param v128{{$}}
 ; SIMD128-NEXT: .result i32{{$}}
@@ -49,6 +101,58 @@ define <16 x i8> @bitselect_v16i8(<16 x
 ; ==============================================================================
 ; 8 x i16
 ; ==============================================================================
+; CHECK-LABEL: add_sat_s_v8i16:
+; SIMD128-NEXT: .param v128, v128{{$}}
+; SIMD128-NEXT: .result v128{{$}}
+; SIMD128-NEXT: i16x8.add_saturate_s $push[[R:[0-9]+]]=, $0, $1{{$}}
+; SIMD128-NEXT: return $pop[[R]]{{$}}
+declare <8 x i16> @llvm.wasm.add.saturate.signed.v8i16(<8 x i16>, <8 x i16>)
+define <8 x i16> @add_sat_s_v8i16(<8 x i16> %x, <8 x i16> %y) {
+  %a = call <8 x i16> @llvm.wasm.add.saturate.signed.v8i16(
+    <8 x i16> %x, <8 x i16> %y
+  )
+  ret <8 x i16> %a
+}
+
+; CHECK-LABEL: add_sat_u_v8i16:
+; SIMD128-NEXT: .param v128, v128{{$}}
+; SIMD128-NEXT: .result v128{{$}}
+; SIMD128-NEXT: i16x8.add_saturate_u $push[[R:[0-9]+]]=, $0, $1{{$}}
+; SIMD128-NEXT: return $pop[[R]]{{$}}
+declare <8 x i16> @llvm.wasm.add.saturate.unsigned.v8i16(<8 x i16>, <8 x i16>)
+define <8 x i16> @add_sat_u_v8i16(<8 x i16> %x, <8 x i16> %y) {
+  %a = call <8 x i16> @llvm.wasm.add.saturate.unsigned.v8i16(
+    <8 x i16> %x, <8 x i16> %y
+  )
+  ret <8 x i16> %a
+}
+
+; CHECK-LABEL: sub_sat_s_v8i16:
+; SIMD128-NEXT: .param v128, v128{{$}}
+; SIMD128-NEXT: .result v128{{$}}
+; SIMD128-NEXT: i16x8.sub_saturate_s $push[[R:[0-9]+]]=, $0, $1{{$}}
+; SIMD128-NEXT: return $pop[[R]]{{$}}
+declare <8 x i16> @llvm.wasm.sub.saturate.signed.v8i16(<8 x i16>, <8 x i16>)
+define <8 x i16> @sub_sat_s_v8i16(<8 x i16> %x, <8 x i16> %y) {
+  %a = call <8 x i16> @llvm.wasm.sub.saturate.signed.v8i16(
+    <8 x i16> %x, <8 x i16> %y
+  )
+  ret <8 x i16> %a
+}
+
+; CHECK-LABEL: sub_sat_u_v8i16:
+; SIMD128-NEXT: .param v128, v128{{$}}
+; SIMD128-NEXT: .result v128{{$}}
+; SIMD128-NEXT: i16x8.sub_saturate_u $push[[R:[0-9]+]]=, $0, $1{{$}}
+; SIMD128-NEXT: return $pop[[R]]{{$}}
+declare <8 x i16> @llvm.wasm.sub.saturate.unsigned.v8i16(<8 x i16>, <8 x i16>)
+define <8 x i16> @sub_sat_u_v8i16(<8 x i16> %x, <8 x i16> %y) {
+  %a = call <8 x i16> @llvm.wasm.sub.saturate.unsigned.v8i16(
+    <8 x i16> %x, <8 x i16> %y
+  )
+  ret <8 x i16> %a
+}
+
 ; CHECK-LABEL: any_v8i16:
 ; SIMD128-NEXT: .param v128{{$}}
 ; SIMD128-NEXT: .result i32{{$}}

Modified: llvm/trunk/test/MC/WebAssembly/simd-encodings.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/WebAssembly/simd-encodings.s?rev=343833&r1=343832&r2=343833&view=diff
==============================================================================
--- llvm/trunk/test/MC/WebAssembly/simd-encodings.s (original)
+++ llvm/trunk/test/MC/WebAssembly/simd-encodings.s Thu Oct  4 17:45:20 2018
@@ -145,6 +145,30 @@
     # CHECK: i64x2.neg # encoding: [0xfd,0x27]
     i64x2.neg
 
+    # CHECK: i8x16.add_saturate_s # encoding: [0xfd,0x28]
+    i8x16.add_saturate_s
+
+    # CHECK: i8x16.add_saturate_u # encoding: [0xfd,0x29]
+    i8x16.add_saturate_u
+
+    # CHECK: i16x8.add_saturate_s # encoding: [0xfd,0x2a]
+    i16x8.add_saturate_s
+
+    # CHECK: i16x8.add_saturate_u # encoding: [0xfd,0x2b]
+    i16x8.add_saturate_u
+
+    # CHECK: i8x16.sub_saturate_s # encoding: [0xfd,0x2c]
+    i8x16.sub_saturate_s
+
+    # CHECK: i8x16.sub_saturate_u # encoding: [0xfd,0x2d]
+    i8x16.sub_saturate_u
+
+    # CHECK: i16x8.sub_saturate_s # encoding: [0xfd,0x2e]
+    i16x8.sub_saturate_s
+
+    # CHECK: i16x8.sub_saturate_u # encoding: [0xfd,0x2f]
+    i16x8.sub_saturate_u
+
     # CHECK: i8x16.shl # encoding: [0xfd,0x30]
     i8x16.shl
 




More information about the llvm-commits mailing list