Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mono][interp] Add SSA transformation and SSA based optimization #96315

Merged
merged 45 commits into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
045be18
[mono][interp] Preliminary phases for SSA computation
BrzVlad Nov 6, 2023
37d98ea
[mono][interp] Insert phi nodes
BrzVlad Nov 6, 2023
909d2d9
[mono][interp] Implement renaming of vars
BrzVlad Nov 7, 2023
96e92f9
[mono][interp] Re-enable bblock optimizations
BrzVlad Nov 7, 2023
d7804e4
[mono][interp] Add liveness computation so we can generate pruned SSA
BrzVlad Nov 8, 2023
45dd009
[mono][interp] Reduce number of fixed ssa vars
BrzVlad Nov 8, 2023
00a772d
[mono][interp] Add more stats tracking compilation time
BrzVlad Nov 8, 2023
7366107
[mono][interp] Compute live end limit for fixed ssa vars
BrzVlad Nov 8, 2023
4104c95
[mono][interp] Ensure all vars have a definition
BrzVlad Nov 8, 2023
09b629f
[mono][interp] Resurrect cprop, cfold and some other small optimizations
BrzVlad Nov 8, 2023
d053d1c
[mono][interp] Bring back deadce
BrzVlad Nov 9, 2023
c210c2f
[mono][interp] Resurrect super instruction pass
BrzVlad Nov 9, 2023
ca9094b
[mono][interp] Redo bblock opt pass after other optimizations
BrzVlad Nov 9, 2023
5ab1755
[mono][interp] Re-enable MINT_INTRINS_MARVIN_BLOCK intrinsic
BrzVlad Nov 9, 2023
b5d3bdd
[mono][interp] Bring back reverse propagation of dreg
BrzVlad Nov 9, 2023
1eb1627
[mono][interp] Fix SSA form for vt field stores
BrzVlad Nov 10, 2023
c88eeae
[mono][interp] Redo optimizations if a var is no longer indirect
BrzVlad Nov 13, 2023
6004987
[mono][interp] Disable ssa optimizations for methods with bad cfg str…
BrzVlad Nov 22, 2023
0422ae5
[mono][interp] Scan also bblocks reachable from EH
BrzVlad Nov 22, 2023
5498668
[mono][interp] Mark vars used inside handlers so they are not transfo…
BrzVlad Nov 14, 2023
df43e38
[mono][interp] Bring back optimizations for variables that are not in…
BrzVlad Nov 27, 2023
b312bb8
[mono][interp] Proper support for ssa disabled
BrzVlad Nov 29, 2023
c30c8d5
[mono][interp] Enable cprop dreg optimization for no-ssa vars
BrzVlad Dec 1, 2023
c9d086f
[mono][interp] Fix handling of BBs with patchpoint data during optimi…
BrzVlad Dec 5, 2023
4ccb8be
[mono][interp] Fix diverging var offsets between tiered and untiered …
BrzVlad Dec 6, 2023
82e5124
[mono][interp] Retry instruction during cprop when replacing with MOV
BrzVlad Dec 13, 2023
0c576b8
[mono][interp] Rename get_local_offset to get_var_offset
BrzVlad Dec 13, 2023
5d47373
[mono][interp] Squash multiple INITLOCAL into single INITLOCALS
BrzVlad Dec 13, 2023
80e189b
[mono][interp] Fix cprop dreg with newobj
BrzVlad Dec 14, 2023
c34c1d9
[mono][interp] Fix u1 narrow simd intrinsic
BrzVlad Dec 20, 2023
ec7b3a2
[mono][interp] Attempt to remove bblocks from EH
BrzVlad Dec 20, 2023
cc660c4
[mono][interp] Remove bblock count limit for optimization support
BrzVlad Dec 21, 2023
3e2ee71
[mono][interp] Improve native offset estimation
BrzVlad Dec 25, 2023
10851ef
[mono][interp] Fix live limit bblocks computation for fixed ssa vars
BrzVlad Dec 23, 2023
0ab313b
[mono][interp] Reduce number of renamable vars
BrzVlad Dec 27, 2023
3fcf0db
[mono][interp] Remove MINT_NOPS after each round of optimizations
BrzVlad Dec 28, 2023
22b6444
[mono][interp] Optimize generation of MINT_DEAD_PHI
BrzVlad Dec 28, 2023
fcb91d0
[mono][interp] Disable SSA for first optimization iteration of huge m…
BrzVlad Dec 28, 2023
f462966
[mono][interp] Fix adding of super instructions
BrzVlad Jan 9, 2024
4f776d3
[mono][interp] Refactor dfs traversal to be iterative
BrzVlad Jan 9, 2024
ff8ef69
[mono][interp] Make rename vars pass non-recursive
BrzVlad Jan 10, 2024
ee0e148
[mono][interp] Make use of dfs_index in more places
BrzVlad Jan 10, 2024
0b9ad9e
[mono][interp] Don't run any optimizations if we have cprop disabled
BrzVlad Jan 11, 2024
67b089a
[mono][interp] Reduce max memory usage during interp compilation
BrzVlad Jan 12, 2024
ad70884
PR review
BrzVlad Jan 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions src/mono/browser/runtime/jiterpreter-trace-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1098,18 +1098,6 @@ export function generateWasmBody(
break;
}

