From: Egor Bogatov Date: Mon, 26 Aug 2019 18:08:53 +0000 (+0300) Subject: Implement Lzcnt hw intrinsics X-Git-Tag: submit/tizen/20210909.063632~10331^2~5^2~687^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7635724e437530421bfd4bf71566b9406dca3d64;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Implement Lzcnt hw intrinsics Commit migrated from https://github.com/mono/mono/commit/044d1519bdf40f37ec06128dd383c21157dc3c0e --- diff --git a/src/mono/mono/mini/llvm-jit.cpp b/src/mono/mono/mini/llvm-jit.cpp index 8ea0050..4672962 100644 --- a/src/mono/mono/mini/llvm-jit.cpp +++ b/src/mono/mono/mini/llvm-jit.cpp @@ -465,6 +465,8 @@ mono_llvm_get_cpu_features (void) if (llvm::sys::getHostCPUFeatures(HostFeatures)) { if (HostFeatures ["popcnt"]) f |= MONO_CPU_X86_POPCNT; + if (HostFeatures ["lzcnt"]) + f |= MONO_CPU_X86_LZCNT; if (HostFeatures ["avx"]) f |= MONO_CPU_X86_AVX; if (HostFeatures ["bmi"]) diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index cdbb13a..b672119 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -303,6 +303,8 @@ typedef enum { INTRINS_EXPECT_I1, INTRINS_CTPOP_I32, INTRINS_CTPOP_I64, + INTRINS_CTLZ_I32, + INTRINS_CTLZ_I64, INTRINS_CTTZ_I32, INTRINS_CTTZ_I64, INTRINS_PEXT_I32, @@ -7216,6 +7218,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) case OP_POPCNT64: values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_CTPOP_I64), &lhs, 1, ""); break; + case OP_LZCNT32: + values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_CTLZ_I32), &lhs, 1, ""); + break; + case OP_LZCNT64: + values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_CTLZ_I64), &lhs, 1, ""); + break; case OP_CTTZ32: case OP_CTTZ64: { LLVMValueRef args [2]; @@ -8462,6 +8470,8 @@ static IntrinsicDesc intrinsics[] = { {INTRINS_EXPECT_I1, "llvm.expect.i1"}, {INTRINS_CTPOP_I32, "llvm.ctpop.i32"}, {INTRINS_CTPOP_I64, "llvm.ctpop.i64"}, + {INTRINS_CTLZ_I32, "llvm.ctlz.i32"}, + {INTRINS_CTLZ_I64, "llvm.ctlz.i64"}, {INTRINS_CTTZ_I32, "llvm.cttz.i32"}, {INTRINS_CTTZ_I64, "llvm.cttz.i64"}, {INTRINS_PEXT_I32, "llvm.x86.bmi.pext.32"}, @@ -8625,9 +8635,11 @@ add_intrinsic (LLVMModuleRef module, int id) case INTRINS_EXPECT_I1: AddFunc2 (module, name, LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type ()); break; + case INTRINS_CTLZ_I32: case INTRINS_CTPOP_I32: AddFunc1 (module, name, LLVMInt32Type (), LLVMInt32Type ()); break; + case INTRINS_CTLZ_I64: case INTRINS_CTPOP_I64: AddFunc1 (module, name, LLVMInt64Type (), LLVMInt64Type ()); break; diff --git a/src/mono/mono/mini/simd-intrinsics-netcore.c b/src/mono/mono/mini/simd-intrinsics-netcore.c index abfe8e2..796406a 100644 --- a/src/mono/mono/mini/simd-intrinsics-netcore.c +++ b/src/mono/mono/mini/simd-intrinsics-netcore.c @@ -437,6 +437,11 @@ static guint16 popcnt_methods [] = { SN_get_IsSupported }; +static guint16 lzcnt_methods [] = { + SN_LeadingZeroCount, + SN_get_IsSupported +}; + static guint16 bmi1_methods [] = { SN_TrailingZeroCount, SN_get_IsSupported, @@ -485,6 +490,31 @@ emit_x86_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature return NULL; } } + if (!strcmp (class_name, "Lzcnt") || (!strcmp (class_name, "X64") && cmethod->klass->nested_in && !strcmp (m_class_get_name (cmethod->klass->nested_in), "Lzcnt"))) { + id = lookup_intrins (lzcnt_methods, sizeof (lzcnt_methods), cmethod); + if (id == -1) + return NULL; + + supported = (get_cpu_features () & MONO_CPU_X86_LZCNT) != 0; + is_64bit = !strcmp (class_name, "X64"); + + switch (id) { + case SN_get_IsSupported: + EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); + ins->type = STACK_I4; + return ins; + case SN_LeadingZeroCount: + if (!supported) + return NULL; + MONO_INST_NEW (cfg, ins, is_64bit ? OP_LZCNT64 : OP_LZCNT32); + ins->dreg = alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + default: + return NULL; + } + } if (!strcmp (class_name, "Bmi1") || (!strcmp (class_name, "X64") && cmethod->klass->nested_in && !strcmp (m_class_get_name (cmethod->klass->nested_in), "Bmi1"))) { // We only support the subset used by corelib if (m_class_get_image (cfg->method->klass) != mono_get_corlib ()) diff --git a/src/mono/mono/mini/simd-methods-netcore.h b/src/mono/mono/mini/simd-methods-netcore.h index a4af28d..e15e237 100644 --- a/src/mono/mono/mini/simd-methods-netcore.h +++ b/src/mono/mono/mini/simd-methods-netcore.h @@ -5,6 +5,7 @@ METHOD(LessThan) METHOD(Min) METHOD(Max) METHOD(PopCount) +METHOD(LeadingZeroCount) METHOD(get_Count) METHOD(get_IsHardwareAccelerated) METHOD(get_IsSupported)