From 74dbefe3bd80cb5c060ed6502e74a3bb389c24a7 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sat, 17 Aug 2019 09:16:36 -0400 Subject: [PATCH] Add support for the System.Runtime.Intrinsics.X86.Popcnt intrinsics. Commit migrated from https://github.com/mono/mono/commit/7418248835be6e3a7397694d1e74248dd5ecdd49 --- src/mono/mono/mini/mini-llvm.c | 27 +++++++++++++- src/mono/mono/mini/mini-ops.h | 6 +++ src/mono/mono/mini/simd-intrinsics-netcore.c | 56 ++++++++++++++++++++++++++++ src/mono/mono/mini/simd-methods-netcore.h | 2 + 4 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 0dfd927..6e54170 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -299,6 +299,8 @@ typedef enum { INTRINS_POWF, INTRINS_EXPECT_I8, INTRINS_EXPECT_I1, + INTRINS_CTPOP_I32, + INTRINS_CTPOP_I64, #if defined(TARGET_AMD64) || defined(TARGET_X86) INTRINS_SSE_PMOVMSKB, INTRINS_SSE_PSRLI_W, @@ -7136,7 +7138,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) // Maybe convert to 0/1 ? break; } - case OP_XBINOP: { switch (ins->inst_c0) { case OP_IADD: @@ -7171,6 +7172,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) } break; } + case OP_POPCNT32: + values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_CTPOP_I32), &lhs, 1, ""); + break; + case OP_POPCNT64: + values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, INTRINS_CTPOP_I64), &lhs, 1, ""); + break; #endif /* SIMD */ case OP_DUMMY_USE: @@ -8312,6 +8319,16 @@ AddFunc (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeR } static inline void +AddFunc1 (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef param_type1) +{ + LLVMTypeRef param_types [4]; + + param_types [0] = param_type1; + + AddFunc (module, name, ret_type, param_types, 1); +} + +static inline void AddFunc2 (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef param_type1, LLVMTypeRef param_type2) { LLVMTypeRef param_types [4]; @@ -8354,6 +8371,8 @@ static IntrinsicDesc intrinsics[] = { {INTRINS_POWF, "llvm.pow.f32"}, {INTRINS_EXPECT_I8, "llvm.expect.i8"}, {INTRINS_EXPECT_I1, "llvm.expect.i1"}, + {INTRINS_CTPOP_I32, "llvm.ctpop.i32"}, + {INTRINS_CTPOP_I64, "llvm.ctpop.i64"}, #if defined(TARGET_AMD64) || defined(TARGET_X86) {INTRINS_SSE_PMOVMSKB, "llvm.x86.sse2.pmovmskb.128"}, {INTRINS_SSE_PSRLI_W, "llvm.x86.sse2.psrli.w"}, @@ -8511,6 +8530,12 @@ add_intrinsic (LLVMModuleRef module, int id) case INTRINS_EXPECT_I1: AddFunc2 (module, name, LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type ()); break; + case INTRINS_CTPOP_I32: + AddFunc1 (module, name, LLVMInt32Type (), LLVMInt32Type ()); + break; + case INTRINS_CTPOP_I64: + AddFunc1 (module, name, LLVMInt64Type (), LLVMInt64Type ()); + break; #if defined(TARGET_AMD64) || defined(TARGET_X86) case INTRINS_SSE_PMOVMSKB: /* pmovmskb */ diff --git a/src/mono/mono/mini/mini-ops.h b/src/mono/mono/mini/mini-ops.h index 5992595..deec494 100644 --- a/src/mono/mono/mini/mini-ops.h +++ b/src/mono/mono/mini/mini-ops.h @@ -1362,3 +1362,9 @@ MINI_OP(OP_XCOMPARE, "xcompare", XREG, XREG, XREG) MINI_OP(OP_XCOMPARE_FP, "xcompare_fp", XREG, XREG, XREG) /* Binary op, inst_c0 contains the operation */ MINI_OP(OP_XBINOP, "xbinop", XREG, XREG, XREG) + +MINI_OP(OP_LZCNT32, "lzcnt32", IREG, IREG, NONE) +MINI_OP(OP_LZCNT64, "lzcnt64", LREG, LREG, NONE) +MINI_OP(OP_POPCNT32, "popcnt32", IREG, IREG, NONE) +MINI_OP(OP_POPCNT64, "popcnt64", LREG, LREG, NONE) + diff --git a/src/mono/mono/mini/simd-intrinsics-netcore.c b/src/mono/mono/mini/simd-intrinsics-netcore.c index 269eb02..565500a 100644 --- a/src/mono/mono/mini/simd-intrinsics-netcore.c +++ b/src/mono/mono/mini/simd-intrinsics-netcore.c @@ -13,6 +13,7 @@ #include "mini.h" #include "ir-emit.h" +#include "llvm-jit.h" #include "mono/utils/bsearch.h" #include #include @@ -393,6 +394,54 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig return NULL; } +#ifdef TARGET_AMD64 + +static guint16 popcnt_methods [] = { + SN_PopCount, + SN_get_IsSupported +}; + +static MonoInst* +emit_x86_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +{ + const char *class_name; + const char *class_ns; + MonoInst *ins; + int id; + gboolean supported, is_64bit; + MonoClass *klass = cmethod->klass; + + class_ns = m_class_get_name_space (klass); + class_name = m_class_get_name (klass); + if (!strcmp (class_name, "Popcnt") || (!strcmp (class_name, "X64") && cmethod->klass->nested_in && !strcmp (m_class_get_name (cmethod->klass->nested_in), "Popcnt"))) { + id = lookup_intrins (popcnt_methods, sizeof (popcnt_methods), cmethod); + if (id == -1) + return NULL; + + supported = (mono_llvm_get_cpu_features () & MONO_CPU_X86_POPCNT) != 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_PopCount: + if (!supported) + return NULL; + MONO_INST_NEW (cfg, ins, is_64bit ? OP_POPCNT64 : OP_POPCNT32); + ins->dreg = alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + default: + return NULL; + } + } + return NULL; +} +#endif + MonoInst* mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { @@ -407,6 +456,7 @@ mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign // FIXME: if (cfg->compile_aot) return NULL; + class_ns = m_class_get_name_space (cmethod->klass); class_name = m_class_get_name (cmethod->klass); if (!strcmp (class_ns, "System.Numerics") && !strcmp (class_name, "Vector")) @@ -418,6 +468,12 @@ mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } return ins; } +#ifdef TARGET_AMD64 + if (cmethod->klass->nested_in) + class_ns = m_class_get_name_space (cmethod->klass->nested_in), class_name, cmethod->klass->nested_in; + if (!strcmp (class_ns, "System.Runtime.Intrinsics.X86")) + return emit_x86_intrinsics (cfg ,cmethod, fsig, args); +#endif return NULL; } diff --git a/src/mono/mono/mini/simd-methods-netcore.h b/src/mono/mono/mini/simd-methods-netcore.h index f1a98a9..a6a675c 100644 --- a/src/mono/mono/mini/simd-methods-netcore.h +++ b/src/mono/mono/mini/simd-methods-netcore.h @@ -4,8 +4,10 @@ SIMD_METHOD("GreaterThan", SN_GreaterThan) SIMD_METHOD("LessThan", SN_LessThan) SIMD_METHOD("Min", SN_Min) SIMD_METHOD("Max", SN_Max) +SIMD_METHOD("PopCount", SN_PopCount) SIMD_METHOD("get_Count", SN_get_Count) SIMD_METHOD("get_IsHardwareAccelerated", SN_get_IsHardwareAccelerated) +SIMD_METHOD("get_IsSupported", SN_get_IsSupported) SIMD_METHOD("get_AllOnes", SN_get_AllOnes) SIMD_METHOD("get_Item", SN_get_Item) SIMD_METHOD("get_One", SN_get_One) -- 2.7.4