From fe839644e3dbe8a6cfbf4f5bfe79684db75c2792 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Tue, 15 Nov 2022 17:02:37 +0100 Subject: [PATCH] [wasm] Add intrinsics for BitOperations zero count --- .../src/System/Numerics/BitOperations.cs | 4 ++ src/mono/mono/mini/simd-intrinsics.c | 50 ++++++++++++++++--- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs index 088b510453cd54..0ecc5ddf5feaeb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs @@ -181,6 +181,7 @@ internal static int LeadingZeroCount(Int128 value) /// Similar in behavior to the x86 instruction LZCNT. /// /// The value. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static int LeadingZeroCount(uint value) @@ -223,6 +224,7 @@ public static int LeadingZeroCount(uint value) /// Similar in behavior to the x86 instruction LZCNT. /// /// The value. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static int LeadingZeroCount(ulong value) @@ -557,6 +559,7 @@ public static int TrailingZeroCount(int value) /// Similar in behavior to the x86 instruction TZCNT. /// /// The value. + [Intrinsic] [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int TrailingZeroCount(uint value) @@ -610,6 +613,7 @@ public static int TrailingZeroCount(long value) /// Similar in behavior to the x86 instruction TZCNT. /// /// The value. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static int TrailingZeroCount(ulong value) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 7f184fc7ab06f3..c8208b390c0f3f 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -4265,6 +4265,11 @@ emit_sum_vector (MonoCompile *cfg, MonoType *vector_type, MonoTypeEnum element_t return extract_first_element (cfg, vector_class, element_type, vsum->dreg); } +static guint16 bitoperations_methods [] = { + SN_LeadingZeroCount, + SN_TrailingZeroCount, +}; + static SimdIntrinsic wasmbase_methods [] = { {SN_LeadingZeroCount}, {SN_TrailingZeroCount}, @@ -4297,6 +4302,39 @@ static const IntrinGroup supported_wasm_common_intrinsics [] = { { "WasmBase", MONO_CPU_WASM_BASE, wasmbase_methods, sizeof (wasmbase_methods) }, }; +static MonoInst* +emit_wasm_zero_count (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, + MonoClass *klass, int id, MonoTypeEnum arg0_type) +{ + gboolean arg0_i32 = (arg0_type == MONO_TYPE_I4) || (arg0_type == MONO_TYPE_U4); +#if TARGET_SIZEOF_VOID_P == 4 + arg0_i32 = arg0_i32 || (arg0_type == MONO_TYPE_I) || (arg0_type == MONO_TYPE_U); +#endif + int opcode = id == SN_LeadingZeroCount ? (arg0_i32 ? OP_LZCNT32 : OP_LZCNT64) : (arg0_i32 ? OP_CTTZ32 : OP_CTTZ64); + + return emit_simd_ins_for_sig (cfg, klass, opcode, 0, arg0_type, fsig, args); +} + +static MonoInst* +emit_wasm_bitoperations_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +{ + int id = lookup_intrins (bitoperations_methods, sizeof (bitoperations_methods), cmethod); + if (id == -1) { + return NULL; + } + + MonoTypeEnum arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID; + + switch (id) { + case SN_LeadingZeroCount: + case SN_TrailingZeroCount: { + return emit_wasm_zero_count(cfg, fsig, args, cmethod->klass, id, arg0_type); + } + } + + return NULL; +} + static MonoInst* emit_wasm_supported_intrinsics ( MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, @@ -4310,13 +4348,7 @@ emit_wasm_supported_intrinsics ( switch (id) { case SN_LeadingZeroCount: case SN_TrailingZeroCount: { - gboolean arg0_i32 = (arg0_type == MONO_TYPE_I4) || (arg0_type == MONO_TYPE_U4); -#if TARGET_SIZEOF_VOID_P == 4 - arg0_i32 = arg0_i32 || (arg0_type == MONO_TYPE_I) || (arg0_type == MONO_TYPE_U); -#endif - int opcode = id == SN_LeadingZeroCount ? (arg0_i32 ? OP_LZCNT32 : OP_LZCNT64) : (arg0_i32 ? OP_CTTZ32 : OP_CTTZ64); - - return emit_simd_ins_for_sig (cfg, klass, opcode, 0, arg0_type, fsig, args); + return emit_wasm_zero_count(cfg, fsig, args, klass, id, arg0_type); } } } @@ -4478,6 +4510,10 @@ arch_emit_common_intrinsics (const char *class_ns, const char *class_name, MonoC emit_wasm_supported_intrinsics); } + if (!strcmp (class_ns, "System.Numerics") && !strcmp (class_name, "BitOperations")) { + return emit_wasm_bitoperations_intrinsics (cfg, cmethod, fsig, args); + } + return NULL; } #else