Skip to content

Commit db5dfad

Browse files
Adding support to mono for v128 constants (#81902)
* Adding support to mono for v128 constants * Ensure that mini-amd64 can handle Vector128<T> constants * Have xconst "maximum instruction length" match r8const * Ensure the right data.target indices are written * Correctly handle the X128 patch point * Ensure MONO_TYPE_I and MONO_TYPE_U are handled * Ensure Vector`1 is handled
1 parent 8fbc863 commit db5dfad

12 files changed

Lines changed: 329 additions & 48 deletions

src/mono/mono/mini/aot-compiler.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7005,6 +7005,13 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
70057005
encode_value (((guint32 *)patch_info->data.target) [MINI_LS_WORD_IDX], p, &p);
70067006
encode_value (((guint32 *)patch_info->data.target) [MINI_MS_WORD_IDX], p, &p);
70077007
break;
7008+
case MONO_PATCH_INFO_X128:
7009+
case MONO_PATCH_INFO_X128_GOT:
7010+
encode_value (((guint32 *)patch_info->data.target) [(MINI_LS_WORD_IDX * 2) + MINI_LS_WORD_IDX], p, &p);
7011+
encode_value (((guint32 *)patch_info->data.target) [(MINI_LS_WORD_IDX * 2) + MINI_MS_WORD_IDX], p, &p);
7012+
encode_value (((guint32 *)patch_info->data.target) [(MINI_MS_WORD_IDX * 2) + MINI_LS_WORD_IDX], p, &p);
7013+
encode_value (((guint32 *)patch_info->data.target) [(MINI_MS_WORD_IDX * 2) + MINI_MS_WORD_IDX], p, &p);
7014+
break;
70087015
case MONO_PATCH_INFO_VTABLE:
70097016
case MONO_PATCH_INFO_CLASS:
70107017
case MONO_PATCH_INFO_IID:

src/mono/mono/mini/aot-runtime.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3842,6 +3842,26 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
38423842
*(double*)ji->data.target = *(double*)&v;
38433843
break;
38443844
}
3845+
case MONO_PATCH_INFO_X128:
3846+
case MONO_PATCH_INFO_X128_GOT: {
3847+
guint32 val [4];
3848+
guint64 v[2];
3849+
3850+
// FIXME: Align to 16 bytes ?
3851+
ji->data.target = mono_mem_manager_alloc0 (mem_manager, 16);
3852+
3853+
val [0] = decode_value (p, &p);
3854+
val [1] = decode_value (p, &p);
3855+
val [2] = decode_value (p, &p);
3856+
val [3] = decode_value (p, &p);
3857+
3858+
v[0] = ((guint64)val [1] << 32) | ((guint64)val [0]);
3859+
((guint64*)ji->data.target)[0] = v[0];
3860+
3861+
v[1] = ((guint64)val [3] << 32) | ((guint64)val [2]);
3862+
((guint64*)ji->data.target)[1] = v[1];
3863+
break;
3864+
}
38453865
case MONO_PATCH_INFO_LDSTR:
38463866
image = load_image (aot_module, decode_value (p, &p), error);
38473867
mono_error_cleanup (error); /* FIXME don't swallow the error */

src/mono/mono/mini/cfold.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,15 @@ mono_constant_fold_ins (MonoCompile *cfg, MonoInst *ins, MonoInst *arg1, MonoIns
300300
}
301301
break;
302302
case OP_XMOVE:
303-
if (arg1->opcode == OP_XZERO) {
303+
if ((arg1->opcode == OP_XZERO) || (arg1->opcode == OP_XONES)) {
304304
ALLOC_DEST (cfg, dest, ins);
305-
dest->opcode = OP_XZERO;
305+
dest->opcode = arg1->opcode;
306306
dest->sreg1 = -1;
307+
} else if (arg1->opcode == OP_XCONST) {
308+
ALLOC_DEST (cfg, dest, ins);
309+
dest->opcode = arg1->opcode;
310+
dest->sreg1 = -1;
311+
dest->inst_p0 = arg1->inst_p0;
307312
}
308313
break;
309314
case OP_COMPARE:

src/mono/mono/mini/cpu-amd64.mdesc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,7 @@ cvttps2dq: dest:x src1:x len:5 clob:1
769769
xmove: dest:x src1:x len:5
770770
xzero: dest:x len:5
771771
xones: dest:x len:5
772+
xconst: dest:x len:12
772773

773774
iconv_to_x: dest:x src1:i len:5
774775
extract_i4: dest:i src1:x len:5

src/mono/mono/mini/liveness.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ optimize_initlocals (MonoCompile *cfg)
678678
//printf ("DEAD: "); mono_print_ins (ins);
679679
if (cfg->disable_initlocals_opt_refs && var->type == STACK_OBJ)
680680
continue;
681-
if ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_R4CONST)) {
681+
if ((ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_R4CONST) || (ins->opcode == OP_XCONST)) {
682682
NULLIFY_INS (ins);
683683
MONO_VARINFO (cfg, var->inst_c0)->spill_costs -= 1;
684684
/*
@@ -874,7 +874,7 @@ update_liveness2 (MonoCompile *cfg, MonoInst *ins, gboolean set_volatile, int in
874874
}
875875
else {
876876
/* Try dead code elimination */
877-
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)) {
877+
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)) {
878878
LIVENESS_DEBUG (printf ("\tdead def of R%d, eliminated\n", ins->dreg));
879879
NULLIFY_INS (ins);
880880
return;

src/mono/mono/mini/method-to-ir.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12647,6 +12647,7 @@ mono_op_no_side_effects (int opcode)
1264712647
case OP_VZERO:
1264812648
case OP_XZERO:
1264912649
case OP_XONES:
12650+
case OP_XCONST:
1265012651
case OP_ICONST:
1265112652
case OP_I8CONST:
1265212653
case OP_ADD_IMM:

src/mono/mono/mini/mini-amd64.c

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7296,6 +7296,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
72967296
case OP_XONES:
72977297
amd64_sse_pcmpeqb_reg_reg (code, ins->dreg, ins->dreg);
72987298
break;
7299+
case OP_XCONST: {
7300+
if (cfg->compile_aot && cfg->code_exec_only) {
7301+
mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_X128_GOT, ins->inst_p0);
7302+
amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, sizeof(gpointer));
7303+
amd64_sse_movups_reg_membase (code, ins->dreg, AMD64_R11, 0);
7304+
} else {
7305+
mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_X128, ins->inst_p0);
7306+
amd64_sse_movups_reg_membase (code, ins->dreg, AMD64_RIP, 0);
7307+
}
7308+
break;
7309+
}
72997310
case OP_ICONV_TO_R4_RAW:
73007311
amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
73017312
if (!cfg->r4fp)
@@ -8140,11 +8151,13 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
81408151
for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
81418152
if (patch_info->type == MONO_PATCH_INFO_EXC)
81428153
code_size += 40;
8143-
if (patch_info->type == MONO_PATCH_INFO_R8)
8154+
else if (patch_info->type == MONO_PATCH_INFO_X128)
8155+
code_size += 16 + 15; /* sizeof (Vector128<T>) + alignment */
8156+
else if (patch_info->type == MONO_PATCH_INFO_R8)
81448157
code_size += 8 + 15; /* sizeof (double) + alignment */
8145-
if (patch_info->type == MONO_PATCH_INFO_R4)
8158+
else if (patch_info->type == MONO_PATCH_INFO_R4)
81468159
code_size += 4 + 15; /* sizeof (float) + alignment */
8147-
if (patch_info->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR)
8160+
else if (patch_info->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR)
81488161
code_size += 8 + 7; /*sizeof (void*) + alignment */
81498162
}
81508163

@@ -8218,6 +8231,10 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
82188231
guint8 *pos, *patch_pos;
82198232
guint32 target_pos;
82208233

8234+
// FIXME: R8 and R4 only need 8 and 4 byte alignment, respectively
8235+
// They should be handled separately with anything needing 16 byte
8236+
// alignment using X128
8237+
82218238
/* The SSE opcodes require a 16 byte alignment */
82228239
code = (guint8*)ALIGN_TO (code, 16);
82238240

@@ -8244,6 +8261,31 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
82448261
remove = TRUE;
82458262
break;
82468263
}
8264+
case MONO_PATCH_INFO_X128: {
8265+
guint8 *pos, *patch_pos;
8266+
guint32 target_pos;
8267+
8268+
/* The SSE opcodes require a 16 byte alignment */
8269+
code = (guint8*)ALIGN_TO (code, 16);
8270+
8271+
pos = cfg->native_code + patch_info->ip.i;
8272+
if (IS_REX (pos [0])) {
8273+
patch_pos = pos + 4;
8274+
target_pos = GPTRDIFF_TO_UINT32 (code - pos - 8);
8275+
}
8276+
else {
8277+
patch_pos = pos + 3;
8278+
target_pos = GPTRDIFF_TO_UINT32 (code - pos - 7);
8279+
}
8280+
8281+
memcpy (code, patch_info->data.target, 16);
8282+
code += 16;
8283+
8284+
*(guint32*)(patch_pos) = target_pos;
8285+
8286+
remove = TRUE;
8287+
break;
8288+
}
82478289
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR: {
82488290
guint8 *pos;
82498291

src/mono/mono/mini/mini-llvm.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7844,6 +7844,94 @@ MONO_RESTORE_WARNING
78447844
values [ins->dreg] = LLVMConstAllOnes (type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass)));
78457845
break;
78467846
}
7847+
case OP_XCONST: {
7848+
MonoTypeEnum etype;
7849+
int ecount;
7850+
7851+
const char *class_name = m_class_get_name (ins->klass);
7852+
7853+
if (!strcmp(class_name, "Vector`1") || !strcmp(class_name, "Vector64`1") || !strcmp (class_name, "Vector128`1") || !strcmp (class_name, "Vector256`1") || !strcmp (class_name, "Vector512`1")) {
7854+
MonoType *element_type = mono_class_get_context (ins->klass)->class_inst->type_argv [0];
7855+
etype = element_type->type;
7856+
ecount = mono_class_value_size (ins->klass, NULL) / mono_class_value_size (mono_class_from_mono_type_internal(element_type), NULL);
7857+
} else if (!strcmp(class_name, "Vector4") || !strcmp(class_name, "Plane") || !strcmp(class_name, "Quaternion")) {
7858+
etype = MONO_TYPE_R4;
7859+
ecount = 4;
7860+
} else {
7861+
g_assert_not_reached ();
7862+
}
7863+
7864+
LLVMTypeRef llvm_type = primitive_type_to_llvm_type(etype);
7865+
LLVMValueRef vals [64];
7866+
7867+
switch (etype) {
7868+
case MONO_TYPE_I1:
7869+
case MONO_TYPE_U1: {
7870+
guint8* v = (guint8*)ins->inst_p0;
7871+
7872+
for (int i = 0; i < ecount; ++i) {
7873+
vals [i] = LLVMConstInt (llvm_type, v[i], FALSE);
7874+
}
7875+
break;
7876+
}
7877+
case MONO_TYPE_I2:
7878+
case MONO_TYPE_U2: {
7879+
guint16* v = (guint16*)ins->inst_p0;
7880+
7881+
for (int i = 0; i < ecount; ++i) {
7882+
vals [i] = LLVMConstInt (llvm_type, v[i], FALSE);
7883+
}
7884+
break;
7885+
}
7886+
#if TARGET_SIZEOF_VOID_P == 4
7887+
case MONO_TYPE_I:
7888+
case MONO_TYPE_U:
7889+
#endif
7890+
case MONO_TYPE_I4:
7891+
case MONO_TYPE_U4: {
7892+
guint32* v = (guint32*)ins->inst_p0;
7893+
7894+
for (int i = 0; i < ecount; ++i) {
7895+
vals [i] = LLVMConstInt (llvm_type, v[i], FALSE);
7896+
}
7897+
break;
7898+
}
7899+
#if TARGET_SIZEOF_VOID_P == 8
7900+
case MONO_TYPE_I:
7901+
case MONO_TYPE_U:
7902+
#endif
7903+
case MONO_TYPE_I8:
7904+
case MONO_TYPE_U8: {
7905+
guint64* v = (guint64*)ins->inst_p0;
7906+
7907+
for (int i = 0; i < ecount; ++i) {
7908+
vals [i] = LLVMConstInt (llvm_type, v[i], FALSE);
7909+
}
7910+
break;
7911+
}
7912+
case MONO_TYPE_R4: {
7913+
float* v = (float*)ins->inst_p0;
7914+
7915+
for (int i = 0; i < ecount; ++i) {
7916+
vals [i] = LLVMConstReal (llvm_type, v[i]);
7917+
}
7918+
break;
7919+
}
7920+
case MONO_TYPE_R8: {
7921+
double* v = (double*)ins->inst_p0;
7922+
7923+
for (int i = 0; i < ecount; ++i) {
7924+
vals [i] = LLVMConstReal (llvm_type, v[i]);
7925+
}
7926+
break;
7927+
}
7928+
default:
7929+
g_assert_not_reached ();
7930+
}
7931+
7932+
values [ins->dreg] = LLVMConstVector (vals, ecount);
7933+
break;
7934+
}
78477935
case OP_LOADX_MEMBASE: {
78487936
LLVMTypeRef t = type_to_llvm_type (ctx, m_class_get_byval_arg (ins->klass));
78497937
LLVMValueRef src;

src/mono/mono/mini/mini-ops.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,7 @@ MINI_OP(OP_CREATE_SCALAR, "create_scalar", XREG, XREG, NONE)
11711171
MINI_OP(OP_XMOVE, "xmove", XREG, XREG, NONE)
11721172
MINI_OP(OP_XZERO, "xzero", XREG, NONE, NONE)
11731173
MINI_OP(OP_XONES, "xones", XREG, NONE, NONE)
1174+
MINI_OP(OP_XCONST, "xconst", XREG, NONE, NONE)
11741175
MINI_OP(OP_XPHI, "xphi", XREG, NONE, NONE)
11751176

11761177
/*

src/mono/mono/mini/mini-runtime.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,8 @@ mono_patch_info_hash (gconstpointer data)
12811281
}
12821282
case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
12831283
return hash | mono_signature_hash (ji->data.sig);
1284+
case MONO_PATCH_INFO_X128_GOT:
1285+
return hash | (guint32)*(double*)ji->data.target;
12841286
case MONO_PATCH_INFO_R8_GOT:
12851287
return hash | (guint32)*(double*)ji->data.target;
12861288
case MONO_PATCH_INFO_R4_GOT:
@@ -1605,6 +1607,8 @@ mono_resolve_patch_target_ext (MonoMemoryManager *mem_manager, MonoMethod *metho
16051607
case MONO_PATCH_INFO_R4_GOT:
16061608
case MONO_PATCH_INFO_R8:
16071609
case MONO_PATCH_INFO_R8_GOT:
1610+
case MONO_PATCH_INFO_X128:
1611+
case MONO_PATCH_INFO_X128_GOT:
16081612
target = patch_info->data.target;
16091613
break;
16101614
case MONO_PATCH_INFO_EXC_NAME:

0 commit comments

Comments
 (0)