Skip to content

Commit 11967d4

Browse files
authored
[interp] Don't cprop between vt vars of different sizes (#54734)
Via unsafe code, getting the lower Vector128 from a Vector256 ends up as a move of `sizeof (Vector128)` from a Vector256 var. However, the destination var is not a valid copy of the source var, having a different type
1 parent db143a0 commit 11967d4

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

src/mono/mono/mini/interp/transform.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8508,17 +8508,30 @@ interp_cprop (TransformData *td)
85088508
} else if (opcode == MINT_LDOBJ_VT) {
85098509
InterpInst *ldloca = local_defs [sregs [0]].ins;
85108510
if (ldloca != NULL && ldloca->opcode == MINT_LDLOCA_S) {
8511+
int ldsize = ins->data [0];
85118512
int local = ldloca->sregs [0];
8512-
// Replace LDLOCA + LDOBJ_VT with MOV_VT
8513-
ins->opcode = MINT_MOV_VT;
85148513
local_ref_count [sregs [0]]--;
8515-
sregs [0] = local;
85168514

8515+
if (ldsize == td->locals [local].size) {
8516+
// Replace LDLOCA + LDOBJ_VT with MOV_VT
8517+
ins->opcode = MINT_MOV_VT;
8518+
sregs [0] = local;
8519+
needs_retry = TRUE;
8520+
} else {
8521+
// This loads just a part of the local valuetype
8522+
ins = interp_insert_ins (td, ins, MINT_MOV_OFF);
8523+
interp_ins_set_dreg (ins, ins->prev->dreg);
8524+
interp_ins_set_sreg (ins, local);
8525+
ins->data [0] = 0;
8526+
ins->data [1] = MINT_TYPE_VT;
8527+
ins->data [2] = ldsize;
8528+
8529+
interp_clear_ins (ins->prev);
8530+
}
85178531
if (td->verbose_level) {
85188532
g_print ("Replace ldloca/ldobj_vt pair :\n\t");
85198533
dump_interp_inst (ins);
85208534
}
8521-
needs_retry = TRUE;
85228535
}
85238536
} else if (MINT_IS_STFLD (opcode) && ins->data [0] == 0) {
85248537
InterpInst *ldloca = local_defs [sregs [0]].ins;

0 commit comments

Comments
 (0)