Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitefd3410

Browse files
authored
[interp] Optimize conditional branches (#52130)
* [interp] Try emitting ldc_0 instead of initlocal if possibleUnlike initlocal ldc_0 are propagated, also having smaller instruction footprint. Signal retry of cprop when we are adding such instructions, also in other cases. We could dynamically update the state, but let's not overcomplicate the cprop pass, for now.* [interp] Also update def_index when swapping dreg* [interp] Refactor special static field accessOn netcore, there are no context static fields so all special static fields are thread static. These thread static accessors are not very common, so just remove redundant opcodes for them, and use ldind/ldobj.vt and stind/stobj.vt instead.* [interp] Remove MINT_LDFLD_VT_* opcodesThese opcodes were used for loading a field of a VT var. This means the opcodes were loading a value from an immediate offset added to a var offset. We can use the standard MINT_MOV opcodes for this, however we need to resolve the offsets at the very end, so it doesn't interfere with other compilation passes, since the final offset is not the real offset of a variable, but rather an offset inside a VT var.* [interp] Remove MINT_CHECKPOINT opcodeIt was used to check for abort requests during backward branches. Also stop checking for abort requests in other places.* [interp] Add super instructions for conditional branchesWe include the safepoint in the instruction and also the immediate comparison value if possible. Doing the safepoint by default in branching opcodes is questionable since, in a typical program, forward branches are far more common than backward branches.We should really remove many of the branching opcodes. We now have the possibility to swap the src vars order, and use the opposite comparison instead.
1 parent9136bce commitefd3410

File tree

4 files changed

+376
-233
lines changed

4 files changed

+376
-233
lines changed

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

Lines changed: 98 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,22 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con
10501050
}\
10511051
} while (0)
10521052