case MintOpcode.MINT_NEWOBJ_VT_INLINED: {
const ret_size = getArgU16(ip, 3);
// memset (this_vt, 0, ret_size);
append_ldloca(builder, getArgU16(ip, 2), ret_size);
append_memset_dest(builder, 0, ret_size);
// LOCAL_VAR (ip [1], gpointer) = this_vt;
builder.local("pLocals");
append_ldloca(builder, getArgU16(ip, 2), ret_size);
append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.i32_store);
break;
}

case MintOpcode.MINT_NEWOBJ:
case MintOpcode.MINT_NEWOBJ_VT:
case MintOpcode.MINT_CALLVIRT_FAST:
Expand Down
7 changes: 7 additions & 0 deletions src/mono/mono/mini/interp/interp-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,13 @@ typedef struct {
typedef struct {
gint64 transform_time;
gint64 methods_transformed;
gint64 optimize_time;
gint64 ssa_compute_time;
gint64 ssa_compute_dominance_time;
gint64 ssa_compute_global_vars_time;
gint64 ssa_compute_pruned_liveness_time;
gint64 ssa_rename_vars_time;
gint64 optimize_bblocks_time;
gint64 cprop_time;
gint64 super_instructions_time;
gint32 emitted_instructions;
Expand Down
6 changes: 3 additions & 3 deletions src/mono/mono/mini/interp/interp-intrins.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ rotate_left (guint32 value, int offset)
}

void
interp_intrins_marvin_block (guint32 *pp0, guint32 *pp1)
interp_intrins_marvin_block (guint32 *pp0, guint32 *pp1, guint32 *dest0, guint32 *dest1)
{
// Marvin.Block
guint32 p0 = *pp0;
Expand All @@ -34,8 +34,8 @@ interp_intrins_marvin_block (guint32 *pp0, guint32 *pp1)
p0 += p1;
p1 = rotate_left (p1, 19);

*pp0 = p0;
*pp1 = p1;
*dest0 = p0;
*dest1 = p1;
}

guint32
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/interp/interp-intrins.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ interp_intrins_popcount_i8 (guint64 val)
#endif

void
interp_intrins_marvin_block (guint32 *pp0, guint32 *pp1);
interp_intrins_marvin_block (guint32 *pp0, guint32 *pp1, guint32 *dest0, guint32 *dest1);

guint32
interp_intrins_ascii_chars_to_uppercase (guint32 val);
Expand Down
44 changes: 6 additions & 38 deletions src/mono/mono/mini/interp/interp-simd.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,47 +315,15 @@ interp_v128_u2_widen_upper (gpointer res, gpointer v1)
static void
interp_v128_u1_narrow (gpointer res, gpointer v1, gpointer v2)
{
guint8 *res_typed = (guint8*)res;
guint8 res_typed [SIZEOF_V128];
guint16 *v1_typed = (guint16*)v1;
guint16 *v2_typed = (guint16*)v2;

if (res != v2) {
res_typed [0] = v1_typed [0];
res_typed [1] = v1_typed [1];
res_typed [2] = v1_typed [2];
res_typed [3] = v1_typed [3];
res_typed [4] = v1_typed [4];
res_typed [5] = v1_typed [5];
res_typed [6] = v1_typed [6];
res_typed [7] = v1_typed [7];

res_typed [8] = v2_typed [0];
res_typed [9] = v2_typed [1];
res_typed [10] = v2_typed [2];
res_typed [11] = v2_typed [3];
res_typed [12] = v2_typed [4];
res_typed [13] = v2_typed [5];
res_typed [14] = v2_typed [6];
res_typed [15] = v2_typed [7];
} else {
res_typed [15] = v2_typed [7];
res_typed [14] = v2_typed [6];
res_typed [13] = v2_typed [5];
res_typed [12] = v2_typed [4];
res_typed [11] = v2_typed [3];
res_typed [10] = v2_typed [2];
res_typed [9] = v2_typed [1];
res_typed [8] = v2_typed [0];

res_typed [0] = v1_typed [0];
res_typed [1] = v1_typed [1];
res_typed [2] = v1_typed [2];
res_typed [3] = v1_typed [3];
res_typed [4] = v1_typed [4];
res_typed [5] = v1_typed [5];
res_typed [6] = v1_typed [6];
res_typed [7] = v1_typed [7];
}
for (int i = 0; i < 8; i++)
res_typed [i] = v1_typed [i];
for (int i = 0; i < 8; i++)
res_typed [i + 8] = v2_typed [i];
memcpy (res, res_typed, SIZEOF_V128);
}

// GreaterThan
Expand Down
35 changes: 9 additions & 26 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -5786,15 +5786,6 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
cmethod = (InterpMethod*)frame->imethod->data_items [imethod_index];
goto jit_call;
}
MINT_IN_CASE(MINT_NEWOBJ_VT_INLINED) {
guint16 ret_size = ip [3];
gpointer this_vt = locals + ip [2];

memset (this_vt, 0, ret_size);
LOCAL_VAR (ip [1], gpointer) = this_vt;
ip += 4;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_NEWOBJ_SLOW) {
guint32 const token = ip [3];
return_offset = ip [1];
Expand Down Expand Up @@ -5937,8 +5928,13 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_INTRINS_MARVIN_BLOCK) {
interp_intrins_marvin_block ((guint32*)(locals + ip [1]), (guint32*)(locals + ip [2]));
ip += 3;
guint32 *pp0 = (guint32*)(locals + ip [1]);
guint32 *pp1 = (guint32*)(locals + ip [2]);
guint32 *dest0 = (guint32*)(locals + ip [3]);
guint32 *dest1 = (guint32*)(locals + ip [4]);

interp_intrins_marvin_block (pp0, pp1, dest0, dest1);
ip += 5;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_INTRINS_ASCII_CHARS_TO_UPPERCASE) {
Expand Down Expand Up @@ -7931,6 +7927,8 @@ interp_parse_options (const char *options)
else if (strncmp (arg, "jiterp", 6) == 0)
opt = INTERP_OPT_JITERPRETER;
#endif
else if (strncmp (arg, "ssa", 3) == 0)
opt = INTERP_OPT_SSA;
else if (strncmp (arg, "all", 3) == 0)
opt = ~INTERP_OPT_NONE;

Expand Down Expand Up @@ -8682,19 +8680,6 @@ interp_cleanup (void)
#endif
}

