Skip to content

Commit 32b8723

Browse files
committed
[mono][interp] Add new ldind super instruction
These new instructions can apply addition and multiplication with constant to the offset var.
1 parent 3558b6d commit 32b8723

File tree

4 files changed

+84
-0
lines changed

4 files changed

+84
-0
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4910,6 +4910,41 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
49104910
#endif
49114911
MINT_IN_BREAK;
49124912

4913+
#define LDIND_OFFSET_ADD_MUL(datatype,casttype,unaligned) do { \
4914+
MONO_DISABLE_WARNING(4127) \
4915+
gpointer ptr = LOCAL_VAR (ip [2], gpointer); \
4916+
NULL_CHECK (ptr); \
4917+
ptr = (char*)ptr + (LOCAL_VAR (ip [3], mono_i) + (gint16)ip [4]) * (gint16)ip [5]; \
4918+
if (unaligned && ((gsize)ptr % SIZEOF_VOID_P)) \
4919+
memcpy (locals + ip [1], ptr, sizeof (datatype)); \
4920+
else \
4921+
LOCAL_VAR (ip [1], datatype) = *(casttype*)ptr; \
4922+
ip += 6; \
4923+
MONO_RESTORE_WARNING \
4924+
} while (0)
4925+
MINT_IN_CASE(MINT_LDIND_OFFSET_ADD_MUL_IMM_I1)
4926+
LDIND_OFFSET_ADD_MUL(gint32, gint8, FALSE);
4927+
MINT_IN_BREAK;
4928+
MINT_IN_CASE(MINT_LDIND_OFFSET_ADD_MUL_IMM_U1)
4929+
LDIND_OFFSET_ADD_MUL(gint32, guint8, FALSE);
4930+
MINT_IN_BREAK;
4931+
MINT_IN_CASE(MINT_LDIND_OFFSET_ADD_MUL_IMM_I2)
4932+
LDIND_OFFSET_ADD_MUL(gint32, gint16, FALSE);
4933+
MINT_IN_BREAK;
4934+
MINT_IN_CASE(MINT_LDIND_OFFSET_ADD_MUL_IMM_U2)
4935+
LDIND_OFFSET_ADD_MUL(gint32, guint16, FALSE);
4936+
MINT_IN_BREAK;
4937+
MINT_IN_CASE(MINT_LDIND_OFFSET_ADD_MUL_IMM_I4)
4938+
LDIND_OFFSET_ADD_MUL(gint32, gint32, FALSE);
4939+
MINT_IN_BREAK;
4940+
MINT_IN_CASE(MINT_LDIND_OFFSET_ADD_MUL_IMM_I8)
4941+
#ifdef NO_UNALIGNED_ACCESS
4942+
LDIND_OFFSET_ADD_MUL(gint64, gint64, TRUE);
4943+
#else
4944+
LDIND_OFFSET_ADD_MUL(gint64, gint64, FALSE);
4945+
#endif
4946+
MINT_IN_BREAK;
4947+
49134948
#define LDIND_OFFSET_IMM(datatype,casttype,unaligned) do { \
49144949
MONO_DISABLE_WARNING(4127) \
49154950
gpointer ptr = LOCAL_VAR (ip [2], gpointer); \

src/mono/mono/mini/interp/mintops.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ OPDEF(MINT_LDIND_OFFSET_IMM_U2, "ldind_off_imm.u2", 4, 1, 1, MintOpShortInt)
156156
OPDEF(MINT_LDIND_OFFSET_IMM_I4, "ldind_off_imm.i4", 4, 1, 1, MintOpShortInt)
157157
OPDEF(MINT_LDIND_OFFSET_IMM_I8, "ldind_off_imm.i8", 4, 1, 1, MintOpShortInt)
158158

159+
OPDEF(MINT_LDIND_OFFSET_ADD_MUL_IMM_I1, "ldind_off_add_mul_imm.i1", 6, 1, 2, MintOpTwoShorts)
160+
OPDEF(MINT_LDIND_OFFSET_ADD_MUL_IMM_U1, "ldind_off_add_mul_imm.u1", 6, 1, 2, MintOpTwoShorts)
161+
OPDEF(MINT_LDIND_OFFSET_ADD_MUL_IMM_I2, "ldind_off_add_mul_imm.i2", 6, 1, 2, MintOpTwoShorts)
162+
OPDEF(MINT_LDIND_OFFSET_ADD_MUL_IMM_U2, "ldind_off_add_mul_imm.u2", 6, 1, 2, MintOpTwoShorts)
163+
OPDEF(MINT_LDIND_OFFSET_ADD_MUL_IMM_I4, "ldind_off_add_mul_imm.i4", 6, 1, 2, MintOpTwoShorts)
164+
OPDEF(MINT_LDIND_OFFSET_ADD_MUL_IMM_I8, "ldind_off_add_mul_imm.i8", 6, 1, 2, MintOpTwoShorts)
165+
159166
OPDEF(MINT_STIND_I1, "stind.i1", 3, 0, 2, MintOpNoArgs)
160167
OPDEF(MINT_STIND_I2, "stind.i2", 3, 0, 2, MintOpNoArgs)
161168
OPDEF(MINT_STIND_I4, "stind.i4", 3, 0, 2, MintOpNoArgs)