1053+
// Reduce duplicate code in interp_exec_method
1054+
staticvoid
1055+
do_safepoint (InterpFrame*frame,ThreadContext*context)
1056+
{
1057+
context_set_safepoint_frame (context,frame);
1058+
/* Poll safepoint */
1059+
mono_threads_safepoint ();
1060+
context_clear_safepoint_frame (context);
1061+
}
1062+
1063+
#defineSAFEPOINT \
1064+
do {\
1065+
if (G_UNLIKELY (mono_polling_required)) \
1066+
do_safepoint (frame, context);\
1067+
} while (0)
1068+
10531069
staticMonoObject*
10541070
ves_array_create (MonoClass*klass,intparam_count,stackval*values,MonoError*error)
10551071
{
@@ -4164,6 +4180,79 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
41644180
CONDBR(mono_isunordered (d1,d2)||d1<d2)
41654181
MINT_IN_BREAK;
41664182
}
4183+
4184+
#defineZEROP_SP(datatype,op) \
4185+
if (LOCAL_VAR (ip [1],datatype)op0) { \
4186+
gint16br_offset= (gint16)ip [2]; \
4187+
BACK_BRANCH_PROFILE (br_offset); \
4188+
SAFEPOINT; \
4189+
ip+=br_offset; \
4190+
}else \
4191+
ip+=3;
4192+
4193+
MINT_IN_CASE(MINT_BRFALSE_I4_SP)ZEROP_SP(gint32,==);MINT_IN_BREAK;
4194+
MINT_IN_CASE(MINT_BRFALSE_I8_SP)ZEROP_SP(gint64,==);MINT_IN_BREAK;
4195+
MINT_IN_CASE(MINT_BRTRUE_I4_SP)ZEROP_SP(gint32, !=);MINT_IN_BREAK;
4196+
MINT_IN_CASE(MINT_BRTRUE_I8_SP)ZEROP_SP(gint64, !=);MINT_IN_BREAK;
4197+
4198+
#defineCONDBR_SP(cond) \
4199+
if (cond) { \
4200+
gint16br_offset= (gint16)ip [3]; \
4201+
BACK_BRANCH_PROFILE (br_offset); \
4202+
SAFEPOINT; \
4203+
ip+=br_offset; \
4204+
}else \
4205+
ip+=4;
4206+
#defineBRELOP_SP(datatype,op) \
4207+
CONDBR_SP(LOCAL_VAR (ip [1],datatype)opLOCAL_VAR (ip [2],datatype))
4208+
4209+
MINT_IN_CASE(MINT_BEQ_I4_SP)BRELOP_SP(gint32,==);MINT_IN_BREAK;
4210+
MINT_IN_CASE(MINT_BEQ_I8_SP)BRELOP_SP(gint64,==);MINT_IN_BREAK;
4211+
MINT_IN_CASE(MINT_BGE_I4_SP)BRELOP_SP(gint32, >=);MINT_IN_BREAK;
4212+
MINT_IN_CASE(MINT_BGE_I8_SP)BRELOP_SP(gint64, >=);MINT_IN_BREAK;
4213+
MINT_IN_CASE(MINT_BGT_I4_SP)BRELOP_SP(gint32,>);MINT_IN_BREAK;
4214+
MINT_IN_CASE(MINT_BGT_I8_SP)BRELOP_SP(gint64,>);MINT_IN_BREAK;
4215+
MINT_IN_CASE(MINT_BLT_I4_SP)BRELOP_SP(gint32,<);MINT_IN_BREAK;
4216+
MINT_IN_CASE(MINT_BLT_I8_SP)BRELOP_SP(gint64,<);MINT_IN_BREAK;
4217+
MINT_IN_CASE(MINT_BLE_I4_SP)BRELOP_SP(gint32, <=);MINT_IN_BREAK;
4218+
MINT_IN_CASE(MINT_BLE_I8_SP)BRELOP_SP(gint64, <=);MINT_IN_BREAK;
4219+
4220+
MINT_IN_CASE(MINT_BNE_UN_I4_SP)BRELOP_SP(guint32, !=);MINT_IN_BREAK;
4221+
MINT_IN_CASE(MINT_BNE_UN_I8_SP)BRELOP_SP(guint64, !=);MINT_IN_BREAK;
4222+
MINT_IN_CASE(MINT_BGE_UN_I4_SP)BRELOP_SP(guint32, >=);MINT_IN_BREAK;
4223+
MINT_IN_CASE(MINT_BGE_UN_I8_SP)BRELOP_SP(guint64, >=);MINT_IN_BREAK;
4224+
MINT_IN_CASE(MINT_BGT_UN_I4_SP)BRELOP_SP(guint32,>);MINT_IN_BREAK;
4225+
MINT_IN_CASE(MINT_BGT_UN_I8_SP)BRELOP_SP(guint64,>);MINT_IN_BREAK;
4226+
MINT_IN_CASE(MINT_BLE_UN_I4_SP)BRELOP_SP(guint32, <=);MINT_IN_BREAK;
4227+
MINT_IN_CASE(MINT_BLE_UN_I8_SP)BRELOP_SP(guint64, <=);MINT_IN_BREAK;
4228+
MINT_IN_CASE(MINT_BLT_UN_I4_SP)BRELOP_SP(guint32,<);MINT_IN_BREAK;
4229+
MINT_IN_CASE(MINT_BLT_UN_I8_SP)BRELOP_SP(guint64,<);MINT_IN_BREAK;
4230+
4231+
#defineBRELOP_IMM_SP(datatype,op) \
4232+
CONDBR_SP(LOCAL_VAR (ip [1],datatype)op (datatype)(gint16)ip [2])
4233+
4234+
MINT_IN_CASE(MINT_BEQ_I4_IMM_SP)BRELOP_IMM_SP(gint32,==);MINT_IN_BREAK;
4235+
MINT_IN_CASE(MINT_BEQ_I8_IMM_SP)BRELOP_IMM_SP(gint64,==);MINT_IN_BREAK;
4236+
MINT_IN_CASE(MINT_BGE_I4_IMM_SP)BRELOP_IMM_SP(gint32, >=);MINT_IN_BREAK;
4237+
MINT_IN_CASE(MINT_BGE_I8_IMM_SP)BRELOP_IMM_SP(gint64, >=);MINT_IN_BREAK;
4238+
MINT_IN_CASE(MINT_BGT_I4_IMM_SP)BRELOP_IMM_SP(gint32,>);MINT_IN_BREAK;
4239+
MINT_IN_CASE(MINT_BGT_I8_IMM_SP)BRELOP_IMM_SP(gint64,>);MINT_IN_BREAK;
4240+
MINT_IN_CASE(MINT_BLT_I4_IMM_SP)BRELOP_IMM_SP(gint32,<);MINT_IN_BREAK;
4241+
MINT_IN_CASE(MINT_BLT_I8_IMM_SP)BRELOP_IMM_SP(gint64,<);MINT_IN_BREAK;
4242+
MINT_IN_CASE(MINT_BLE_I4_IMM_SP)BRELOP_IMM_SP(gint32, <=);MINT_IN_BREAK;
4243+
MINT_IN_CASE(MINT_BLE_I8_IMM_SP)BRELOP_IMM_SP(gint64, <=);MINT_IN_BREAK;
4244+
4245+
MINT_IN_CASE(MINT_BNE_UN_I4_IMM_SP)BRELOP_IMM_SP(guint32, !=);MINT_IN_BREAK;
4246+
MINT_IN_CASE(MINT_BNE_UN_I8_IMM_SP)BRELOP_IMM_SP(guint64, !=);MINT_IN_BREAK;
4247+
MINT_IN_CASE(MINT_BGE_UN_I4_IMM_SP)BRELOP_IMM_SP(guint32, >=);MINT_IN_BREAK;
4248+
MINT_IN_CASE(MINT_BGE_UN_I8_IMM_SP)BRELOP_IMM_SP(guint64, >=);MINT_IN_BREAK;
4249+
MINT_IN_CASE(MINT_BGT_UN_I4_IMM_SP)BRELOP_IMM_SP(guint32,>);MINT_IN_BREAK;
4250+
MINT_IN_CASE(MINT_BGT_UN_I8_IMM_SP)BRELOP_IMM_SP(guint64,>);MINT_IN_BREAK;
4251+
MINT_IN_CASE(MINT_BLE_UN_I4_IMM_SP)BRELOP_IMM_SP(guint32, <=);MINT_IN_BREAK;
4252+
MINT_IN_CASE(MINT_BLE_UN_I8_IMM_SP)BRELOP_IMM_SP(guint64, <=);MINT_IN_BREAK;
4253+
MINT_IN_CASE(MINT_BLT_UN_I4_IMM_SP)BRELOP_IMM_SP(guint32,<);MINT_IN_BREAK;
4254+
MINT_IN_CASE(MINT_BLT_UN_I8_IMM_SP)BRELOP_IMM_SP(guint64,<);MINT_IN_BREAK;
4255+
41674256
MINT_IN_CASE(MINT_SWITCH) {
41684257
guint32val=LOCAL_VAR (ip [1],guint32);
41694258
guint32n=READ32 (ip+2);
@@ -5117,20 +5206,8 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
51175206
THROW_EX (ex,ip);
51185207
MINT_IN_BREAK;
51195208
}
5120-
MINT_IN_CASE(MINT_CHECKPOINT)
5121-
/* Do synchronous checking of abort requests */
5122-
EXCEPTION_CHECKPOINT;
5123-
++ip;
5124-
MINT_IN_BREAK;
51255209
MINT_IN_CASE(MINT_SAFEPOINT)
5126-
/* Do synchronous checking of abort requests */
5127-
EXCEPTION_CHECKPOINT;
5128-
if (G_UNLIKELY (mono_polling_required)) {
5129-
context_set_safepoint_frame (context,frame);
5130-
/* Poll safepoint */
5131-
mono_threads_safepoint ();
5132-
context_clear_safepoint_frame (context);
5133-
}
5210+
SAFEPOINT;
51345211
++ip;
51355212
MINT_IN_BREAK;
51365213
MINT_IN_CASE(MINT_LDFLDA_UNSAFE) {
@@ -5153,35 +5230,6 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
51535230
MINT_IN_BREAK;
51545231
}
51555232

