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,
// Maybe convert to 0/1 ?
break;
}
-
case OP_XBINOP: {
switch (ins->inst_c0) {
case OP_IADD:
}
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:
}
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];
{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"},
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 */
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)
+
#include "mini.h"
#include "ir-emit.h"
+#include "llvm-jit.h"
#include "mono/utils/bsearch.h"
#include <mono/metadata/abi-details.h>
#include <mono/metadata/reflection-internals.h>
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)
{
// 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"))
}
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;
}
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)