From 5c4dd0d9ea0798c0c5db81bad26c25e7b10830c0 Mon Sep 17 00:00:00 2001 From: Nathan Ricci Date: Tue, 26 Jan 2021 11:22:30 -0800 Subject: [PATCH 1/2] Implemented AdvSimd Abs intrinsic on arm64 --- src/mono/mono/mini/aot-compiler.c | 2 + src/mono/mono/mini/llvm-intrinsics.h | 6 +++ src/mono/mono/mini/mini-llvm.c | 35 ++++++++++++++++++ src/mono/mono/mini/mini.h | 7 ++++ src/mono/mono/mini/simd-intrinsics-netcore.c | 39 ++++++++++++++++++++ src/mono/mono/mini/simd-methods-netcore.h | 2 +- 6 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 1b970c86a1000a..a87b4eda72dfbb 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -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; diff --git a/src/mono/mono/mini/llvm-intrinsics.h b/src/mono/mono/mini/llvm-intrinsics.h index 643c3c0f191643..8fdb28c7a61170 100644 --- a/src/mono/mono/mini/llvm-intrinsics.h +++ b/src/mono/mono/mini/llvm-intrinsics.h @@ -263,6 +263,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 diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 2bf7bd16b57d1a..40e053f4c237c0 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -9093,6 +9093,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 @@ -10564,6 +10580,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 (); @@ -11951,6 +11985,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) diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index 26d99ec2aa65f2..431b74a6766ae8 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -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, diff --git a/src/mono/mono/mini/simd-intrinsics-netcore.c b/src/mono/mono/mini/simd-intrinsics-netcore.c index e69506721629bf..2ff1b6e101a80e 100644 --- a/src/mono/mono/mini/simd-intrinsics-netcore.c +++ b/src/mono/mono/mini/simd-intrinsics-netcore.c @@ -825,6 +825,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) { @@ -941,6 +945,41 @@ 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; + case MONO_TYPE_R4: + op = SIMD_OP_LLVM_FABS; + break; + case MONO_TYPE_I1: + op = SIMD_OP_LLVM_I8ABS; + case MONO_TYPE_I2: + op = SIMD_OP_LLVM_I16ABS; + case MONO_TYPE_I4: + op = SIMD_OP_LLVM_I32ABS; + 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 diff --git a/src/mono/mono/mini/simd-methods-netcore.h b/src/mono/mono/mini/simd-methods-netcore.h index 51601e0c7a8c1d..71c90fd35fae32 100644 --- a/src/mono/mono/mini/simd-methods-netcore.h +++ b/src/mono/mono/mini/simd-methods-netcore.h @@ -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) From 3f2a70c1bf08fb40fcecf6145efb76137b4b9fd5 Mon Sep 17 00:00:00 2001 From: Nathan Ricci Date: Wed, 27 Jan 2021 10:07:56 -0800 Subject: [PATCH 2/2] Changed spacing in case statement. --- src/mono/mono/mini/simd-intrinsics-netcore.c | 44 +++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/mono/mono/mini/simd-intrinsics-netcore.c b/src/mono/mono/mini/simd-intrinsics-netcore.c index 2ff1b6e101a80e..cad3a18df1f2c5 100644 --- a/src/mono/mono/mini/simd-intrinsics-netcore.c +++ b/src/mono/mono/mini/simd-intrinsics-netcore.c @@ -955,27 +955,31 @@ emit_arm64_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignatur 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; - case MONO_TYPE_R4: - op = SIMD_OP_LLVM_FABS; - break; - case MONO_TYPE_I1: - op = SIMD_OP_LLVM_I8ABS; - case MONO_TYPE_I2: - op = SIMD_OP_LLVM_I16ABS; - case MONO_TYPE_I4: - op = SIMD_OP_LLVM_I32ABS; - 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); + 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); + } } }