Skip to content

Commit

Permalink
Adding support to mono for v128 constants
Browse files Browse the repository at this point in the history
  • Loading branch information
tannergooding committed Feb 9, 2023
1 parent 7f73d0c commit f3f0340
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 43 deletions.
9 changes: 7 additions & 2 deletions src/mono/mono/mini/cfold.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,15 @@ mono_constant_fold_ins (MonoCompile *cfg, MonoInst *ins, MonoInst *arg1, MonoIns
}
break;
case OP_XMOVE:
if (arg1->opcode == OP_XZERO) {
if ((arg1->opcode == OP_XZERO) || (arg1->opcode == OP_XONES)) {
ALLOC_DEST (cfg, dest, ins);
dest->opcode = OP_XZERO;
dest->opcode = arg1->opcode;
dest->sreg1 = -1;
} else if (arg1->opcode == OP_XCONST) {
ALLOC_DEST (cfg, dest, ins);
dest->opcode = arg1->opcode;
dest->sreg1 = -1;
dest->inst_p0 = arg1->inst_p0;
}
break;
case OP_COMPARE:
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/cpu-amd64.mdesc
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,7 @@ cvttps2dq: dest:x src1:x len:5 clob:1
xmove: dest:x src1:x len:5
xzero: dest:x len:5
xones: dest:x len:5
xconst: dest:x len:5

iconv_to_x: dest:x src1:i len:5
extract_i4: dest:i src1:x len:5
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/cpu-x86.mdesc
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ cvttps2dq: dest:x src1:x len:4 clob:1
xmove: dest:x src1:x len:4
xzero: dest:x len:4
xones: dest:x len:4
xconst: dest:x len:4

iconv_to_x: dest:x src1:i len:4
extract_i4: dest:i src1:x len:4
Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/mini/liveness.c
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ optimize_initlocals (MonoCompile *cfg)
//printf ("DEAD: "); mono_print_ins (ins);
if (cfg->disable_initlocals_opt_refs && var->type == STACK_OBJ)
continue;
if ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_R4CONST)) {
if ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_R4CONST) || (ins->opcode == OP_XCONST)) {
NULLIFY_INS (ins);
MONO_VARINFO (cfg, var->inst_c0)->spill_costs -= 1;
/*
Expand Down Expand Up @@ -874,7 +874,7 @@ update_liveness2 (MonoCompile *cfg, MonoInst *ins, gboolean set_volatile, int in
}
else {
/* Try dead code elimination */
if (!cfg->disable_deadce_vars && (var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST)) && !(var->flags & MONO_INST_VOLATILE)) {
if (!cfg->disable_deadce_vars && (var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_XCONST)) && !(var->flags & MONO_INST_VOLATILE)) {
LIVENESS_DEBUG (printf ("\tdead def of R%d, eliminated\n", ins->dreg));
NULLIFY_INS (ins);
return;
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -12640,6 +12640,7 @@ mono_op_no_side_effects (int opcode)
case OP_VZERO:
case OP_XZERO:
case OP_XONES:
case OP_XCONST:
case OP_ICONST:
case OP_I8CONST:
case OP_ADD_IMM:
Expand Down
80 changes: 80 additions & 0 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -7844,6 +7844,86 @@ MONO_RESTORE_WARNING
values [ins->dreg] = LLVMConstAllOnes (type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass)));
break;
}
case OP_XCONST: {
MonoTypeEnum etype;
int ecount;

const char *class_name = m_class_get_name (ins->klass);

if (!strcmp(class_name, "Vector64`1") || !strcmp (class_name, "Vector128`1") || !strcmp (class_name, "Vector256`1") || !strcmp (class_name, "Vector512`1")) {
MonoType *element_type = mono_class_get_context (ins->klass)->class_inst->type_argv [0];
etype = element_type->type;
ecount = mono_class_value_size (ins->klass, NULL) / mono_class_value_size (mono_class_from_mono_type_internal(element_type), NULL);
} else if (!strcmp(class_name, "Vector4") || !strcmp(class_name, "Plane") || !strcmp(class_name, "Quaternion")) {
etype = MONO_TYPE_R4;
ecount = 4;
} else {
g_assert_not_reached ();
}

LLVMTypeRef llvm_type = primitive_type_to_llvm_type(etype);
LLVMValueRef vals [64];

switch (etype) {
case MONO_TYPE_I1:
case MONO_TYPE_U1: {
guint8* v = (guint8*)ins->inst_p0;

for (int i = 0; i < ecount; ++i) {
vals [i] = LLVMConstInt (llvm_type, v[i], FALSE);
}
break;
}
case MONO_TYPE_I2:
case MONO_TYPE_U2: {
guint16* v = (guint16*)ins->inst_p0;

for (int i = 0; i < ecount; ++i) {
vals [i] = LLVMConstInt (llvm_type, v[i], FALSE);
}
break;
}
case MONO_TYPE_I4:
case MONO_TYPE_U4: {
guint32* v = (guint32*)ins->inst_p0;

for (int i = 0; i < ecount; ++i) {
vals [i] = LLVMConstInt (llvm_type, v[i], FALSE);
}
break;
}
case MONO_TYPE_I8:
case MONO_TYPE_U8: {
guint64* v = (guint64*)ins->inst_p0;

for (int i = 0; i < ecount; ++i) {
vals [i] = LLVMConstInt (llvm_type, v[i], FALSE);
}
break;
}
case MONO_TYPE_R4: {
float* v = (float*)ins->inst_p0;

for (int i = 0; i < ecount; ++i) {
vals [i] = LLVMConstReal (llvm_type, v[i]);
}
break;
}
case MONO_TYPE_R8: {
double* v = (double*)ins->inst_p0;

for (int i = 0; i < ecount; ++i) {
vals [i] = LLVMConstReal (llvm_type, v[i]);
}
break;
}
default:
g_assert_not_reached ();
}

values [ins->dreg] = LLVMConstVector (vals, ecount);
break;
}
case OP_LOADX_MEMBASE: {
LLVMTypeRef t = type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass));
LLVMValueRef src;
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/mini-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,7 @@ MINI_OP(OP_CREATE_SCALAR, "create_scalar", XREG, XREG, NONE)
MINI_OP(OP_XMOVE, "xmove", XREG, XREG, NONE)
MINI_OP(OP_XZERO, "xzero", XREG, NONE, NONE)
MINI_OP(OP_XONES, "xones", XREG, NONE, NONE)
MINI_OP(OP_XCONST, "xconst", XREG, NONE, NONE)
MINI_OP(OP_XPHI, "xphi", XREG, NONE, NONE)