src/mono/mono/mini/interp/mintops.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ typedef enum {
7979
#define MINT_IS_LDIND(op) ((op) >= MINT_LDIND_I1 && (op) <= MINT_LDIND_R8)
8080
#define MINT_IS_STIND_INT(op) ((op) >= MINT_STIND_I1 && (op) <= MINT_STIND_I8)
8181
#define MINT_IS_STIND(op) ((op) >= MINT_STIND_I1 && (op) <= MINT_STIND_REF)
82+
#define MINT_IS_LDIND_OFFSET(op) ((op) >= MINT_LDIND_OFFSET_I1 && (op) <= MINT_LDIND_OFFSET_I8)
8283

8384
// TODO Add more
8485
#define MINT_NO_SIDE_EFFECTS(op) (MINT_IS_MOV (op) || MINT_IS_LDC_I4 (op) || MINT_IS_LDC_I8 (op) || op == MINT_MONO_LDPTR)

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,17 @@ MonoInterpStats mono_interp_stats;
145145
#define MINT_STIND_I MINT_STIND_I8
146146
#define MINT_LDELEM_I MINT_LDELEM_I8
147147
#define MINT_STELEM_I MINT_STELEM_I8
148+
#define MINT_MUL_P_IMM MINT_MUL_I8_IMM
149+
#define MINT_ADD_MUL_P_IMM MINT_ADD_MUL_I8_IMM
148150
#else
149151
#define MINT_MOV_P MINT_MOV_4
150152
#define MINT_LDNULL MINT_LDC_I4_0
151153
#define MINT_LDIND_I MINT_LDIND_I4
152154
#define MINT_STIND_I MINT_STIND_I4
153155
#define MINT_LDELEM_I MINT_LDELEM_I4
154156
#define MINT_STELEM_I MINT_STELEM_I4
157+
#define MINT_MUL_P_IMM MINT_MUL_I4_IMM
158+
#define MINT_ADD_MUL_P_IMM MINT_ADD_MUL_I4_IMM
155159
#endif
156160

157161
static const char *stack_type_string [] = { "I4", "I8", "R4", "R8", "O ", "VT", "MP", "F " };
@@ -9654,6 +9658,43 @@ interp_super_instructions (TransformData *td)
96549658
}
96559659
}
96569660
}
9661+
} else if (MINT_IS_LDIND_OFFSET (opcode)) {
9662+
int sreg_off = ins->sregs [1];
9663+
InterpInst *def = td->locals [sreg_off].def;
9664+
if (def != NULL && td->local_ref_count [sreg_off] == 1) {
9665+
if (def->opcode == MINT_MUL_P_IMM || def->opcode == MINT_ADD_P_IMM || def->opcode == MINT_ADD_MUL_P_IMM) {
9666+
int ldind_offset_op = MINT_LDIND_OFFSET_ADD_MUL_IMM_I1 + (opcode - MINT_LDIND_OFFSET_I1);
9667+
InterpInst *new_inst = interp_insert_ins (td, ins, ldind_offset_op);
9668+
new_inst->dreg = ins->dreg;
9669+
new_inst->sregs [0] = ins->sregs [0]; // base
9670+
new_inst->sregs [1] = def->sregs [0]; // off
9671+
9672+
// set the add and mul immediates
9673+
switch (def->opcode) {
9674+
case MINT_ADD_P_IMM:
9675+
new_inst->data [0] = def->data [0];
9676+
new_inst->data [1] = 1;
9677+
break;
9678+
case MINT_MUL_P_IMM:
9679+
new_inst->data [0] = 0;
9680+
new_inst->data [1] = def->data [0];
9681+
break;
9682+
case MINT_ADD_MUL_P_IMM:
9683+
new_inst->data [0] = def->data [0];
9684+
new_inst->data [1] = def->data [1];
9685+
break;
9686+
}
9687+
9688+
interp_clear_ins (def);
9689+
interp_clear_ins (ins);
9690+
local_ref_count [sreg_off]--;
9691+
mono_interp_stats.super_instructions++;
9692+
if (td->verbose_level) {
9693+
g_print ("method %s:%s, superins: ", m_class_get_name (td->method->klass), td->method->name);
9694+
dump_interp_inst (new_inst);
9695+
}
9696+
}
9697+
}
96579698
} else if (MINT_IS_STIND_INT (opcode)) {
96589699
int sreg_base = ins->sregs [0];
96599700
InterpInst *def = td->locals [sreg_base].def;

0 commit comments

Comments
 (0)