Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/mono/mono/mini/llvm-intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,10 @@ INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FADDP, aarch64_neon_faddp, Arm64, V64 | V128 |
INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_FMAXNMV, aarch64_neon_fmaxnmv, Arm64, Across, V64 | V128 | R4 | R8)
INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_FMINNMV, aarch64_neon_fminnmv, Arm64, Across, V64 | V128 | R4 | R8)

INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_SADDV, aarch64_neon_saddv, Arm64, Across, V64 | V128 | I1 | I2 | I4)
INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_SADDV, aarch64_neon_saddv, Arm64, Across, V64 | V128 | I1 | I2 | I4 | I8)
INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_UADDV, aarch64_neon_uaddv, Arm64, Across, V64 | V128 | I1 | I2 | I4 | I8)
INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_FADDV, aarch64_neon_faddv, Arm64, Across, V64 | V128 | R4 | R8)

INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_SMAXV, aarch64_neon_smaxv, Arm64, Across, V64 | V128 | I1 | I2 | I4)
INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_UMAXV, aarch64_neon_umaxv, Arm64, Across, V64 | V128 | I1 | I2 | I4)
INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_SMINV, aarch64_neon_sminv, Arm64, Across, V64 | V128 | I1 | I2 | I4)
Expand Down
8 changes: 8 additions & 0 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -11023,6 +11023,14 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
values [ins->dreg] = result;
break;
}
case OP_ARM64_XADDV: {
IntrinsicId iid = (IntrinsicId) ins->inst_c0;
LLVMTypeRef arg_t = LLVMTypeOf (lhs);
llvm_ovr_tag_t ovr_tag = ovr_tag_from_llvm_type (arg_t);
LLVMValueRef result = call_overloaded_intrins (ctx, iid, ovr_tag, &lhs, "arm64_xaddv");
values [ins->dreg] = result;
break;
}
case OP_ARM64_SXTL:
case OP_ARM64_SXTL2:
case OP_ARM64_UXTL:
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/mini-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -1812,7 +1812,7 @@ MINI_OP(OP_ARM64_UADALP, "arm64_uadalp_scalar", XREG, XREG, XREG)

MINI_OP(OP_ARM64_SADDLV, "arm64_saddlv", XREG, XREG, NONE)
MINI_OP(OP_ARM64_UADDLV, "arm64_uaddlv", XREG, XREG, NONE)

MINI_OP(OP_ARM64_XADDV, "arm64_xaddv", XREG, XREG, NONE)
MINI_OP(OP_ARM64_XHORIZ, "arm64_xhoriz", XREG, XREG, NONE)

MINI_OP3(OP_ARM64_SABAL, "arm64_sabal", XREG, XREG, XREG, XREG)
Expand Down
44 changes: 44 additions & 0 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,39 @@ emit_xones (MonoCompile *cfg, MonoClass *klass)
return emit_simd_ins (cfg, klass, OP_XONES, -1, -1);
}

#ifdef TARGET_ARM64
static int type_to_extract_op (MonoTypeEnum type);
static MonoType* get_vector_t_elem_type (MonoType *vector_type);

static MonoInst*
emit_sum_vector (MonoCompile *cfg, MonoType *vector_type, MonoTypeEnum element_type, MonoInst *arg)
{
MonoClass *vector_class = mono_class_from_mono_type_internal (vector_type);
int vector_size = mono_class_value_size (vector_class, NULL);
MonoClass *element_class = mono_class_from_mono_type_internal (get_vector_t_elem_type (vector_type));
int element_size = mono_class_value_size (element_class, NULL);
gboolean has_single_element = vector_size == element_size;

// If there's just one element we need to extract it instead of summing the whole array
if (has_single_element) {
MonoInst *ins = emit_simd_ins (cfg, vector_class, type_to_extract_op (element_type), arg->dreg, -1);
ins->inst_c0 = 0;
ins->inst_c1 = element_type;
return ins;
}

MonoInst *ins = emit_simd_ins (cfg, vector_class, OP_ARM64_XADDV, arg->dreg, -1);

if (type_enum_is_float (element_type)) {
ins->inst_c0 = INTRINS_AARCH64_ADV_SIMD_FADDV;
} else {
ins->inst_c0 = type_enum_is_unsigned (element_type) ? INTRINS_AARCH64_ADV_SIMD_UADDV : INTRINS_AARCH64_ADV_SIMD_SADDV;
}

return ins;
}
#endif

static gboolean
is_intrinsics_vector_type (MonoType *vector_type)
{
Expand Down Expand Up @@ -831,6 +864,7 @@ static guint16 sri_vector_methods [] = {
SN_CreateScalar,
SN_CreateScalarUnsafe,
SN_Divide,
SN_Dot,
SN_Equals,
SN_EqualsAll,
SN_EqualsAny,
Expand Down Expand Up @@ -858,6 +892,7 @@ static guint16 sri_vector_methods [] = {
SN_OnesComplement,
SN_Sqrt,
SN_Subtract,
SN_Sum,
SN_ToScalar,
SN_ToVector128,
SN_ToVector128Unsafe,
Expand Down Expand Up @@ -1223,6 +1258,15 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
if (!is_element_type_primitive (fsig->params [0]))
return NULL;
return emit_simd_ins_for_unary_op (cfg, klass, fsig, args, arg0_type, id);
}
case SN_Sum: {
#ifdef TARGET_ARM64
if (!is_element_type_primitive (fsig->params [0]))
return NULL;
return emit_sum_vector (cfg, fsig->params [0], arg0_type, args [0]);
#else
return NULL;
#endif
}
case SN_Sqrt: {
#ifdef TARGET_ARM64
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/mini/simd-methods.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,13 @@ METHOD(Create)
METHOD(CreateScalar)
METHOD(CreateScalarUnsafe)
METHOD(ConditionalSelect)
METHOD(Dot)
METHOD(EqualsAll)
METHOD(EqualsAny)
METHOD(GetElement)
METHOD(GetLower)
METHOD(GetUpper)
METHOD(Sum)
METHOD(ToScalar)
METHOD(ToVector128)
METHOD(ToVector128Unsafe)
Expand Down