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"])
INTRINS_EXPECT_I1,
INTRINS_CTPOP_I32,
INTRINS_CTPOP_I64,
+ INTRINS_CTLZ_I32,
+ INTRINS_CTLZ_I64,
INTRINS_CTTZ_I32,
INTRINS_CTTZ_I64,
INTRINS_PEXT_I32,
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];
{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"},
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;
SN_get_IsSupported
};
+static guint16 lzcnt_methods [] = {
+ SN_LeadingZeroCount,
+ SN_get_IsSupported
+};
+
static guint16 bmi1_methods [] = {
SN_TrailingZeroCount,
SN_get_IsSupported,
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 ())