未验证 提交 f638a75f 编写于 作者: N Nathan Ricci 提交者: GitHub

[Mono][LLVM][ARM] Implemented Arm64 Abs intrinsic (#47482)

* Implemented AdvSimd Abs intrinsic on arm64
上级 64da821c
......@@ -8229,6 +8229,8 @@ parse_cpu_features (const gchar *attr)
feature = MONO_CPU_ARM64_BASE;
else if (!strcmp (attr + prefix, "crc"))
feature = MONO_CPU_ARM64_CRC;
else if (!strcmp (attr + prefix, "simd"))
feature = MONO_CPU_ARM64_ADVSIMD;
#elif defined(TARGET_WASM)
if (!strcmp (attr + prefix, "simd"))
feature = MONO_CPU_WASM_SIMD;
......
......@@ -269,6 +269,12 @@ INTRINS(AARCH64_SHA256SU0, aarch64_crypto_sha256su0)
INTRINS(AARCH64_SHA256SU1, aarch64_crypto_sha256su1)
INTRINS(AARCH64_SHA256H, aarch64_crypto_sha256h)
INTRINS(AARCH64_SHA256H2, aarch64_crypto_sha256h2)
INTRINS_OVR(AARCH64_ADV_SIMD_ABS_FLOAT, fabs)
INTRINS_OVR(AARCH64_ADV_SIMD_ABS_DOUBLE, fabs)
INTRINS_OVR(AARCH64_ADV_SIMD_ABS_INT8, aarch64_neon_abs)
INTRINS_OVR(AARCH64_ADV_SIMD_ABS_INT16, aarch64_neon_abs)
INTRINS_OVR(AARCH64_ADV_SIMD_ABS_INT32, aarch64_neon_abs)
INTRINS_OVR(AARCH64_ADV_SIMD_ABS_INT64, aarch64_neon_abs)
#endif
#undef INTRINS
......
......@@ -9095,6 +9095,22 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
values [ins->dreg] = call_intrins (ctx, id, args, "");
break;
}
case OP_XOP_X_X: {
IntrinsicId id = (IntrinsicId)0;
switch (ins->inst_c0) {
case SIMD_OP_LLVM_FABS: id = INTRINS_AARCH64_ADV_SIMD_ABS_FLOAT; break;
case SIMD_OP_LLVM_DABS: id = INTRINS_AARCH64_ADV_SIMD_ABS_DOUBLE; break;
case SIMD_OP_LLVM_I8ABS: id = INTRINS_AARCH64_ADV_SIMD_ABS_INT8; break;
case SIMD_OP_LLVM_I16ABS: id = INTRINS_AARCH64_ADV_SIMD_ABS_INT16; break;
case SIMD_OP_LLVM_I32ABS: id = INTRINS_AARCH64_ADV_SIMD_ABS_INT32; break;
case SIMD_OP_LLVM_I64ABS: id = INTRINS_AARCH64_ADV_SIMD_ABS_INT64; break;
default: g_assert_not_reached (); break;
}
LLVMValueRef arg0 = lhs;
values [ins->dreg] = call_intrins (ctx, id, &arg0, "");
break;
}
case OP_LSCNT32:
case OP_LSCNT64: {
// %shr = ashr i32 %x, 31
......@@ -10566,6 +10582,24 @@ add_intrinsic (LLVMModuleRef module, int id)
case INTRINS_BITREVERSE_I64:
intrins = add_intrins1 (module, id, LLVMInt64Type ());
break;
case INTRINS_AARCH64_ADV_SIMD_ABS_FLOAT:
intrins = add_intrins1 (module, id, sse_r4_t);
break;
case INTRINS_AARCH64_ADV_SIMD_ABS_DOUBLE:
intrins = add_intrins1 (module, id, sse_r8_t);
break;
case INTRINS_AARCH64_ADV_SIMD_ABS_INT8:
intrins = add_intrins1 (module, id, sse_i1_t);
break;
case INTRINS_AARCH64_ADV_SIMD_ABS_INT16:
intrins = add_intrins1 (module, id, sse_i2_t);
break;
case INTRINS_AARCH64_ADV_SIMD_ABS_INT32:
intrins = add_intrins1 (module, id, sse_i4_t);
break;
case INTRINS_AARCH64_ADV_SIMD_ABS_INT64:
intrins = add_intrins1 (module, id, sse_i8_t);
break;
#endif
default:
g_assert_not_reached ();
......@@ -11953,6 +11987,7 @@ MonoCPUFeatures mono_llvm_get_cpu_features (void)
#if defined(TARGET_ARM64)
{ "crc", MONO_CPU_ARM64_CRC },
{ "crypto", MONO_CPU_ARM64_CRYPTO },
{ "neon", MONO_CPU_ARM64_ADVSIMD }
#endif
};
if (!cpu_features)
......
......@@ -2872,6 +2872,7 @@ typedef enum {
MONO_CPU_ARM64_BASE = 1 << 1,
MONO_CPU_ARM64_CRC = 1 << 2,
MONO_CPU_ARM64_CRYPTO = 1 << 3,
MONO_CPU_ARM64_ADVSIMD = 1 << 4,
#endif
} MonoCPUFeatures;
......@@ -2899,6 +2900,12 @@ enum {
/* SIMD operations */
typedef enum {
SIMD_OP_LLVM_FABS,
SIMD_OP_LLVM_DABS,
SIMD_OP_LLVM_I8ABS,
SIMD_OP_LLVM_I16ABS,
SIMD_OP_LLVM_I32ABS,
SIMD_OP_LLVM_I64ABS,
SIMD_OP_SSE_CVTSS2SI,
SIMD_OP_SSE_CVTTSS2SI,
SIMD_OP_SSE_CVTSS2SI64,
......
......@@ -835,6 +835,10 @@ static SimdIntrinsic sha256_methods [] = {
{SN_get_IsSupported}
};
static SimdIntrinsic advsimd_methods [] = {
{SN_Abs}
};
static MonoInst*
emit_arm64_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
{
......@@ -957,6 +961,45 @@ emit_arm64_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignatur
if (info->op != 0)
return emit_simd_ins_for_sig (cfg, klass, info->op, info->instc0, arg0_type, fsig, args);
}
if (is_hw_intrinsics_class (klass, "AdvSimd", &is_64bit)) {
info = lookup_intrins_info (advsimd_methods, sizeof (advsimd_methods), cmethod);
if (!info)
return NULL;
supported = (mini_get_cpu_features (cfg) & MONO_CPU_ARM64_ADVSIMD) != 0;
switch (info -> id) {
case SN_Abs: {
SimdOp op = (SimdOp)0;
switch (get_underlying_type (fsig->params [0])) {
case MONO_TYPE_R8:
op = SIMD_OP_LLVM_DABS;
break;
case MONO_TYPE_R4:
op = SIMD_OP_LLVM_FABS;
break;
case MONO_TYPE_I1:
op = SIMD_OP_LLVM_I8ABS;
break;
case MONO_TYPE_I2:
op = SIMD_OP_LLVM_I16ABS;
break;
case MONO_TYPE_I4:
op = SIMD_OP_LLVM_I32ABS;
break;
case MONO_TYPE_I8:
op = SIMD_OP_LLVM_I64ABS;
break;
}
return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X, op, arg0_type, fsig, args);
}
}
}
return NULL;
}
#endif // TARGET_ARM64
......
......@@ -183,7 +183,7 @@ METHOD(MoveAndDuplicate)
METHOD(MoveHighAndDuplicate)
METHOD(MoveLowAndDuplicate)
// Ssse3
METHOD(Abs)
METHOD(Abs) // Also used by ARM64
METHOD(AlignRight)
METHOD(HorizontalAddSaturate)
METHOD(HorizontalSubtractSaturate)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册