5156-
// FIXME squash to load directly field type, LDFLD_VT is just a LDLOC
5157-
#defineLDFLD_VT_UNALIGNED(datatype,fieldtype,unaligned)do { \
5158-
if (unaligned) \
5159-
memcpy (locals+ip [1], (char*)locals+ip [2]+ip [3],sizeof (fieldtype)); \
5160-
else \
5161-
LOCAL_VAR (ip [1],datatype)=LOCAL_VAR (ip [2]+ip [3],fieldtype); \
5162-
ip+=4; \
5163-
}while (0)
5164-
5165-
#defineLDFLD_VT(datatype,fieldtype)LDFLD_VT_UNALIGNED(datatype,fieldtype,FALSE)
5166-
5167-
MINT_IN_CASE(MINT_LDFLD_VT_I1)LDFLD_VT(gint32,gint8);MINT_IN_BREAK;
5168-
MINT_IN_CASE(MINT_LDFLD_VT_U1)LDFLD_VT(gint32,guint8);MINT_IN_BREAK;
5169-
MINT_IN_CASE(MINT_LDFLD_VT_I2)LDFLD_VT(gint32,gint16);MINT_IN_BREAK;
5170-
MINT_IN_CASE(MINT_LDFLD_VT_U2)LDFLD_VT(gint32,guint16);MINT_IN_BREAK;
5171-
MINT_IN_CASE(MINT_LDFLD_VT_I4)LDFLD_VT(gint32,gint32);MINT_IN_BREAK;
5172-
MINT_IN_CASE(MINT_LDFLD_VT_I8)LDFLD_VT(gint64,gint64);MINT_IN_BREAK;
5173-
MINT_IN_CASE(MINT_LDFLD_VT_R4)LDFLD_VT(float,float);MINT_IN_BREAK;
5174-
MINT_IN_CASE(MINT_LDFLD_VT_R8)LDFLD_VT(double,double);MINT_IN_BREAK;
5175-
MINT_IN_CASE(MINT_LDFLD_VT_O)LDFLD_VT(gpointer,gpointer);MINT_IN_BREAK;
5176-
MINT_IN_CASE(MINT_LDFLD_VT_I8_UNALIGNED)LDFLD_VT_UNALIGNED(gint64,gint64,TRUE);MINT_IN_BREAK;
5177-
MINT_IN_CASE(MINT_LDFLD_VT_R8_UNALIGNED)LDFLD_VT_UNALIGNED(double,double,TRUE);MINT_IN_BREAK;
5178-
5179-
MINT_IN_CASE(MINT_LDFLD_VT_VT) {
5180-
memmove (locals+ip [1],locals+ip [2]+ip [3],ip [4]);
5181-
ip+=5;
5182-
MINT_IN_BREAK;
5183-
}
5184-
51855233
#defineLDFLD_UNALIGNED(datatype,fieldtype,unaligned)do { \
51865234
MonoObject*o=LOCAL_VAR (ip [2],MonoObject*); \
51875235
NULL_CHECK (o); \
@@ -5269,9 +5317,10 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
52695317
MINT_IN_BREAK;
52705318
}
52715319