static void
register_interp_stats (void)
{
mono_counters_init ();
mono_counters_register ("Total transform time", MONO_COUNTER_INTERP | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &mono_interp_stats.transform_time);
mono_counters_register ("Methods transformed", MONO_COUNTER_INTERP | MONO_COUNTER_LONG, &mono_interp_stats.methods_transformed);
mono_counters_register ("Total cprop time", MONO_COUNTER_INTERP | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &mono_interp_stats.cprop_time);
mono_counters_register ("Total super instructions time", MONO_COUNTER_INTERP | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &mono_interp_stats.super_instructions_time);
mono_counters_register ("Emitted instructions", MONO_COUNTER_INTERP | MONO_COUNTER_INT, &mono_interp_stats.emitted_instructions);
mono_counters_register ("Methods inlined", MONO_COUNTER_INTERP | MONO_COUNTER_INT, &mono_interp_stats.inlined_methods);
mono_counters_register ("Inline failures", MONO_COUNTER_INTERP | MONO_COUNTER_INT, &mono_interp_stats.inline_failures);
}

#undef MONO_EE_CALLBACK
#define MONO_EE_CALLBACK(ret, name, sig) interp_ ## name,

Expand Down Expand Up @@ -8723,8 +8708,6 @@ mono_ee_interp_init (const char *opts)

mini_install_interp_callbacks (&mono_interp_callbacks);

register_interp_stats ();

#ifdef HOST_WASI
debugger_enabled = mini_get_debug_options ()->mdb_optimizations;
#endif
Expand Down
3 changes: 2 additions & 1 deletion src/mono/mono/mini/interp/interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ enum {
#if HOST_BROWSER
INTERP_OPT_JITERPRETER = 64,
#endif
INTERP_OPT_DEFAULT = INTERP_OPT_INLINE | INTERP_OPT_CPROP | INTERP_OPT_SUPER_INSTRUCTIONS | INTERP_OPT_BBLOCKS | INTERP_OPT_TIERING | INTERP_OPT_SIMD
INTERP_OPT_SSA = 128,
INTERP_OPT_DEFAULT = INTERP_OPT_INLINE | INTERP_OPT_CPROP | INTERP_OPT_SUPER_INSTRUCTIONS | INTERP_OPT_BBLOCKS | INTERP_OPT_TIERING | INTERP_OPT_SIMD | INTERP_OPT_SSA
#if HOST_BROWSER
| INTERP_OPT_JITERPRETER
#endif
Expand Down
1 change: 0 additions & 1 deletion src/mono/mono/mini/interp/jiterpreter-opcode-values.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ OP(MINT_INTRINS_RUNTIMEHELPERS_OBJECT_HAS_COMPONENT_SIZE, HIGH)
OP(MINT_INTRINS_ENUM_HASFLAG, HIGH)
OP(MINT_INTRINS_ORDINAL_IGNORE_CASE_ASCII, HIGH)
OP(MINT_NEWOBJ_INLINED, HIGH)
OP(MINT_NEWOBJ_VT_INLINED, MASSIVE)
OP(MINT_CPBLK, HIGH)
OP(MINT_INITBLK, HIGH)
OP(MINT_ROL_I4_IMM, HIGH)
Expand Down
12 changes: 9 additions & 3 deletions src/mono/mono/mini/interp/mintops.def
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,6 @@ OPDEF(MINT_NEWOBJ_STRING, "newobj_string", 4, 1, 1, MintOpMethodToken)
OPDEF(MINT_NEWOBJ, "newobj", 5, 1, 1, MintOpMethodToken)
OPDEF(MINT_NEWOBJ_INLINED, "newobj_inlined", 3, 1, 0, MintOpVTableToken)
OPDEF(MINT_NEWOBJ_VT, "newobj_vt", 5, 1, 1, MintOpMethodToken)
OPDEF(MINT_NEWOBJ_VT_INLINED, "newobj_vt_inlined", 4, 1, 1, MintOpShortInt)
OPDEF(MINT_INITOBJ, "initobj", 3, 0, 1, MintOpShortInt)
OPDEF(MINT_CASTCLASS, "castclass", 4, 1, 1, MintOpClassToken)
OPDEF(MINT_ISINST, "isinst", 4, 1, 1, MintOpClassToken)
Expand Down Expand Up @@ -815,7 +814,8 @@ OPDEF(MINT_INTRINS_GET_TYPE, "intrins_get_type", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_INTRINS_SPAN_CTOR, "intrins_span_ctor", 4, 1, 2, MintOpNoArgs)
OPDEF(MINT_INTRINS_RUNTIMEHELPERS_OBJECT_HAS_COMPONENT_SIZE, "intrins_runtimehelpers_object_has_component_size", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_INTRINS_CLEAR_WITH_REFERENCES, "intrin_clear_with_references", 3, 0, 2, MintOpNoArgs)
OPDEF(MINT_INTRINS_MARVIN_BLOCK, "intrins_marvin_block", 3, 0, 2, MintOpNoArgs)
// This actually has 2 dregs and 2 sregs. Dregs are displayed as the metadata
OPDEF(MINT_INTRINS_MARVIN_BLOCK, "intrins_marvin_block", 5, 0, 2, MintOpTwoShorts)
OPDEF(MINT_INTRINS_ASCII_CHARS_TO_UPPERCASE, "intrins_ascii_chars_to_uppercase", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_INTRINS_MEMORYMARSHAL_GETARRAYDATAREF, "intrins_memorymarshal_getarraydataref", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_INTRINS_ORDINAL_IGNORE_CASE_ASCII, "intrins_ordinal_ignore_case_ascii", 4, 1, 2, MintOpNoArgs)
Expand All @@ -834,12 +834,18 @@ OPDEF(MINT_TIER_MONITOR_JITERPRETER, "tier_monitor_jiterpreter", 4, 0, 0, MintOp

IROPDEF(MINT_NOP, "nop", 1, 0, 0, MintOpNoArgs)
IROPDEF(MINT_DEF, "def", 2, 1, 0, MintOpNoArgs)
IROPDEF(MINT_DEF_ARG, "def_arg", 2, 1, 0, MintOpNoArgs)
IROPDEF(MINT_DEF_TIER_VAR, "def_tier_var", 3, 1, 1, MintOpNoArgs)
IROPDEF(MINT_IL_SEQ_POINT, "il_seq_point", 1, 0, 0, MintOpNoArgs)
IROPDEF(MINT_DUMMY_USE, "dummy_use", 2, 0, 1, MintOpNoArgs)
IROPDEF(MINT_TIER_PATCHPOINT_DATA, "tier_patchpoint_data", 2, 0, 0, MintOpShortInt)
// These two opcodes are resolved to a normal MINT_MOV when emitting compacted instructions
IROPDEF(MINT_MOV_SRC_OFF, "mov.src.off", 6, 1, 1, MintOpTwoShorts)
IROPDEF(MINT_MOV_DST_OFF, "mov.dst.off", 6, 1, 1, MintOpTwoShorts)
IROPDEF(MINT_MOV_DST_OFF, "mov.dst.off", 8, 1, 2, MintOpTwoShorts)
IROPDEF(MINT_PHI, "phi", 2, 1, 0, MintOpNoArgs)
IROPDEF(MINT_DEAD_PHI, "dead_phi", 1, 0, 0, MintOpNoArgs)
IROPDEF(MINT_INTRINS_MARVIN_BLOCK_SSA1, "intrins_marvin_block_ssa1", 4, 1, 2, MintOpNoArgs)
IROPDEF(MINT_INTRINS_MARVIN_BLOCK_SSA2, "intrins_marvin_block_ssa2", 4, 1, 2, MintOpNoArgs)

#ifdef __DEFINED_IROPDEF__
#undef IROPDEF
Expand Down
5 changes: 3 additions & 2 deletions src/mono/mono/mini/interp/mintops.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ typedef enum {

#define MINT_SWITCH_LEN(n) (4 + (n) * 2)

#define MINT_IS_NOP(op) ((op) == MINT_NOP || (op) == MINT_DEF || (op) == MINT_DUMMY_USE || (op) == MINT_IL_SEQ_POINT)
#define MINT_IS_NOP(op) ((op) == MINT_NOP || (op) == MINT_DEF || (op) == MINT_DEF_ARG || (op) == MINT_DUMMY_USE || (op) == MINT_IL_SEQ_POINT)
#define MINT_IS_EMIT_NOP(op) ((op) == MINT_NOP || (op) == MINT_DEF || (op) == MINT_DEF_ARG || (op) == MINT_DEF_TIER_VAR || (op) == MINT_DUMMY_USE)
#define MINT_IS_MOV(op) ((op) >= MINT_MOV_I4_I1 && (op) <= MINT_MOV_VT)
#define MINT_IS_UNCONDITIONAL_BRANCH(op) ((op) >= MINT_BR && (op) <= MINT_CALL_HANDLER_S)
#define MINT_IS_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BLT_UN_R8_S)
Expand All @@ -234,7 +235,7 @@ typedef enum {
#define MINT_IS_RETURN(op) (((op) >= MINT_RET && (op) <= MINT_RET_U2) || (op) == MINT_RET_I4_IMM || (op) == MINT_RET_I8_IMM)

// TODO Add more
#define MINT_NO_SIDE_EFFECTS(op) (MINT_IS_MOV (op) || MINT_IS_LDC_I4 (op) || MINT_IS_LDC_I8 (op) || op == MINT_LDC_R4 || op == MINT_LDC_R8 || op == MINT_LDPTR || op == MINT_BOX)
#define MINT_NO_SIDE_EFFECTS(op) (MINT_IS_MOV (op) || MINT_IS_LDC_I4 (op) || MINT_IS_LDC_I8 (op) || op == MINT_LDC_R4 || op == MINT_LDC_R8 || op == MINT_LDPTR || op == MINT_BOX || op == MINT_INITLOCAL)

#define MINT_CALL_ARGS 2
#define MINT_CALL_ARGS_SREG -2
Expand Down
Loading
Loading