Skip to content

Commit d09f42d

Browse files
authored
[Mono]Enable emitting intrinsics for System.Numerics.Vector<T> on arm64 (#67125)
* Enable emitting intrinsics for System.Numerics.Vector<T> on arm64 * Handle multiply by scalar * Fix typo * Add support for IsHardwareAccelerated * Move architecture specific code under corresponding functions * Resolve feedback * Fix scalar checking
1 parent 35ff175 commit d09f42d

File tree

1 file changed

+77
-34
lines changed

1 file changed

+77
-34
lines changed

src/mono/mono/mini/simd-intrinsics.c

Lines changed: 77 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,19 @@ emit_simd_ins_for_binary_op (MonoCompile *cfg, MonoClass *klass, MonoMethodSigna
306306
break;
307307
case SN_Multiply:
308308
case SN_op_Multiply:
309+
if (fsig->params [1]->type != MONO_TYPE_GENERICINST) {
310+
MonoInst* ins = emit_simd_ins (cfg, klass, OP_CREATE_SCALAR_UNSAFE, args [1]->dreg, -1);
311+
ins->inst_c1 = arg_type;
312+
ins = emit_simd_ins (cfg, klass, OP_XBINOP_BYSCALAR, args [0]->dreg, ins->dreg);
313+
ins->inst_c0 = OP_FMUL;
314+
return ins;
315+
} else if (fsig->params [0]->type != MONO_TYPE_GENERICINST) {
316+
MonoInst* ins = emit_simd_ins (cfg, klass, OP_CREATE_SCALAR_UNSAFE, args [0]->dreg, -1);
317+
ins->inst_c1 = arg_type;
318+
ins = emit_simd_ins (cfg, klass, OP_XBINOP_BYSCALAR, ins->dreg, args [1]->dreg);
319+
ins->inst_c0 = OP_FMUL;
320+
return ins;
321+
}
309322
instc0 = OP_FMUL;
310323
break;
311324
case SN_Subtract:
@@ -332,6 +345,19 @@ emit_simd_ins_for_binary_op (MonoCompile *cfg, MonoClass *klass, MonoMethodSigna
332345
break;
333346
case SN_Multiply:
334347
case SN_op_Multiply:
348+
if (fsig->params [1]->type != MONO_TYPE_GENERICINST) {
349+
MonoInst* ins = emit_simd_ins (cfg, klass, OP_CREATE_SCALAR_UNSAFE, args [1]->dreg, -1);
350+
ins->inst_c1 = arg_type;
351+
ins = emit_simd_ins (cfg, klass, OP_XBINOP_BYSCALAR, args [0]->dreg, ins->dreg);
352+
ins->inst_c0 = OP_IMUL;
353+
return ins;
354+
} else if (fsig->params [0]->type != MONO_TYPE_GENERICINST) {
355+
MonoInst* ins = emit_simd_ins (cfg, klass, OP_CREATE_SCALAR_UNSAFE, args [0]->dreg, -1);
356+
ins->inst_c1 = arg_type;
357+
ins = emit_simd_ins (cfg, klass, OP_XBINOP_BYSCALAR, ins->dreg, args [1]->dreg);
358+
ins->inst_c0 = OP_IMUL;
359+
return ins;
360+
}
335361
instc0 = OP_IMUL;
336362
break;
337363
case SN_Subtract:
@@ -812,15 +838,9 @@ type_to_extract_op (MonoTypeEnum type)
812838
}
813839

814840
static MonoClass *
815-
create_class_instance (MonoCompile *cfg, MonoMethodSignature *fsig, const char* name_space, const char *name, gboolean same_type, MonoType *param_type)
841+
create_class_instance (const char* name_space, const char *name, MonoType *param_type)
816842
{
817843
MonoClass *ivector = mono_class_load_from_name (mono_defaults.corlib, name_space, name);
818-
if (same_type) {
819-
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
820-
param_type = mono_class_get_generic_class (arg_class)->context.class_inst->type_argv [0];
821-
} else {
822-
g_assert(param_type != NULL);
823-
}
824844

825845
MonoType *args [ ] = { param_type };
826846
MonoGenericContext ctx;
@@ -905,6 +925,7 @@ static guint16 sri_vector_methods [] = {
905925
SN_WidenUpper,
906926
SN_WithElement,
907927
SN_Xor,
928+
SN_get_IsHardwareAccelerated,
908929
};
909930

910931
/* nint and nuint haven't been enabled yet for System.Runtime.Intrinsics.
@@ -957,8 +978,19 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
957978

958979
MonoClass *klass = cmethod->klass;
959980
MonoTypeEnum arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID;
981+
982+
gboolean supported = FALSE;
983+
#ifdef MONO_ARCH_SIMD_INTRINSICS
984+
supported = TRUE;
985+
#endif
960986

961987
switch (id) {
988+
case SN_get_IsHardwareAccelerated: {
989+
MonoInst* ins;
990+
EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0);
991+
ins->type = STACK_I4;
992+
return ins;
993+
}
962994
case SN_Abs: {
963995
if (!is_element_type_primitive (fsig->params [0]))
964996
return NULL;
@@ -1240,7 +1272,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
12401272
ins2->inst_c0 = 0;
12411273
ins2->inst_c1 = arg0_type;
12421274

1243-
MonoClass *ivector128_inst = create_class_instance (cfg, fsig, "System.Runtime.Intrinsics", "Vector128`1", TRUE, NULL);
1275+
MonoType* param_type = get_vector_t_elem_type (fsig->params[0]);
1276+
MonoClass *ivector128_inst = create_class_instance ("System.Runtime.Intrinsics", "Vector128`1", param_type);
12441277

12451278
ins1 = emit_simd_ins (cfg, ivector128_inst, OP_XINSERT_R8, ins1->dreg, ins2->dreg);
12461279
ins1->sreg3 = tmp;
@@ -1268,9 +1301,9 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
12681301
type_new = m_class_get_byval_arg (mono_defaults.int64_class);
12691302
type_enum_new = MONO_TYPE_I8;
12701303
}
1271-
MonoClass *ivector128_64_inst = create_class_instance (cfg, fsig, "System.Runtime.Intrinsics", "Vector128`1", FALSE, type_new);
1304+
MonoClass *ivector128_64_inst = create_class_instance ("System.Runtime.Intrinsics", "Vector128`1", type_new);
12721305
arg0 = emit_simd_ins (cfg, ivector128_64_inst, OP_XCAST, arg0->dreg, -1);
1273-
MonoClass *ivector64_64_inst = create_class_instance (cfg, fsig, "System.Runtime.Intrinsics", "Vector64`1", FALSE, type_new);
1306+
MonoClass *ivector64_64_inst = create_class_instance ("System.Runtime.Intrinsics", "Vector64`1", type_new);
12741307
MonoInst *arg1 = emit_simd_ins (cfg, ivector64_64_inst, OP_XCAST, args [1]->dreg, -1);
12751308

12761309
//Insert arg1 to arg0
@@ -1279,7 +1312,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
12791312
arg1 = emit_simd_ins (cfg, ivector64_64_inst, OP_EXTRACT_I8, arg1->dreg, -1);
12801313
arg1->inst_c0 = 0;
12811314
arg1->inst_c1 = type_enum_new;
1282-
MonoClass *ivector128_inst = create_class_instance (cfg, fsig, "System.Runtime.Intrinsics", "Vector128`1", TRUE, NULL);
1315+
MonoType *param_type = get_vector_t_elem_type (fsig->params[0]);
1316+
MonoClass *ivector128_inst = create_class_instance ("System.Runtime.Intrinsics", "Vector128`1", param_type);
12831317
MonoInst *ins = emit_simd_ins (cfg, ivector128_64_inst, OP_XINSERT_I8, arg0->dreg, arg1->dreg);
12841318
ins->sreg3 = tmp;
12851319
ins->inst_c1 = type_enum_new;
@@ -3701,23 +3735,50 @@ emit_amd64_intrinsics (const char *class_ns, const char *class_name, MonoCompile
37013735
#ifdef TARGET_ARM64
37023736
static
37033737
MonoInst*
3704-
emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
3738+
arch_emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
37053739
{
3706-
// FIXME: implement Vector64<T>, Vector128<T> and Vector<T> for Arm64
37073740
if (!strcmp (class_ns, "System.Runtime.Intrinsics.Arm")) {
37083741
return emit_hardware_intrinsics(cfg, cmethod, fsig, args,
37093742
supported_arm_intrinsics, sizeof (supported_arm_intrinsics),
37103743
emit_arm64_intrinsics);
37113744
}
37123745

3746+
if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
3747+
if (!strcmp (class_name, "Vector128") || !strcmp (class_name, "Vector64"))
3748+
return emit_sri_vector (cfg, cmethod, fsig, args);
3749+
}
3750+
3751+
if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
3752+
if (!strcmp (class_name, "Vector128`1") || !strcmp (class_name, "Vector64`1"))
3753+
return emit_vector64_vector128_t (cfg, cmethod, fsig, args);
3754+
}
3755+
3756+
if (!strcmp (class_ns, "System.Numerics") && !strcmp (class_name, "Vector")){
3757+
return emit_sri_vector (cfg, cmethod, fsig, args);
3758+
}
3759+
3760+
if (!strcmp (class_ns, "System.Numerics") && !strcmp (class_name, "Vector`1")){
3761+
return emit_vector64_vector128_t (cfg, cmethod, fsig, args);
3762+
}
3763+
37133764
return NULL;
37143765
}
37153766
#elif TARGET_AMD64
37163767
// TODO: test and enable for x86 too
37173768
static
37183769
MonoInst*
3719-
emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
3770+
arch_emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
37203771
{
3772+
if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
3773+
if (!strcmp (class_name, "Vector128") || !strcmp (class_name, "Vector64"))
3774+
return emit_sri_vector (cfg, cmethod, fsig, args);
3775+
}
3776+
3777+
if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
3778+
if (!strcmp (class_name, "Vector128`1") || !strcmp (class_name, "Vector64`1"))
3779+
return emit_vector64_vector128_t (cfg, cmethod, fsig, args);
3780+
}
3781+
37213782
MonoInst *simd_inst = emit_amd64_intrinsics (class_ns, class_name, cfg, cmethod, fsig, args);
37223783
if (simd_inst != NULL)
37233784
cfg->uses_simd_intrinsics |= MONO_CFG_USES_SIMD_INTRINSICS;
@@ -3726,7 +3787,7 @@ emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile
37263787
#else
37273788
static
37283789
MonoInst*
3729-
emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
3790+
arch_emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
37303791
{
37313792
return NULL;
37323793
}
@@ -3749,25 +3810,7 @@ mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
37493810
if (m_class_get_nested_in (cmethod->klass))
37503811
class_ns = m_class_get_name_space (m_class_get_nested_in (cmethod->klass));
37513812

3752-
#if defined(TARGET_ARM64) || defined(TARGET_AMD64)
3753-
if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
3754-
if (!strcmp (class_name, "Vector128") || !strcmp (class_name, "Vector64"))
3755-
return emit_sri_vector (cfg, cmethod, fsig, args);
3756-
}
3757-
3758-
if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
3759-
if (!strcmp (class_name, "Vector128`1") || !strcmp (class_name, "Vector64`1"))
3760-
return emit_vector64_vector128_t (cfg, cmethod, fsig, args);
3761-
}
3762-
#endif // defined(TARGET_ARM64) || defined(TARGET_AMD64)
3763-
3764-
#if defined(TARGET_ARM64)
3765-
if (!strcmp (class_ns, "System.Numerics") && !strcmp (class_name, "Vector")){
3766-
return emit_sri_vector (cfg, cmethod, fsig, args);
3767-
}
3768-
#endif // defined(TARGET_ARM64)
3769-
3770-
return emit_simd_intrinsics (class_ns, class_name, cfg, cmethod, fsig, args);
3813+
return arch_emit_simd_intrinsics (class_ns, class_name, cfg, cmethod, fsig, args);
37713814
}
37723815

37733816
/*

0 commit comments

Comments
 (0)