5272-
MINT_IN_CASE(MINT_LDSSFLDA) {
5273-
guint32offset=READ32(ip+2);
5274-
LOCAL_VAR (ip [1],gpointer)=mono_get_special_static_data (offset);
5320+
MINT_IN_CASE(MINT_LDTSFLDA) {
5321+
MonoInternalThread*thread=mono_thread_internal_current ();
5322+
guint32offset=READ32 (ip+2);
5323+
LOCAL_VAR (ip [1],gpointer)= ((char*)thread->static_data [offset&0x3f])+ (offset >>6);
52755324
ip+=4;
52765325
MINT_IN_BREAK;
52775326
}
@@ -5306,38 +5355,6 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
53065355
MINT_IN_BREAK;
53075356
}
53085357

5309-
#defineLDTSFLD(datatype,fieldtype) { \
5310-
MonoInternalThread*thread=mono_thread_internal_current (); \
5311-
guint32offset=READ32 (ip+2); \
5312-
gpointeraddr= ((char*)thread->static_data [offset&0x3f])+ (offset >>6); \
5313-
LOCAL_VAR (ip [1],datatype)=*(fieldtype*)addr; \
5314-
ip+=4; \
5315-
}
5316-
MINT_IN_CASE(MINT_LDTSFLD_I1)LDTSFLD(gint32,gint8);MINT_IN_BREAK;
5317-
MINT_IN_CASE(MINT_LDTSFLD_U1)LDTSFLD(gint32,guint8);MINT_IN_BREAK;
5318-
MINT_IN_CASE(MINT_LDTSFLD_I2)LDTSFLD(gint32,gint16);MINT_IN_BREAK;
5319-
MINT_IN_CASE(MINT_LDTSFLD_U2)LDTSFLD(gint32,guint16);MINT_IN_BREAK;
5320-
MINT_IN_CASE(MINT_LDTSFLD_I4)LDTSFLD(gint32,gint32);MINT_IN_BREAK;
5321-
MINT_IN_CASE(MINT_LDTSFLD_I8)LDTSFLD(gint64,gint64);MINT_IN_BREAK;
5322-
MINT_IN_CASE(MINT_LDTSFLD_R4)LDTSFLD(float,float);MINT_IN_BREAK;
5323-
MINT_IN_CASE(MINT_LDTSFLD_R8)LDTSFLD(double,double);MINT_IN_BREAK;
5324-
MINT_IN_CASE(MINT_LDTSFLD_O)LDTSFLD(gpointer,gpointer);MINT_IN_BREAK;
5325-
5326-
MINT_IN_CASE(MINT_LDSSFLD) {
5327-
guint32offset=READ32(ip+3);
5328-
gpointeraddr=mono_get_special_static_data (offset);
5329-
MonoClassField*field= (MonoClassField*)frame->imethod->data_items [ip [2]];
5330-
stackval_from_data (field->type, (stackval*)(locals+ip [1]),addr,FALSE);
5331-
ip+=5;
5332-
MINT_IN_BREAK;
5333-
}
5334-
MINT_IN_CASE(MINT_LDSSFLD_VT) {
5335-
guint32offset=READ32(ip+2);
5336-
gpointeraddr=mono_get_special_static_data (offset);
5337-
memcpy (locals+ip [1],addr,ip [4]);
5338-
ip+=5;
5339-
MINT_IN_BREAK;
5340-
}
53415358
#defineSTSFLD(datatype,fieldtype) { \
53425359
MonoVTable*vtable= (MonoVTable*)frame->imethod->data_items [ip [2]]; \
53435360
INIT_VTABLE (vtable); \
@@ -5364,40 +5381,6 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
53645381
MINT_IN_BREAK;
53655382
}
53665383

