{
const SimdIntrinsic *intrins;
MonoMethodSignature *sig = mono_method_signature (cmethod);
+ MonoType *type = &cmethod->klass->byval_arg;
/*
* Vector2/3/4 are handled the same way, since the underlying SIMD type is the same (4 * r4).
}
switch (intrins->name) {
- case SN_ctor:
+ case SN_ctor: {
+ gboolean match = TRUE;
+ for (int i = 0; i < fsig->param_count; ++i)
+ if (fsig->params [i]->type != MONO_TYPE_R4)
+ match = FALSE;
+ if (!match)
+ break;
return simd_intrinsic_emit_ctor (intrins, cfg, cmethod, args);
- break;
+ }
case SN_Equals:
+ if (!(fsig->param_count == 1 && fsig->ret->type == MONO_TYPE_BOOLEAN && fsig->params [0] == type))
+ break;
return simd_intrinsic_emit_equality (intrins, cfg, cmethod, args);
- break;
case SN_SquareRoot:
+ if (!(fsig->param_count == 1 && fsig->ret == type && fsig->params [0] == type))
+ break;
return simd_intrinsic_emit_unary (intrins, cfg, cmethod, args);
- break;
case SN_Dot:
+ if (!(fsig->param_count == 2 && fsig->ret->type == MONO_TYPE_R4 && fsig->params [0] == type && fsig->params [1] == type))
+ break;
if (COMPILE_LLVM (cfg)) {
MonoInst *ins;
MonoInst *sub;
MonoInst *zero;
+ if (!(fsig->param_count == 1 && fsig->ret == type && fsig->params [0] == type))
+ break;
+
MONO_INST_NEW (cfg, zero, OP_XZERO);
zero->dreg = alloc_xreg (cfg);
zero->klass = cmethod->klass;
case SN_op_Division:
case SN_op_Multiply:
case SN_op_Subtraction:
+ if (!(fsig->param_count == 2 && fsig->ret == type && (fsig->params [0] == type || fsig->params [0]->type == MONO_TYPE_R4) && (fsig->params [1] == type || fsig->params [1]->type == MONO_TYPE_R4)))
+ break;
return simd_intrinsic_emit_binary (intrins, cfg, cmethod, args);
default:
break;
}
+ if (cfg->verbose_level > 1) {
+ char *name = mono_method_full_name (cmethod, TRUE);
+ printf (" SIMD method %s not handled.\n", name);
+ g_free (name);
+ }
return NULL;
}
emit_vector_t_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
{
const SimdIntrinsic *intrins;
- MonoType *etype;
+ MonoType *type, *etype;
MonoInst *ins;
int size, len, index;
return NULL;
}
+ type = &cmethod->klass->byval_arg;
etype = mono_class_get_context (cmethod->klass)->class_inst->type_argv [0];
size = mono_class_value_size (mono_class_from_mono_type (etype), NULL);
g_assert (size);
switch (intrins->name) {
case SN_get_Count:
+ if (!(fsig->param_count == 0 && fsig->ret->type == MONO_TYPE_I4))
+ break;
EMIT_NEW_ICONST (cfg, ins, len);
return ins;
case SN_get_AllOnes:
case SN_get_Zero:
+ if (!(fsig->param_count == 0 && mono_metadata_type_equal (fsig->ret, type)))
+ break;
return simd_intrinsic_emit_const (intrins, cfg, cmethod, args);
case SN_get_Item:
g_assert (fsig->param_count == 1);
break;
}
break;
- case SN_op_Addition: {
- int op = type_to_padd_op (etype);
- if (op != -1)
- return simd_intrinsic_emit_binary_op (cfg, op, 0, cmethod->klass, fsig->params [0], fsig->params [0], args [0], args [1]);
- break;
- }
- case SN_op_Subtraction: {
- int op = type_to_psub_op (etype);
- if (op != -1)
- return simd_intrinsic_emit_binary_op (cfg, op, 0, cmethod->klass, fsig->params [0], fsig->params [0], args [0], args [1]);
- break;
- }
- case SN_op_Multiply: {
- int op = type_to_pmul_op (etype);
- if (op != -1)
- return simd_intrinsic_emit_binary_op (cfg, op, 0, cmethod->klass, fsig->params [0], fsig->params [0], args [0], args [1]);
- break;
- }
- case SN_op_Division: {
- int op = type_to_pdiv_op (etype);
+ case SN_op_Addition:
+ case SN_op_Subtraction:
+ case SN_op_Multiply:
+ case SN_op_Division: {
+ if (!(fsig->param_count == 2 && mono_metadata_type_equal (fsig->ret, fsig->params [0]) && mono_metadata_type_equal (fsig->params [0], fsig->params [1])))
+ break;
+ int op = 0;
+ switch (intrins->name) {
+ case SN_op_Addition:
+ op = type_to_padd_op (etype);
+ break;
+ case SN_op_Subtraction:
+ op = type_to_psub_op (etype);
+ break;
+ case SN_op_Multiply:
+ op = type_to_pmul_op (etype);
+ break;
+ case SN_op_Division:
+ op = type_to_pdiv_op (etype);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
if (op != -1)
return simd_intrinsic_emit_binary_op (cfg, op, 0, cmethod->klass, fsig->params [0], fsig->params [0], args [0], args [1]);
break;
break;
}
+ if (cfg->verbose_level > 1) {
+ char *name = mono_method_full_name (cmethod, TRUE);
+ printf (" SIMD method %s not handled.\n", name);
+ g_free (name);
+ }
+
return NULL;
}