Skip to content
16 changes: 16 additions & 0 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -9086,6 +9086,22 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, ins->opcode == OP_LSCNT32 ? INTRINS_CTLZ_I32 : INTRINS_CTLZ_I64), args, 2, "");
break;
}
case OP_ARM64_SMULH:
case OP_ARM64_UMULH: {
LLVMValueRef op1, op2;
if (ins->opcode == OP_ARM64_SMULH) {
op1 = LLVMBuildSExt (builder, lhs, LLVMInt128Type(), "");
op2 = LLVMBuildSExt (builder, rhs, LLVMInt128Type(), "");
} else {
op1 = LLVMBuildZExt (builder, lhs, LLVMInt128Type(), "");
op2 = LLVMBuildZExt (builder, rhs, LLVMInt128Type(), "");
}
LLVMValueRef mul = LLVMBuildMul (builder, op1, op2, "");
LLVMValueRef hi64 = LLVMBuildLShr (builder, mul,
LLVMConstInt(LLVMInt128Type (), 64, FALSE), "");
values [ins->dreg] = LLVMBuildTrunc (builder, hi64, LLVMInt64Type(), "");
break;
}
#endif

case OP_DUMMY_USE:
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/mini/mini-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -1578,4 +1578,6 @@ MINI_OP(OP_POPCNT64, "popcnt64", LREG, LREG, NONE)
#ifdef TARGET_ARM64
MINI_OP(OP_LSCNT32, "lscnt32", IREG, IREG, NONE)
MINI_OP(OP_LSCNT64, "lscnt64", LREG, LREG, NONE)
MINI_OP(OP_ARM64_SMULH, "arm64_smulh", LREG, LREG, LREG)
MINI_OP(OP_ARM64_UMULH, "arm64_umulh", LREG, LREG, LREG)
#endif // TARGET_ARM64
4 changes: 4 additions & 0 deletions src/mono/mono/mini/simd-intrinsics-netcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,7 @@ emit_invalid_operation (MonoCompile *cfg, const char* message)
static SimdIntrinsic armbase_methods [] = {
{SN_LeadingSignCount},
{SN_LeadingZeroCount},
{SN_MultiplyHigh},
{SN_ReverseElementBits},
{SN_get_IsSupported}
};
Expand Down Expand Up @@ -847,6 +848,9 @@ emit_arm64_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignatur
return emit_simd_ins_for_sig (cfg, klass, arg0_i32 ? OP_LZCNT32 : OP_LZCNT64, 0, arg0_type, fsig, args);
case SN_LeadingSignCount:
return emit_simd_ins_for_sig (cfg, klass, arg0_i32 ? OP_LSCNT32 : OP_LSCNT64, 0, arg0_type, fsig, args);
case SN_MultiplyHigh:
return emit_simd_ins_for_sig (cfg, klass,
(arg0_type == MONO_TYPE_I8 ? OP_ARM64_SMULH : OP_ARM64_UMULH), 0, arg0_type, fsig, args);
case SN_ReverseElementBits:
return emit_simd_ins_for_sig (cfg, klass,
(is_64bit ? OP_XOP_I8_I8 : OP_XOP_I4_I4),
Expand Down