From a07019a275cd0deb59433ac59e4faa85d0722822 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 31 Oct 2019 16:49:47 -0700 Subject: [PATCH] [WebAssembly] SIMD integer min and max instructions Summary: Introduces a clang builtins and LLVM intrinsics representing integer min/max instructions. These instructions have not been merged to the SIMD spec proposal yet, so they are currently opt-in only via builtins and not produced by general pattern matching. If these instructions are accepted into the spec proposal the builtins and intrinsics will be replaced with normal pattern matching. Defined in https://github.com/WebAssembly/simd/pull/27. Reviewers: aheejin Reviewed By: aheejin Subscribers: dschuff, sbc100, jgravelle-google, hiraditya, sunfish, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D69696 --- clang/include/clang/Basic/BuiltinsWebAssembly.def | 15 +++ clang/lib/CodeGen/CGBuiltin.cpp | 42 ++++++++ clang/test/CodeGen/builtins-wasm.c | 84 +++++++++++++++ llvm/include/llvm/IR/IntrinsicsWebAssembly.td | 20 ++++ .../lib/Target/WebAssembly/WebAssemblyInstrSIMD.td | 9 ++ llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll | 120 +++++++++++++++++++++ llvm/test/MC/WebAssembly/simd-encodings.s | 36 +++++++ 7 files changed, 326 insertions(+) diff --git a/clang/include/clang/Basic/BuiltinsWebAssembly.def b/clang/include/clang/Basic/BuiltinsWebAssembly.def index 7fed9d2..2233c20 100644 --- a/clang/include/clang/Basic/BuiltinsWebAssembly.def +++ b/clang/include/clang/Basic/BuiltinsWebAssembly.def @@ -98,6 +98,21 @@ TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i8x16, "V16cV16cV16c", "nc", "simd1 TARGET_BUILTIN(__builtin_wasm_sub_saturate_s_i16x8, "V8sV8sV8s", "nc", "simd128") TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i16x8, "V8sV8sV8s", "nc", "simd128") +// TODO: Remove builtins and rely on codegen patterns once these are officially +// merged to the spec proposal +TARGET_BUILTIN(__builtin_wasm_min_s_i8x16, "V16cV16cV16c", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_min_u_i8x16, "V16cV16cV16c", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_max_s_i8x16, "V16cV16cV16c", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_max_u_i8x16, "V16cV16cV16c", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_min_s_i16x8, "V8sV8sV8s", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_min_u_i16x8, "V8sV8sV8s", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_max_s_i16x8, "V8sV8sV8s", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_max_u_i16x8, "V8sV8sV8s", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_min_s_i32x4, "V4iV4iV4i", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_min_u_i32x4, "V4iV4iV4i", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_max_s_i32x4, "V4iV4iV4i", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_max_u_i32x4, "V4iV4iV4i", "nc", "simd128") + TARGET_BUILTIN(__builtin_wasm_bitselect, "V4iV4iV4iV4i", "nc", "simd128") TARGET_BUILTIN(__builtin_wasm_any_true_i8x16, "iV16c", "nc", "simd128") diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 648837a..fef5cab 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -14318,6 +14318,48 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, ConvertType(E->getType())); return Builder.CreateCall(Callee, {V1, V2, C}); } + case WebAssembly::BI__builtin_wasm_min_s_i8x16: + case WebAssembly::BI__builtin_wasm_min_u_i8x16: + case WebAssembly::BI__builtin_wasm_max_s_i8x16: + case WebAssembly::BI__builtin_wasm_max_u_i8x16: + case WebAssembly::BI__builtin_wasm_min_s_i16x8: + case WebAssembly::BI__builtin_wasm_min_u_i16x8: + case WebAssembly::BI__builtin_wasm_max_s_i16x8: + case WebAssembly::BI__builtin_wasm_max_u_i16x8: + case WebAssembly::BI__builtin_wasm_min_s_i32x4: + case WebAssembly::BI__builtin_wasm_min_u_i32x4: + case WebAssembly::BI__builtin_wasm_max_s_i32x4: + case WebAssembly::BI__builtin_wasm_max_u_i32x4: { + unsigned IntNo; + switch (BuiltinID) { + case WebAssembly::BI__builtin_wasm_min_s_i8x16: + case WebAssembly::BI__builtin_wasm_min_s_i16x8: + case WebAssembly::BI__builtin_wasm_min_s_i32x4: + IntNo = Intrinsic::wasm_min_signed; + break; + case WebAssembly::BI__builtin_wasm_min_u_i8x16: + case WebAssembly::BI__builtin_wasm_min_u_i16x8: + case WebAssembly::BI__builtin_wasm_min_u_i32x4: + IntNo = Intrinsic::wasm_min_unsigned; + break; + case WebAssembly::BI__builtin_wasm_max_s_i8x16: + case WebAssembly::BI__builtin_wasm_max_s_i16x8: + case WebAssembly::BI__builtin_wasm_max_s_i32x4: + IntNo = Intrinsic::wasm_max_signed; + break; + case WebAssembly::BI__builtin_wasm_max_u_i8x16: + case WebAssembly::BI__builtin_wasm_max_u_i16x8: + case WebAssembly::BI__builtin_wasm_max_u_i32x4: + IntNo = Intrinsic::wasm_max_unsigned; + break; + default: + llvm_unreachable("unexpected builtin ID"); + } + Value *LHS = EmitScalarExpr(E->getArg(0)); + Value *RHS = EmitScalarExpr(E->getArg(1)); + Function *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType())); + return Builder.CreateCall(Callee, {LHS, RHS}); + } case WebAssembly::BI__builtin_wasm_any_true_i8x16: case WebAssembly::BI__builtin_wasm_any_true_i16x8: case WebAssembly::BI__builtin_wasm_any_true_i32x4: diff --git a/clang/test/CodeGen/builtins-wasm.c b/clang/test/CodeGen/builtins-wasm.c index 71c9e66..c07e73f 100644 --- a/clang/test/CodeGen/builtins-wasm.c +++ b/clang/test/CodeGen/builtins-wasm.c @@ -352,6 +352,90 @@ i16x8 sub_saturate_u_i16x8(i16x8 x, i16x8 y) { // WEBASSEMBLY-NEXT: ret } +i8x16 min_s_i8x16(i8x16 x, i8x16 y) { + return __builtin_wasm_min_s_i8x16(x, y); + // WEBASSEMBLY: call <16 x i8> @llvm.wasm.min.signed.v16i8( + // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y) + // WEBASSEMBLY-NEXT: ret +} + +i8x16 min_u_i8x16(i8x16 x, i8x16 y) { + return __builtin_wasm_min_u_i8x16(x, y); + // WEBASSEMBLY: call <16 x i8> @llvm.wasm.min.unsigned.v16i8( + // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y) + // WEBASSEMBLY-NEXT: ret +} + +i8x16 max_s_i8x16(i8x16 x, i8x16 y) { + return __builtin_wasm_max_s_i8x16(x, y); + // WEBASSEMBLY: call <16 x i8> @llvm.wasm.max.signed.v16i8( + // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y) + // WEBASSEMBLY-NEXT: ret +} + +i8x16 max_u_i8x16(i8x16 x, i8x16 y) { + return __builtin_wasm_max_u_i8x16(x, y); + // WEBASSEMBLY: call <16 x i8> @llvm.wasm.max.unsigned.v16i8( + // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y) + // WEBASSEMBLY-NEXT: ret +} + +i16x8 min_s_i16x8(i16x8 x, i16x8 y) { + return __builtin_wasm_min_s_i16x8(x, y); + // WEBASSEMBLY: call <8 x i16> @llvm.wasm.min.signed.v8i16( + // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y) + // WEBASSEMBLY-NEXT: ret +} + +i16x8 min_u_i16x8(i16x8 x, i16x8 y) { + return __builtin_wasm_min_u_i16x8(x, y); + // WEBASSEMBLY: call <8 x i16> @llvm.wasm.min.unsigned.v8i16( + // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y) + // WEBASSEMBLY-NEXT: ret +} + +i16x8 max_s_i16x8(i16x8 x, i16x8 y) { + return __builtin_wasm_max_s_i16x8(x, y); + // WEBASSEMBLY: call <8 x i16> @llvm.wasm.max.signed.v8i16( + // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y) + // WEBASSEMBLY-NEXT: ret +} + +i16x8 max_u_i16x8(i16x8 x, i16x8 y) { + return __builtin_wasm_max_u_i16x8(x, y); + // WEBASSEMBLY: call <8 x i16> @llvm.wasm.max.unsigned.v8i16( + // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y) + // WEBASSEMBLY-NEXT: ret +} + +i32x4 min_s_i32x4(i32x4 x, i32x4 y) { + return __builtin_wasm_min_s_i32x4(x, y); + // WEBASSEMBLY: call <4 x i32> @llvm.wasm.min.signed.v4i32( + // WEBASSEMBLY-SAME: <4 x i32> %x, <4 x i32> %y) + // WEBASSEMBLY-NEXT: ret +} + +i32x4 min_u_i32x4(i32x4 x, i32x4 y) { + return __builtin_wasm_min_u_i32x4(x, y); + // WEBASSEMBLY: call <4 x i32> @llvm.wasm.min.unsigned.v4i32( + // WEBASSEMBLY-SAME: <4 x i32> %x, <4 x i32> %y) + // WEBASSEMBLY-NEXT: ret +} + +i32x4 max_s_i32x4(i32x4 x, i32x4 y) { + return __builtin_wasm_max_s_i32x4(x, y); + // WEBASSEMBLY: call <4 x i32> @llvm.wasm.max.signed.v4i32( + // WEBASSEMBLY-SAME: <4 x i32> %x, <4 x i32> %y) + // WEBASSEMBLY-NEXT: ret +} + +i32x4 max_u_i32x4(i32x4 x, i32x4 y) { + return __builtin_wasm_max_u_i32x4(x, y); + // WEBASSEMBLY: call <4 x i32> @llvm.wasm.max.unsigned.v4i32( + // WEBASSEMBLY-SAME: <4 x i32> %x, <4 x i32> %y) + // WEBASSEMBLY-NEXT: ret +} + i32x4 bitselect(i32x4 x, i32x4 y, i32x4 c) { return __builtin_wasm_bitselect(x, y, c); // WEBASSEMBLY: call <4 x i32> @llvm.wasm.bitselect.v4i32( diff --git a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td index 810979b..b99abb4 100644 --- a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td +++ b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td @@ -112,6 +112,26 @@ def int_wasm_sub_saturate_unsigned : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; + +// TODO: Remove intrinsics and rely on codegen patterns once these are +// officially merged to the spec proposal +def int_wasm_min_signed : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; +def int_wasm_min_unsigned : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; +def int_wasm_max_signed : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; +def int_wasm_max_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>], diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td index 751c565..2a423ac 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -727,8 +727,17 @@ defm SUB_SAT_U : SIMDBinaryIntSmall; // Integer multiplication: mul +let isCommutable = 1 in defm MUL : SIMDBinaryIntNoI64x2; +// Integer min_s / min_u / max_s / max_u +let isCommutable = 1 in { +defm MIN_S : SIMDBinaryIntNoI64x2; +defm MIN_U : SIMDBinaryIntNoI64x2; +defm MAX_S : SIMDBinaryIntNoI64x2; +defm MAX_U : SIMDBinaryIntNoI64x2; +} // isCommutable = 1 + //===----------------------------------------------------------------------===// // Floating-point unary arithmetic //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll index 6a901ee..d404e0b 100644 --- a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll +++ b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll @@ -65,6 +65,46 @@ define <16 x i8> @sub_sat_u_v16i8(<16 x i8> %x, <16 x i8> %y) { ret <16 x i8> %a } +; CHECK-LABEL: min_s_v16i8: +; SIMD128-NEXT: .functype min_s_v16i8 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i8x16.min_s $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <16 x i8> @llvm.wasm.min.signed.v16i8(<16 x i8>, <16 x i8>) +define <16 x i8> @min_s_v16i8(<16 x i8> %x, <16 x i8> %y) { + %a = call <16 x i8> @llvm.wasm.min.signed.v16i8(<16 x i8> %x, <16 x i8> %y) + ret <16 x i8> %a +} + +; CHECK-LABEL: min_u_v16i8: +; SIMD128-NEXT: .functype min_u_v16i8 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i8x16.min_u $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <16 x i8> @llvm.wasm.min.unsigned.v16i8(<16 x i8>, <16 x i8>) +define <16 x i8> @min_u_v16i8(<16 x i8> %x, <16 x i8> %y) { + %a = call <16 x i8> @llvm.wasm.min.unsigned.v16i8(<16 x i8> %x, <16 x i8> %y) + ret <16 x i8> %a +} + +; CHECK-LABEL: max_s_v16i8: +; SIMD128-NEXT: .functype max_s_v16i8 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i8x16.max_s $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <16 x i8> @llvm.wasm.max.signed.v16i8(<16 x i8>, <16 x i8>) +define <16 x i8> @max_s_v16i8(<16 x i8> %x, <16 x i8> %y) { + %a = call <16 x i8> @llvm.wasm.max.signed.v16i8(<16 x i8> %x, <16 x i8> %y) + ret <16 x i8> %a +} + +; CHECK-LABEL: max_u_v16i8: +; SIMD128-NEXT: .functype max_u_v16i8 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i8x16.max_u $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <16 x i8> @llvm.wasm.max.unsigned.v16i8(<16 x i8>, <16 x i8>) +define <16 x i8> @max_u_v16i8(<16 x i8> %x, <16 x i8> %y) { + %a = call <16 x i8> @llvm.wasm.max.unsigned.v16i8(<16 x i8> %x, <16 x i8> %y) + ret <16 x i8> %a +} + ; CHECK-LABEL: any_v16i8: ; SIMD128-NEXT: .functype any_v16i8 (v128) -> (i32){{$}} ; SIMD128-NEXT: i8x16.any_true $push[[R:[0-9]+]]=, $0{{$}} @@ -168,6 +208,46 @@ define <8 x i16> @sub_sat_u_v8i16(<8 x i16> %x, <8 x i16> %y) { ret <8 x i16> %a } +; CHECK-LABEL: min_s_v8i16: +; SIMD128-NEXT: .functype min_s_v8i16 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i16x8.min_s $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <8 x i16> @llvm.wasm.min.signed.v8i16(<8 x i16>, <8 x i16>) +define <8 x i16> @min_s_v8i16(<8 x i16> %x, <8 x i16> %y) { + %a = call <8 x i16> @llvm.wasm.min.signed.v8i16(<8 x i16> %x, <8 x i16> %y) + ret <8 x i16> %a +} + +; CHECK-LABEL: min_u_v8i16: +; SIMD128-NEXT: .functype min_u_v8i16 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i16x8.min_u $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <8 x i16> @llvm.wasm.min.unsigned.v8i16(<8 x i16>, <8 x i16>) +define <8 x i16> @min_u_v8i16(<8 x i16> %x, <8 x i16> %y) { + %a = call <8 x i16> @llvm.wasm.min.unsigned.v8i16(<8 x i16> %x, <8 x i16> %y) + ret <8 x i16> %a +} + +; CHECK-LABEL: max_s_v8i16: +; SIMD128-NEXT: .functype max_s_v8i16 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i16x8.max_s $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <8 x i16> @llvm.wasm.max.signed.v8i16(<8 x i16>, <8 x i16>) +define <8 x i16> @max_s_v8i16(<8 x i16> %x, <8 x i16> %y) { + %a = call <8 x i16> @llvm.wasm.max.signed.v8i16(<8 x i16> %x, <8 x i16> %y) + ret <8 x i16> %a +} + +; CHECK-LABEL: max_u_v8i16: +; SIMD128-NEXT: .functype max_u_v8i16 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i16x8.max_u $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <8 x i16> @llvm.wasm.max.unsigned.v8i16(<8 x i16>, <8 x i16>) +define <8 x i16> @max_u_v8i16(<8 x i16> %x, <8 x i16> %y) { + %a = call <8 x i16> @llvm.wasm.max.unsigned.v8i16(<8 x i16> %x, <8 x i16> %y) + ret <8 x i16> %a +} + ; CHECK-LABEL: any_v8i16: ; SIMD128-NEXT: .functype any_v8i16 (v128) -> (i32){{$}} ; SIMD128-NEXT: i16x8.any_true $push[[R:[0-9]+]]=, $0{{$}} @@ -267,6 +347,46 @@ define <8 x i16> @widen_high_unsigned_v8i16(<16 x i8> %v) { ; ============================================================================== ; 4 x i32 ; ============================================================================== +; CHECK-LABEL: min_s_v4i32: +; SIMD128-NEXT: .functype min_s_v4i32 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i32x4.min_s $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <4 x i32> @llvm.wasm.min.signed.v4i32(<4 x i32>, <4 x i32>) +define <4 x i32> @min_s_v4i32(<4 x i32> %x, <4 x i32> %y) { + %a = call <4 x i32> @llvm.wasm.min.signed.v4i32(<4 x i32> %x, <4 x i32> %y) + ret <4 x i32> %a +} + +; CHECK-LABEL: min_u_v4i32: +; SIMD128-NEXT: .functype min_u_v4i32 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i32x4.min_u $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <4 x i32> @llvm.wasm.min.unsigned.v4i32(<4 x i32>, <4 x i32>) +define <4 x i32> @min_u_v4i32(<4 x i32> %x, <4 x i32> %y) { + %a = call <4 x i32> @llvm.wasm.min.unsigned.v4i32(<4 x i32> %x, <4 x i32> %y) + ret <4 x i32> %a +} + +; CHECK-LABEL: max_s_v4i32: +; SIMD128-NEXT: .functype max_s_v4i32 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i32x4.max_s $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <4 x i32> @llvm.wasm.max.signed.v4i32(<4 x i32>, <4 x i32>) +define <4 x i32> @max_s_v4i32(<4 x i32> %x, <4 x i32> %y) { + %a = call <4 x i32> @llvm.wasm.max.signed.v4i32(<4 x i32> %x, <4 x i32> %y) + ret <4 x i32> %a +} + +; CHECK-LABEL: max_u_v4i32: +; SIMD128-NEXT: .functype max_u_v4i32 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i32x4.max_u $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <4 x i32> @llvm.wasm.max.unsigned.v4i32(<4 x i32>, <4 x i32>) +define <4 x i32> @max_u_v4i32(<4 x i32> %x, <4 x i32> %y) { + %a = call <4 x i32> @llvm.wasm.max.unsigned.v4i32(<4 x i32> %x, <4 x i32> %y) + ret <4 x i32> %a +} + ; CHECK-LABEL: any_v4i32: ; SIMD128-NEXT: .functype any_v4i32 (v128) -> (i32){{$}} ; SIMD128-NEXT: i32x4.any_true $push[[R:[0-9]+]]=, $0{{$}} diff --git a/llvm/test/MC/WebAssembly/simd-encodings.s b/llvm/test/MC/WebAssembly/simd-encodings.s index f321094..adddcf5 100644 --- a/llvm/test/MC/WebAssembly/simd-encodings.s +++ b/llvm/test/MC/WebAssembly/simd-encodings.s @@ -283,6 +283,18 @@ main: # CHECK: i8x16.mul # encoding: [0xfd,0x5d] i8x16.mul + # CHECK: i8x16.min_s # encoding: [0xfd,0x5e] + i8x16.min_s + + # CHECK: i8x16.min_u # encoding: [0xfd,0x5f] + i8x16.min_u + + # CHECK: i8x16.max_s # encoding: [0xfd,0x60] + i8x16.max_s + + # CHECK: i8x16.max_u # encoding: [0xfd,0x61] + i8x16.max_u + # CHECK: i16x8.neg # encoding: [0xfd,0x62] i16x8.neg @@ -322,6 +334,18 @@ main: # CHECK: i16x8.mul # encoding: [0xfd,0x6e] i16x8.mul + # CHECK: i16x8.min_s # encoding: [0xfd,0x6f] + i16x8.min_s + + # CHECK: i16x8.min_u # encoding: [0xfd,0x70] + i16x8.min_u + + # CHECK: i16x8.max_s # encoding: [0xfd,0x71] + i16x8.max_s + + # CHECK: i16x8.max_u # encoding: [0xfd,0x72] + i16x8.max_u + # CHECK: i32x4.neg # encoding: [0xfd,0x73] i32x4.neg @@ -349,6 +373,18 @@ main: # CHECK: i32x4.mul # encoding: [0xfd,0x7f] i32x4.mul + # CHECK: i32x4.min_s # encoding: [0xfd,0x80,0x01] + i32x4.min_s + + # CHECK: i32x4.min_u # encoding: [0xfd,0x81,0x01] + i32x4.min_u + + # CHECK: i32x4.max_s # encoding: [0xfd,0x82,0x01] + i32x4.max_s + + # CHECK: i32x4.max_u # encoding: [0xfd,0x83,0x01] + i32x4.max_u + # CHECK: i64x2.neg # encoding: [0xfd,0x84,0x01] i64x2.neg -- 2.7.4