From: Vlad Brezae Date: Thu, 24 Oct 2019 15:05:04 +0000 (+0300) Subject: [interp] Add super instructions for field storing (mono/mono#17525) X-Git-Tag: submit/tizen/20210909.063632~10331^2~5^2~295 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=53929d630f0e6b55be049e914dfb886f1ef3a385;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [interp] Add super instructions for field storing (mono/mono#17525) * [interp] Add also floating versions for stloc.np * [interp] Add super instructions for stfld When storing into a field of a local or an argument (ldloc/ldarg -> random instructions that end up pushing one value -> stfld). We add this instruction to the cprop pass because the instructions that are optimized together are not consecutive and we need the stack information to be able to access the instruction that loaded the argument / local and to make sure that the local wasn't dirtied. Alternatively we could make the super instruction pass stack aware, which we should probably do if more super instruction candidates turn out to require stack state information. * [interp] Enable cprop for methods without locals We do some optimizations here that don't apply to locals. * [interp] Fix result stack type of CEE_CONV_OVF_I_UN Commit migrated from https://github.com/mono/mono/commit/b7ef7363382757c2951a7a84026d5a1baa7f0130 --- diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 6b37efd..95c4447 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -5096,6 +5096,56 @@ common_vcall: sp -= 2; MINT_IN_BREAK; +#define STARGFLD(datamem, fieldtype) do { \ + MonoObject *o = frame->stack_args [ip [1]].data.o; \ + NULL_CHECK (o); \ + sp--; \ + * (fieldtype *)((char *)o + ip [2]) = sp [0].data.datamem; \ + ip += 3; \ +} while (0) + MINT_IN_CASE(MINT_STARGFLD_I1) STARGFLD(i, gint8); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STARGFLD_U1) STARGFLD(i, guint8); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STARGFLD_I2) STARGFLD(i, gint16); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STARGFLD_U2) STARGFLD(i, guint16); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STARGFLD_I4) STARGFLD(i, gint32); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STARGFLD_I8) STARGFLD(l, gint64); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STARGFLD_R4) STARGFLD(f_r4, float); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STARGFLD_R8) STARGFLD(f, double); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STARGFLD_P) STARGFLD(p, gpointer); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STARGFLD_O) { + MonoObject *o = frame->stack_args [ip [1]].data.o; + NULL_CHECK (o); + sp--; + mono_gc_wbarrier_set_field_internal (o, (char *) o + ip [2], sp [0].data.o); + ip += 3; + MINT_IN_BREAK; + } + +#define STLOCFLD(datamem, fieldtype) do { \ + MonoObject *o = *(MonoObject**)(locals + ip [1]); \ + NULL_CHECK (o); \ + sp--; \ + * (fieldtype *)((char *)o + ip [2]) = sp [0].data.datamem; \ + ip += 3; \ +} while (0) + MINT_IN_CASE(MINT_STLOCFLD_I1) STLOCFLD(i, gint8); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOCFLD_U1) STLOCFLD(i, guint8); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOCFLD_I2) STLOCFLD(i, gint16); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOCFLD_U2) STLOCFLD(i, guint16); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOCFLD_I4) STLOCFLD(i, gint32); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOCFLD_I8) STLOCFLD(l, gint64); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOCFLD_R4) STLOCFLD(f_r4, float); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOCFLD_R8) STLOCFLD(f, double); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOCFLD_P) STLOCFLD(p, gpointer); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOCFLD_O) { + MonoObject *o = *(MonoObject**)(locals + ip [1]); + NULL_CHECK (o); + sp--; + mono_gc_wbarrier_set_field_internal (o, (char *) o + ip [2], sp [0].data.o); + ip += 3; + MINT_IN_BREAK; + } + MINT_IN_CASE(MINT_LDSFLDA) { MonoVTable *vtable = (MonoVTable*) frame->imethod->data_items [ip [1]]; INIT_VTABLE (vtable); @@ -6415,6 +6465,8 @@ common_vcall: MINT_IN_CASE(MINT_STLOC_NP_I4) STLOC_NP(i, gint32); MINT_IN_BREAK; MINT_IN_CASE(MINT_STLOC_NP_I8) STLOC_NP(l, gint64); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOC_NP_R4) STLOC_NP(f_r4, float); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STLOC_NP_R8) STLOC_NP(f, double); MINT_IN_BREAK; MINT_IN_CASE(MINT_STLOC_NP_O) STLOC_NP(p, gpointer); MINT_IN_BREAK; MINT_IN_CASE(MINT_STLOC_VT) { diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 81a01d8..ef83487 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -133,6 +133,28 @@ OPDEF(MINT_STFLD_R8_UNALIGNED, "stfld.r8.unaligned", 2, Pop2, Push0, MintOpUShor OPDEF(MINT_STRMFLD, "strmfld", 2, Pop2, Push0, MintOpFieldToken) OPDEF(MINT_STRMFLD_VT, "strmfld.vt", 2, Pop2, Push0, MintOpUShortInt) +OPDEF(MINT_STARGFLD_I1, "stargfld.i1", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STARGFLD_U1, "stargfld.u1", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STARGFLD_I2, "stargfld.i2", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STARGFLD_U2, "stargfld.u2", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STARGFLD_I4, "stargfld.i4", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STARGFLD_I8, "stargfld.i8", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STARGFLD_R4, "stargfld.r4", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STARGFLD_R8, "stargfld.r8", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STARGFLD_O, "stargfld.o", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STARGFLD_P, "stargfld.p", 3, Pop1, Push0, MintOpTwoShorts) + +OPDEF(MINT_STLOCFLD_I1, "stlocfld.i1", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STLOCFLD_U1, "stlocfld.u1", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STLOCFLD_I2, "stlocfld.i2", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STLOCFLD_U2, "stlocfld.u2", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STLOCFLD_I4, "stlocfld.i4", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STLOCFLD_I8, "stlocfld.i8", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STLOCFLD_R4, "stlocfld.r4", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STLOCFLD_R8, "stlocfld.r8", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STLOCFLD_O, "stlocfld.o", 3, Pop1, Push0, MintOpTwoShorts) +OPDEF(MINT_STLOCFLD_P, "stlocfld.p", 3, Pop1, Push0, MintOpTwoShorts) + OPDEF(MINT_LDTSFLD_I1, "ldtsfld.i1", 3, Pop0, Push1, MintOpInt) OPDEF(MINT_LDTSFLD_U1, "ldtsfld.u1", 3, Pop0, Push1, MintOpInt) OPDEF(MINT_LDTSFLD_I2, "ldtsfld.i2", 3, Pop0, Push1, MintOpInt) @@ -210,6 +232,8 @@ OPDEF(MINT_STLOC_VT, "stloc.vt", 4, Pop1, Push0, MintOpShortAndInt) OPDEF(MINT_STLOC_NP_I4, "stloc.np.i4", 2, Pop0, Push0, MintOpUShortInt) OPDEF(MINT_STLOC_NP_I8, "stloc.np.i8", 2, Pop0, Push0, MintOpUShortInt) +OPDEF(MINT_STLOC_NP_R4, "stloc.np.R4", 2, Pop0, Push0, MintOpUShortInt) +OPDEF(MINT_STLOC_NP_R8, "stloc.np.R8", 2, Pop0, Push0, MintOpUShortInt) OPDEF(MINT_STLOC_NP_O, "stloc.np.o", 2, Pop0, Push0, MintOpUShortInt) OPDEF(MINT_MOVLOC_1, "movloc.1", 3, Pop0, Push0, MintOpTwoShorts) diff --git a/src/mono/mono/mini/interp/mintops.h b/src/mono/mono/mini/interp/mintops.h index 0afec36..69c4239 100644 --- a/src/mono/mono/mini/interp/mintops.h +++ b/src/mono/mono/mini/interp/mintops.h @@ -65,6 +65,7 @@ typedef enum { #define MINT_IS_UNOP(op) ((op) >= MINT_ADD1_I4 && (op) <= MINT_CEQ0_I4) #define MINT_IS_BINOP(op) ((op) >= MINT_ADD_I4 && (op) <= MINT_CLT_UN_R8) #define MINT_IS_LDLOCFLD(op) ((op) >= MINT_LDLOCFLD_I1 && (op) <= MINT_LDLOCFLD_P) +#define MINT_IS_STLOCFLD(op) ((op) >= MINT_STLOCFLD_I1 && (op) <= MINT_STLOCFLD_P) #define MINT_IS_LOCUNOP(op) ((op) >= MINT_LOCADD1_I4 && (op) <= MINT_LOCSUB1_I8) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 7779a1aa..3cc82d2 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -4916,7 +4916,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, g_assert_not_reached (); break; } - SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I8); + SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I); ++td->ip; break; case CEE_CONV_OVF_I8_UN: @@ -6399,7 +6399,7 @@ emit_compacted_instruction (TransformData *td, guint16* start_ip, InterpInst *in cbb->last_seq_point = seqp; } else { if (MINT_IS_LDLOC (opcode) || MINT_IS_STLOC (opcode) || MINT_IS_STLOC_NP (opcode) || opcode == MINT_LDLOCA_S || - MINT_IS_LDLOCFLD (opcode) || MINT_IS_LOCUNOP (opcode)) { + MINT_IS_LDLOCFLD (opcode) || MINT_IS_LOCUNOP (opcode) || MINT_IS_STLOCFLD (opcode)) { ins->data [0] = get_interp_local_offset (td, ins->data [0]); } else if (MINT_IS_MOVLOC (opcode)) { ins->data [0] = get_interp_local_offset (td, ins->data [0]); @@ -6791,7 +6791,7 @@ interp_local_equal (StackValue *locals, int local1, int local2) static void interp_cprop (TransformData *td) { - if (!td->max_stack_height || !td->locals_size) + if (!td->max_stack_height) return; StackContentInfo *stack = (StackContentInfo*) g_malloc (td->max_stack_height * sizeof (StackContentInfo)); StackContentInfo *stack_end = stack + td->max_stack_height; @@ -6839,6 +6839,10 @@ retry: replace_op = MINT_STLOC_NP_I4; else if (mt == MINT_TYPE_I8) replace_op = MINT_STLOC_NP_I8; + else if (mt == MINT_TYPE_R4) + replace_op = MINT_STLOC_NP_R4; + else if (mt == MINT_TYPE_R8) + replace_op = MINT_STLOC_NP_R8; else if (mt == MINT_TYPE_O || mt == MINT_TYPE_P) replace_op = MINT_STLOC_NP_O; if (replace_op) { @@ -7067,6 +7071,39 @@ retry: } else if (MINT_IS_BINOP (ins->opcode)) { ins = interp_fold_binop (td, sp, ins); sp--; + } else if (ins->opcode >= MINT_STFLD_I1 && ins->opcode <= MINT_STFLD_P && (mono_interp_opt & INTERP_OPT_SUPER_INSTRUCTIONS)) { + if (sp [-2].ins) { + InterpInst *obj_ins = sp [-2].ins; + if (obj_ins->opcode == MINT_LDLOC_O) { + int loc_index = obj_ins->data [0]; + int fld_offset = ins->data [0]; + int mt = ins->opcode - MINT_STFLD_I1; + ins = interp_insert_ins (td, ins, MINT_STLOCFLD_I1 + mt); + ins->data [0] = loc_index; + ins->data [1] = fld_offset; + interp_clear_ins (td, ins->prev); + interp_clear_ins (td, obj_ins); + mono_interp_stats.super_instructions++; + mono_interp_stats.killed_instructions++; + } else if (obj_ins->opcode == MINT_LDARG_O || obj_ins->opcode == MINT_LDARG_P0) { + int arg_index = 0; + int fld_offset = ins->data [0]; + int mt = ins->opcode - MINT_STFLD_I1; + if (obj_ins->opcode == MINT_LDARG_O) + arg_index = obj_ins->data [0]; + ins = interp_insert_ins (td, ins, MINT_STARGFLD_I1 + mt); + ins->data [0] = arg_index; + ins->data [1] = fld_offset; + interp_clear_ins (td, ins->prev); + interp_clear_ins (td, obj_ins); + mono_interp_stats.super_instructions++; + mono_interp_stats.killed_instructions++; + } + } + sp -= 2; + } else if (MINT_IS_STLOCFLD (ins->opcode)) { + local_ref_count [ins->data [0]]++; + sp--; } else { if (pop == MINT_POP_ALL) pop = sp - stack;