5367-
#defineSTTSFLD(datatype,fieldtype) { \
5368-
MonoInternalThread*thread=mono_thread_internal_current (); \
5369-
guint32offset=READ32 (ip+2); \
5370-
gpointeraddr= ((char*)thread->static_data [offset&0x3f])+ (offset >>6); \
5371-
*(fieldtype*)addr=LOCAL_VAR (ip [1],datatype); \
5372-
ip+=4; \
5373-
}
5374-
5375-
MINT_IN_CASE(MINT_STTSFLD_I1)STTSFLD(gint32,gint8);MINT_IN_BREAK;
5376-
MINT_IN_CASE(MINT_STTSFLD_U1)STTSFLD(gint32,guint8);MINT_IN_BREAK;
5377-
MINT_IN_CASE(MINT_STTSFLD_I2)STTSFLD(gint32,gint16);MINT_IN_BREAK;
5378-
MINT_IN_CASE(MINT_STTSFLD_U2)STTSFLD(gint32,guint16);MINT_IN_BREAK;
5379-
MINT_IN_CASE(MINT_STTSFLD_I4)STTSFLD(gint32,gint32);MINT_IN_BREAK;
5380-
MINT_IN_CASE(MINT_STTSFLD_I8)STTSFLD(gint64,gint64);MINT_IN_BREAK;
5381-
MINT_IN_CASE(MINT_STTSFLD_R4)STTSFLD(float,float);MINT_IN_BREAK;
5382-
MINT_IN_CASE(MINT_STTSFLD_R8)STTSFLD(double,double);MINT_IN_BREAK;
5383-
MINT_IN_CASE(MINT_STTSFLD_O)STTSFLD(gpointer,gpointer);MINT_IN_BREAK;
5384-
5385-
MINT_IN_CASE(MINT_STSSFLD) {
5386-
guint32offset=READ32(ip+3);
5387-
gpointeraddr=mono_get_special_static_data (offset);
5388-
MonoClassField*field= (MonoClassField*)frame->imethod->data_items [ip [2]];
5389-
stackval_to_data (field->type, (stackval*)(locals+ip [1]),addr,FALSE);
5390-
ip+=5;
5391-
MINT_IN_BREAK;
5392-
}
5393-
MINT_IN_CASE(MINT_STSSFLD_VT) {
5394-
guint32offset=READ32(ip+2);
5395-
gpointeraddr=mono_get_special_static_data (offset);
5396-
memcpy (addr,locals+ip [1],ip [4]);
5397-
ip+=5;
5398-
MINT_IN_BREAK;
5399-
}
5400-
54015384
MINT_IN_CASE(MINT_STOBJ_VT) {
54025385
MonoClass*c= (MonoClass*)frame->imethod->data_items [ip [3]];
54035386
mono_value_copy_internal (LOCAL_VAR (ip [1],gpointer),locals+ip [2],c);
@@ -6211,9 +6194,6 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
62116194

62126195
gbooleanconstshort_offset=opcode==MINT_LEAVE_S||opcode==MINT_LEAVE_S_CHECK;
62136196
ip+=short_offset ? (gint16)*(ip+1) : (gint32)READ32 (ip+1);
6214-
// Check for any abort requests, once all finally blocks were invoked
6215-
if (!check)
6216-
EXCEPTION_CHECKPOINT;
62176197
MINT_IN_BREAK;
62186198
}
62196199
MINT_IN_CASE(MINT_ICALL_V_V)
@@ -6569,6 +6549,10 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
65696549
ip+=3;
65706550
MINT_IN_BREAK;
65716551

6552+
MINT_IN_CASE(MINT_MOV_OFF)
6553+
// This opcode is resolved to a normal MINT_MOV when emitting compacted instructions
6554+
g_assert_not_reached ();
6555+
MINT_IN_BREAK;
65726556

65736557
#defineMOV(argtype1,argtype2) \
65746558
LOCAL_VAR (ip [1],argtype1)=LOCAL_VAR (ip [2],argtype2); \

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp