Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Merge branch 'main' into vector-intrinsics-dot-product
  • Loading branch information
simonrozsival authored Mar 11, 2022
commit 08ac8a2455c109df1e752737c741b2281c61f297
168 changes: 97 additions & 71 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -978,68 +978,7 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
case SN_Xor:
if (!is_element_type_primitive (fsig->params [0]))
return NULL;
int instc0 = -1;
if (type_enum_is_float (arg0_type)) {
switch (id) {
case SN_Add:
instc0 = OP_FADD;
break;
case SN_Divide:
instc0 = OP_FDIV;
break;
case SN_Max:
instc0 = OP_FMAX;
break;
case SN_Min:
instc0 = OP_FMIN;
break;
case SN_Multiply:
instc0 = OP_FMUL;
break;
case SN_Subtract:
instc0 = OP_FSUB;
break;
default:
g_assert_not_reached ();
}
} else {
switch (id) {
case SN_Add:
instc0 = OP_IADD;
break;
case SN_Divide:
return NULL;
case SN_Max:
instc0 = OP_IMAX;
break;
case SN_Min:
instc0 = OP_IMIN;
break;
case SN_Multiply:
instc0 = OP_IMUL;
break;
case SN_Subtract:
instc0 = OP_ISUB;
break;
default:
g_assert_not_reached ();
}
}
return emit_simd_ins_for_sig (cfg, klass, OP_XBINOP, instc0, arg0_type, fsig, args);
}
case SN_Dot: {
#ifdef TARGET_ARM64
if (!is_element_type_primitive (fsig->params [0]))
return NULL;

int instc0 = type_enum_is_float (arg0_type) ? OP_FMUL : OP_IMUL;
MonoInst *pairwise_multiply = emit_simd_ins_for_sig (cfg, klass, OP_XBINOP, instc0, arg0_type, fsig, args);

return emit_sum_vector (cfg, fsig->params [0], arg0_type, pairwise_multiply);
#else
return NULL;
#endif
}
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id);
case SN_AndNot:
#ifdef TARGET_ARM64
if (!is_element_type_primitive (fsig->params [0]))
Expand Down Expand Up @@ -1217,17 +1156,109 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
g_assert_not_reached ();
}
}
case SN_Negate:
case SN_OnesComplement: {
case SN_Narrow: {
#ifdef TARGET_ARM64
if (!is_element_type_primitive (fsig->params [0]))
return NULL;
int op = id == SN_Negate ? OP_ARM64_XNEG : OP_ARM64_MVN;
return emit_simd_ins_for_sig (cfg, klass, op, -1, arg0_type, fsig, args);

MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
int size = mono_class_value_size (arg_class, NULL);

if (size == 16) {
switch (arg0_type) {
case MONO_TYPE_R8: {
MonoInst *ins = emit_simd_ins (cfg, arg_class, OP_ARM64_FCVTN, args [0]->dreg, -1);
return emit_simd_ins (cfg, arg_class, OP_ARM64_FCVTN2, ins->dreg, args [1]->dreg);
}
case MONO_TYPE_I2:
case MONO_TYPE_I4:
case MONO_TYPE_I8:
case MONO_TYPE_U2:
case MONO_TYPE_U4:
case MONO_TYPE_U8: {
MonoInst *ins = emit_simd_ins (cfg, arg_class, OP_ARM64_XTN, args [0]->dreg, -1);
return emit_simd_ins (cfg, arg_class, OP_ARM64_XTN2, ins->dreg, args [1]->dreg);
}
default:
return NULL;
}
} else {
switch (arg0_type) {
case MONO_TYPE_R8: {
//Widen arg0
MonoInst *ins1 = emit_simd_ins (cfg, arg_class, OP_XWIDEN_UNSAFE, args [0]->dreg, -1);

//Insert arg1 to arg0
int tmp = alloc_ireg (cfg);
MONO_EMIT_NEW_ICONST (cfg, tmp, 1);
MonoInst *ins2 = emit_simd_ins (cfg, arg_class, OP_EXTRACT_R8, args [1]->dreg, -1);
ins2->inst_c0 = 0;
ins2->inst_c1 = arg0_type;

MonoClass *ivector128_inst = create_class_instance (cfg, fsig, "System.Runtime.Intrinsics", "Vector128`1", TRUE, NULL);

ins1 = emit_simd_ins (cfg, ivector128_inst, OP_XINSERT_R8, ins1->dreg, ins2->dreg);
ins1->sreg3 = tmp;
ins1->inst_c1 = arg0_type;

//ConvertToSingleLower
return emit_simd_ins (cfg, arg_class, OP_ARM64_FCVTN, ins1->dreg, -1);
}
case MONO_TYPE_I2:
case MONO_TYPE_I4:
case MONO_TYPE_I8:
case MONO_TYPE_U2:
case MONO_TYPE_U4:
case MONO_TYPE_U8: {
//Widen arg0
MonoInst *arg0 = emit_simd_ins (cfg, arg_class, OP_XWIDEN_UNSAFE, args [0]->dreg, -1);

//Cast arg0 and arg1 to u/int64
MonoType *type_new;
MonoTypeEnum type_enum_new;
if (type_enum_is_unsigned (arg0_type)) {
type_new = m_class_get_byval_arg (mono_defaults.uint64_class);
type_enum_new = MONO_TYPE_U8;
} else {
type_new = m_class_get_byval_arg (mono_defaults.int64_class);
type_enum_new = MONO_TYPE_I8;
}
MonoClass *ivector128_64_inst = create_class_instance (cfg, fsig, "System.Runtime.Intrinsics", "Vector128`1", FALSE, type_new);
arg0 = emit_simd_ins (cfg, ivector128_64_inst, OP_XCAST, arg0->dreg, -1);
MonoClass *ivector64_64_inst = create_class_instance (cfg, fsig, "System.Runtime.Intrinsics", "Vector64`1", FALSE, type_new);
MonoInst *arg1 = emit_simd_ins (cfg, ivector64_64_inst, OP_XCAST, args [1]->dreg, -1);

//Insert arg1 to arg0
int tmp = alloc_ireg (cfg);
MONO_EMIT_NEW_ICONST (cfg, tmp, 1);
arg1 = emit_simd_ins (cfg, ivector64_64_inst, OP_EXTRACT_I8, arg1->dreg, -1);
arg1->inst_c0 = 0;
arg1->inst_c1 = type_enum_new;
MonoClass *ivector128_inst = create_class_instance (cfg, fsig, "System.Runtime.Intrinsics", "Vector128`1", TRUE, NULL);
MonoInst *ins = emit_simd_ins (cfg, ivector128_64_inst, OP_XINSERT_I8, arg0->dreg, arg1->dreg);
ins->sreg3 = tmp;
ins->inst_c1 = type_enum_new;

//Cast arg0 back to its original element type (arg0_type)
ins = emit_simd_ins (cfg, ivector128_inst, OP_XCAST, ins->dreg, -1);

//ExtractNarrowingLower
return emit_simd_ins (cfg, ivector128_inst, OP_ARM64_XTN, ins->dreg, -1);
}
default:
return NULL;
}
}
#else
return NULL;
#endif
}
case SN_Negate:
case SN_OnesComplement: {
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]))
Expand All @@ -1237,11 +1268,6 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return NULL;
#endif
}
case SN_Sqrt: {
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_Sqrt: {
#ifdef TARGET_ARM64
if (!is_element_type_primitive (fsig->params [0]))
Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.