/*
Expand Down
180 changes: 141 additions & 39 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,49 @@ emit_xones (MonoCompile *cfg, MonoClass *klass)
return emit_simd_ins (cfg, klass, OP_XONES, -1, -1);
}

static MonoInst*
emit_xconst_v128 (MonoCompile *cfg, MonoClass *klass, guint8 value[16])
{
const int size = 16;

gboolean all_zeros = TRUE;

for (int i = 0; i < size; ++i) {
if (value[i] != 0x00) {
all_zeros = FALSE;
break;
}
}

if (all_zeros) {
return emit_xzero (cfg, klass);
}

gboolean all_ones = TRUE;

for (int i = 0; i < size; ++i) {
if (value[i] != 0xFF) {
all_ones = FALSE;
break;
}
}

if (all_ones) {
return emit_xones (cfg, klass);
}

MonoInst *ins;

MONO_INST_NEW (cfg, ins, OP_XCONST);
ins->type = STACK_VTYPE;
ins->dreg = alloc_xreg (cfg);
ins->inst_p0 = mono_mem_manager_alloc (cfg->mem_manager, size);
MONO_ADD_INS (cfg->cbb, ins);

memcpy (ins->inst_p0, &value[0], size);
return ins;
}

#ifdef TARGET_ARM64
static int type_to_extract_op (MonoTypeEnum type);
static MonoType* get_vector_t_elem_type (MonoType *vector_type);
Expand Down Expand Up @@ -2000,25 +2043,46 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
}
case SN_get_Zero:
return emit_xzero (cfg, klass);
case SN_get_UnitX: {
float value[4];
value [0] = 1.0f;
value [1] = 0.0f;
value [2] = 0.0f;
value [3] = 0.0f;
return emit_xconst_v128 (cfg, klass, (guint8*)value);
}
case SN_get_UnitY: {
float value[4];
value [0] = 0.0f;
value [1] = 1.0f;
value [2] = 0.0f;
value [3] = 0.0f;
return emit_xconst_v128 (cfg, klass, (guint8*)value);
}
case SN_get_UnitZ: {
float value[4];
value [0] = 0.0f;
value [1] = 0.0f;
value [2] = 1.0f;
value [3] = 0.0f;
return emit_xconst_v128 (cfg, klass, (guint8*)value);
}
case SN_get_Identity:
case SN_get_UnitX:
case SN_get_UnitY:
case SN_get_UnitZ:
case SN_get_UnitW: {
// FIXME:
return NULL;
float value[4];
value [0] = 0.0f;
value [1] = 0.0f;
value [2] = 0.0f;
value [3] = 1.0f;
return emit_xconst_v128 (cfg, klass, (guint8*)value);
}
case SN_get_One: {
static const float r4_one = 1.0f;

MonoInst *one = NULL;
MONO_INST_NEW (cfg, one, OP_R4CONST);
one->type = STACK_R4;
one->inst_p0 = (void *)&r4_one;
one->dreg = alloc_dreg (cfg, (MonoStackType)one->type);
MONO_ADD_INS (cfg->cbb, one);

return emit_simd_ins (cfg, klass, OP_EXPAND_R4, one->dreg, -1);
float value[4];
value [0] = 1.0f;
value [1] = 1.0f;
value [2] = 1.0f;
value [3] = 1.0f;
return emit_xconst_v128 (cfg, klass, (guint8*)value);
}
case SN_set_Item: {
// WithElement is marked as Intrinsic, but handling this in set_Item leads to better code
Expand Down Expand Up @@ -2251,9 +2315,6 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
int size, len, id;
gboolean is_unsigned;

static const float r4_one = 1.0f;
static const double r8_one = 1.0;

id = lookup_intrins (vector_t_methods, sizeof (vector_t_methods), cmethod);
if (id == -1) {
//check_no_intrinsic_cattr (cmethod);
Expand Down Expand Up @@ -2293,29 +2354,70 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
return emit_xzero (cfg, klass);
case SN_get_One: {
g_assert (fsig->param_count == 0 && mono_metadata_type_equal (fsig->ret, type));
MonoInst *one = NULL;
int expand_opcode = type_to_expand_op (etype);
MONO_INST_NEW (cfg, one, -1);
switch (expand_opcode) {
case OP_EXPAND_R4:
one->opcode = OP_R4CONST;
one->type = STACK_R4;
one->inst_p0 = (void *) &r4_one;
break;
case OP_EXPAND_R8:
one->opcode = OP_R8CONST;
one->type = STACK_R8;
one->inst_p0 = (void *) &r8_one;
break;
g_assert (register_size == 16);

switch (etype->type) {
case MONO_TYPE_I1:
case MONO_TYPE_U1: {
guint8 value[16];

for (int i = 0; i < len; ++i) {
value [i] = 1;
}

return emit_xconst_v128 (cfg, klass, value);
}
case MONO_TYPE_I2:
case MONO_TYPE_U2: {
guint16 value[8];

for (int i = 0; i < len; ++i) {
value [i] = 1;
}

return emit_xconst_v128 (cfg, klass, (guint8*)value);
}
case MONO_TYPE_I4:
case MONO_TYPE_U4: {
guint32 value[4];

for (int i = 0; i < len; ++i) {
value [i] = 1;
}

return emit_xconst_v128 (cfg, klass, (guint8*)value);
}
case MONO_TYPE_I8:
case MONO_TYPE_U8: {
guint64 value[2];

for (int i = 0; i < len; ++i) {
value [i] = 1;
}

return emit_xconst_v128 (cfg, klass, (guint8*)value);
}
case MONO_TYPE_R4: {
float value[4];

for (int i = 0; i < len; ++i) {
value [i] = 1.0f;
}

return emit_xconst_v128 (cfg, klass, (guint8*)value);
}
case MONO_TYPE_R8: {
double value[2];

for (int i = 0; i < len; ++i) {
value [i] = 1.0;
}

return emit_xconst_v128 (cfg, klass, (guint8*)value);
}
default:
one->opcode = OP_ICONST;
one->type = STACK_I4;
one->inst_c0 = 1;
break;
g_assert_not_reached ();
}
one->dreg = alloc_dreg (cfg, (MonoStackType)one->type);
MONO_ADD_INS (cfg->cbb, one);
return emit_simd_ins (cfg, klass, expand_opcode, one->dreg, -1);
}
case SN_get_AllBitsSet: {
return emit_xones (cfg, klass);
Expand Down

0 comments on commit f3f0340

Please sign in to comment.