mini_emit_init_rvar (cfg, dreg, t);
ins = cfg->cbb->last_ins;
} else {
- MONO_INST_NEW (cfg, ins, MONO_CLASS_IS_SIMD (cfg, arg0) ? OP_XZERO : OP_VZERO);
+ MONO_INST_NEW (cfg, ins, mini_class_is_simd (cfg, arg0) ? OP_XZERO : OP_VZERO);
ins->dreg = mono_alloc_dreg (cfg, STACK_VTYPE);
ins->type = STACK_VTYPE;
ins->klass = arg0;
#define MONO_EMIT_NEW_VZERO(cfg,dr,kl) do { \
MonoInst *__inst; \
- MONO_INST_NEW ((cfg), (__inst), MONO_CLASS_IS_SIMD (cfg, kl) ? OP_XZERO : OP_VZERO); \
+ MONO_INST_NEW ((cfg), (__inst), mini_class_is_simd (cfg, kl) ? OP_XZERO : OP_VZERO); \
__inst->dreg = dr; \
(__inst)->type = STACK_VTYPE; \
(__inst)->klass = (kl); \
type = mono_class_enum_basetype_internal (type->data.klass);
goto handle_enum;
}
- if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type_internal (type)))
+ if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type)))
return OP_XMOVE;
return OP_VMOVE;
case MONO_TYPE_TYPEDBYREF:
return OP_VMOVE;
case MONO_TYPE_GENERICINST:
- if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type_internal (type)))
+ if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type)))
return OP_XMOVE;
type = m_class_get_byval_arg (type->data.generic_class->container_class);
goto handle_enum;
EMIT_NEW_RETLOADA (cfg, ret_addr);
MonoClass *ret_class = mono_class_from_mono_type_internal (ret_type);
- if (MONO_CLASS_IS_SIMD (cfg, ret_class))
+ if (mini_class_is_simd (cfg, ret_class))
EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, ret_addr->dreg, 0, val->dreg);
else
EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREV_MEMBASE, ret_addr->dreg, 0, val->dreg);
/* printf ("INS: "); mono_print_ins (ins); */
/* Create a store instruction */
NEW_STORE_MEMBASE (cfg, store_ins, store_opcode, var->inst_basereg, var->inst_offset, ins->dreg);
+ if (store_ins->opcode == OP_STOREX_MEMBASE)
+ mini_type_to_eval_stack_type (cfg, var->inst_vtype, store_ins);
/* Insert it after the instruction */
mono_bblock_insert_after_ins (bb, ins, store_ins);
g_assert (load_opcode != OP_LOADI8_MEMBASE);
#endif
NEW_LOAD_MEMBASE (cfg, load_ins, load_opcode, sreg, var->inst_basereg, var->inst_offset);
+ if (load_ins->opcode == OP_LOADX_MEMBASE)
+ mini_type_to_eval_stack_type (cfg, var->inst_vtype, load_ins);
mono_bblock_insert_before_ins (bb, ins, load_ins);
use_ins = load_ins;
}
*/
if ((t->type == MONO_TYPE_GENERICINST) && !cfg->full_aot && !sig->pinvoke) {
MonoClass *klass = mono_class_from_mono_type_internal (t);
- if (MONO_CLASS_IS_SIMD (cfg, klass)) {
+ if (mini_class_is_simd (cfg, klass)) {
linfo->args [i].storage = LLVMArgVtypeInSIMDReg;
break;
}
/* Allocate a local to hold the result, the epilog will copy it to the correct place */
MonoType *ret_type = mini_get_underlying_type (sig->ret);
MonoClass *klass = mono_class_from_mono_type_internal (ret_type);
- if (MONO_CLASS_IS_SIMD (cfg, klass)) {
+ if (mini_class_is_simd (cfg, klass)) {
int align_simd = mono_type_size (m_class_get_byval_arg (klass), NULL);
offset = ALIGN_TO (offset, align_simd);
}
*/
if ((t->type == MONO_TYPE_GENERICINST) && !cfg->full_aot && !sig->pinvoke) {
MonoClass *klass = mono_class_from_mono_type_internal (t);
- if (MONO_CLASS_IS_SIMD (cfg, klass)) {
+ if (mini_class_is_simd (cfg, klass)) {
lainfo->storage = LLVMArgVtypeInSIMDReg;
break;
}
code = emit_xextract (code, VREG_FULL, ins->inst_c0, dreg, sreg1);
break;
case OP_STOREX_MEMBASE:
- code = emit_strfpq (code, sreg1, dreg, ins->inst_offset);
+ if (ins->klass && mono_class_value_size (ins->klass, NULL) == 8)
+ code = emit_strfpx (code, sreg1, dreg, ins->inst_offset);
+ else
+ code = emit_strfpq (code, sreg1, dreg, ins->inst_offset);
break;
case OP_LOADX_MEMBASE:
- code = emit_ldrfpq (code, dreg, sreg1, ins->inst_offset);
+ if (ins->klass && mono_class_value_size (ins->klass, NULL) == 8)
+ code = emit_ldrfpx (code, dreg, sreg1, ins->inst_offset);
+ else
+ code = emit_ldrfpq (code, dreg, sreg1, ins->inst_offset);
break;
case OP_XMOVE:
if(dreg != sreg1)
klass = mono_class_from_mono_type_internal (t);
- if (MONO_CLASS_IS_SIMD (ctx->cfg, klass))
+ if (mini_class_is_simd (ctx->cfg, klass))
return simd_class_to_llvm_type (ctx, klass);
if (m_class_is_enumtype (klass))
klass = mono_class_from_mono_type_internal (t);
size = mono_class_value_size (klass, NULL);
- if (MONO_CLASS_IS_SIMD (ctx->cfg, klass))
+ if (mini_class_is_simd (ctx->cfg, klass))
address = build_ptr_cast (ctx->builder, address, pointer_type (LLVMInt8Type ()));
if (ainfo->storage == LLVMArgAsFpArgs)
switch (ainfo->pair_storage [j]) {
case LLVMArgInIReg: {
part_type = LLVMIntType (part_size * 8);
- if (MONO_CLASS_IS_SIMD (ctx->cfg, klass)) {
+ if (mini_class_is_simd (ctx->cfg, klass)) {
index [0] = const_int32 (j * TARGET_SIZEOF_VOID_P);
addr = LLVMBuildGEP2 (builder, i1_t, address, index, 1, "");
} else {
t = mini_get_underlying_type (t);
int32_t size = get_vtype_size_align (t).size;
- if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (t)))
+ if (mini_class_is_simd (ctx->cfg, mono_class_from_mono_type_internal (t)))
address = build_ptr_cast (ctx->builder, address, pointer_type (LLVMInt8Type ()));
if (ainfo->storage == LLVMArgAsFpArgs)
switch (ainfo->pair_storage [j]) {
case LLVMArgInIReg:
- if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (t))) {
+ if (mini_class_is_simd (ctx->cfg, mono_class_from_mono_type_internal (t))) {
index [0] = const_int32 (j * TARGET_SIZEOF_VOID_P);
addr = LLVMBuildGEP2 (builder, i1_t, address, index, 1, "");
} else {
g_assert (!mini_is_gsharedvt_variable_type (t));
- if (MONO_CLASS_IS_SIMD (ctx->cfg, k))
+ if (mini_class_is_simd (ctx->cfg, k))
align = mono_class_value_size (k, NULL);
else
align = mono_class_min_align (k);
if ((var->opcode == OP_GSHAREDVT_LOCAL || var->opcode == OP_GSHAREDVT_ARG_REGOFFSET))
continue;
- if (var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || (mini_type_is_vtype (var->inst_vtype) && !MONO_CLASS_IS_SIMD (ctx->cfg, var->klass))) {
+ if (var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || (mini_type_is_vtype (var->inst_vtype) && !mini_class_is_simd (ctx->cfg, var->klass))) {
if (!ctx_ok (ctx))
return;
/* Could be already created by an OP_VPHI */
case LLVMArgVtypeByRef:
case LLVMArgAsFpArgs:
{
- if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (ainfo->type)))
+ if (mini_class_is_simd (ctx->cfg, mono_class_from_mono_type_internal (ainfo->type)))
/* Treat these as normal values */
ctx->values [reg] = LLVMBuildLoad2 (builder, ctx->addresses [reg]->type, ctx->addresses [reg]->value, "simd_vtype");
break;
}
MonoClass *retclass = mono_class_from_mono_type_internal (sig->ret);
- gboolean is_simd = MONO_CLASS_IS_SIMD (ctx->cfg, retclass);
+ gboolean is_simd = mini_class_is_simd (ctx->cfg, retclass);
gboolean should_promote_to_value = FALSE;
const char *load_name = NULL;
/*
LLVMTypeRef ret_type = LLVMGetReturnType (ctx->lmethod_type);
LLVMValueRef retval = LLVMGetUndef (ret_type);
gboolean src_in_reg = FALSE;
- gboolean is_simd = MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (sig->ret));
+ gboolean is_simd = mini_class_is_simd (ctx->cfg, mono_class_from_mono_type_internal (sig->ret));
switch (linfo->ret.storage) {
case LLVMArgNormal: src_in_reg = TRUE; break;
case LLVMArgVtypeInReg: case LLVMArgVtypeAsScalar: src_in_reg = is_simd; break;
case LLVMArgFpStruct: {
LLVMTypeRef ret_type = LLVMGetReturnType (ctx->lmethod_type);
LLVMValueRef retval, elem;
- gboolean is_simd = MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (sig->ret));
+ gboolean is_simd = mini_class_is_simd (ctx->cfg, mono_class_from_mono_type_internal (sig->ret));
if (is_simd) {
g_assert (lhs);
case OP_LDADDR: {
MonoInst *var = ins->inst_i0;
- if (var->opcode == OP_VTARG_ADDR && !MONO_CLASS_IS_SIMD(cfg, var->klass)) {
+ if (var->opcode == OP_VTARG_ADDR && !mini_class_is_simd(cfg, var->klass)) {
/* The variable contains the vtype address */
values [ins->dreg] = values [var->dreg];
} else if (var->opcode == OP_GSHAREDVT_LOCAL) {
MINI_OP(OP_STOREI2_MEMBASE_IMM, "storei2_membase_imm", IREG, NONE, NONE)
MINI_OP(OP_STOREI4_MEMBASE_IMM, "storei4_membase_imm", IREG, NONE, NONE)
MINI_OP(OP_STOREI8_MEMBASE_IMM, "storei8_membase_imm", IREG, NONE, NONE)
+/* klass must be set to a simd class */
MINI_OP(OP_STOREX_MEMBASE, "storex_membase", IREG, XREG, NONE)
MINI_OP(OP_STOREV_MEMBASE, "storev_membase", IREG, VREG, NONE)
MINI_OP(OP_LOADR4_MEMBASE,"loadr4_membase", FREG, IREG, NONE)
MINI_OP(OP_LOADR8_MEMBASE,"loadr8_membase", FREG, IREG, NONE)
+/* klass must be set to a simd class */
MINI_OP(OP_LOADX_MEMBASE, "loadx_membase", XREG, IREG, NONE)
#if defined(TARGET_X86) || defined(TARGET_AMD64)
type = mono_class_enum_basetype_internal (type->data.klass);
goto handle_enum;
}
- if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type_internal (type)))
+ if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type)))
return OP_STOREX_MEMBASE;
return OP_STOREV_MEMBASE;
case MONO_TYPE_TYPEDBYREF:
return OP_STOREV_MEMBASE;
case MONO_TYPE_GENERICINST:
- if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type_internal (type)))
+ if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type)))
return OP_STOREX_MEMBASE;
type = m_class_get_byval_arg (type->data.generic_class->container_class);
goto handle_enum;
case MONO_TYPE_R8:
return OP_LOADR8_MEMBASE;
case MONO_TYPE_VALUETYPE:
- if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type_internal (type)))
+ if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type)))
return OP_LOADX_MEMBASE;
case MONO_TYPE_TYPEDBYREF:
return OP_LOADV_MEMBASE;
case MONO_TYPE_GENERICINST:
- if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type_internal (type)))
+ if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (type)))
return OP_LOADX_MEMBASE;
if (mono_type_generic_inst_is_valuetype (type))
return OP_LOADV_MEMBASE;
size = mini_type_stack_size (t, &ialign);
align = ialign;
- if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type_internal (t)))
+ if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (t)))
align = 16;
}
if (mono_class_has_failure (mono_class_from_mono_type_internal (t)))
mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
- if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type_internal (t)))
+ if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (t)))
align = 16;
}
#define MONO_IS_REAL_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_FMOVE) || ((ins)->opcode == OP_XMOVE) || ((ins)->opcode == OP_RMOVE))
#define MONO_IS_ZERO(ins) (((ins)->opcode == OP_VZERO) || ((ins)->opcode == OP_XZERO))
-#define MONO_CLASS_IS_SIMD(cfg, klass) (((cfg)->opt & MONO_OPT_SIMD) && m_class_is_simd_type (klass) && (COMPILE_LLVM (cfg) || mono_type_size (m_class_get_byval_arg (klass), NULL) == 16))
-
#else
#define MONO_IS_PHI(ins) (((ins)->opcode == OP_PHI) || ((ins)->opcode == OP_FPHI) || ((ins)->opcode == OP_VPHI))
#define MONO_IS_REAL_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_FMOVE) || ((ins)->opcode == OP_RMOVE))
#define MONO_IS_ZERO(ins) ((ins)->opcode == OP_VZERO)
-#define MONO_CLASS_IS_SIMD(cfg, klass) (0)
-
#endif
#if defined(TARGET_X86) || defined(TARGET_AMD64)
#endif
}
+static inline gboolean
+mini_class_is_simd (MonoCompile *cfg, MonoClass *klass)
+{
+#ifdef MONO_ARCH_SIMD_INTRINSICS
+ if (!(((cfg)->opt & MONO_OPT_SIMD) && m_class_is_simd_type (klass)))
+ return FALSE;
+ if (COMPILE_LLVM (cfg))
+ return TRUE;
+ int size = mono_type_size (m_class_get_byval_arg (klass), NULL);
+#ifdef TARGET_ARM64
+ if (size == 8 || size == 16)
+ return TRUE;
+#else
+ if (size == 16)
+ return TRUE;
+#endif
+#endif
+ return FALSE;
+}
+
gpointer
mono_arch_load_function (MonoJitICallId jit_icall_id);
// Read back.
// TODO: on x86, use a LEA
MonoInst* scratch = emit_xzero (cfg, args [0]->klass);
- MonoInst* scratcha;
+ MonoInst* scratcha, *ins;
NEW_VARLOADA_VREG (cfg, scratcha, scratch->dreg, fsig->params [0]);
MONO_ADD_INS (cfg->cbb, scratcha);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, mono_type_to_store_membase (cfg, fsig->params [0]), scratcha->dreg, 0, args [0]->dreg);
+ EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, fsig->params [0], scratcha->dreg, 0, args [0]->dreg);
int offset_reg = alloc_lreg (cfg);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, offset_reg, args [1]->dreg, type_to_width_log2 (arg0_type));
int addr_reg = alloc_preg (cfg);
MONO_EMIT_NEW_BIALU(cfg, OP_PADD, addr_reg, scratcha->dreg, offset_reg);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, mono_type_to_store_membase (cfg, fsig->params [2]), addr_reg, 0, args [2]->dreg);
+ EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, fsig->params [2], addr_reg, 0, args [2]->dreg);
MonoInst* ret;
NEW_LOAD_MEMBASE (cfg, ret, mono_type_to_load_membase (cfg, fsig->ret), scratch->dreg, scratcha->dreg, 0);
ins->sreg3 = args [1]->dreg;
ins->inst_c1 = MONO_TYPE_R4;
ins->dreg = dreg;
- if (indirect)
+ if (indirect) {
EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, args [0]->dreg, 0, dreg);
+ ins->klass = klass;
+ }
return ins;
}
{
guint32 *sreg = (guint32*)sreg_int32;
MonoInst *src_var = get_vreg_to_inst (cfg, *sreg);
- if (src_var && src_var->opcode == OP_ARG && src_var->klass && MONO_CLASS_IS_SIMD (cfg, src_var->klass)) {
+ if (src_var && src_var->opcode == OP_ARG && src_var->klass && mini_class_is_simd (cfg, src_var->klass)) {
MonoInst *varload_ins, *load_ins;
NEW_VARLOADA (cfg, varload_ins, src_var, src_var->inst_vtype);
mono_bblock_insert_before_ins (bb, ins, varload_ins);
{
guint32 *dreg = (guint32*)dreg_int32;
MonoInst *dest_var = get_vreg_to_inst (cfg, *dreg);
- if (dest_var && dest_var->opcode == OP_ARG && dest_var->klass && MONO_CLASS_IS_SIMD (cfg, dest_var->klass)) {
+ if (dest_var && dest_var->opcode == OP_ARG && dest_var->klass && mini_class_is_simd (cfg, dest_var->klass)) {
MonoInst *varload_ins, *store_ins;
*dreg = alloc_xreg (cfg);
NEW_VARLOADA (cfg, varload_ins, dest_var, dest_var->inst_vtype);
ins->opcode = OP_FPHI;
break;
case STACK_VTYPE:
- ins->opcode = MONO_CLASS_IS_SIMD (cfg, var->klass) ? OP_XPHI : OP_VPHI;
+ ins->opcode = mini_class_is_simd (cfg, var->klass) ? OP_XPHI : OP_VPHI;
break;
}