Skip to content

Commit

Permalink
[interp] Handle more cases for stloc.np optimization
Browse files Browse the repository at this point in the history
We emit stloc.np if we have "stloc local; ldloc local". Bu we can also emit if we have "stloc loc1; ldloc loc2" and loc2 == loc1.


Commit migrated from mono/mono@f2006f6
  • Loading branch information
BrzVlad authored and lewing committed Oct 8, 2019
1 parent 222e27e commit 05099ad
Showing 1 changed file with 24 additions and 2 deletions.
26 changes: 24 additions & 2 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -6387,6 +6387,26 @@ interp_local_deadce (TransformData *td, int *local_ref_count)
}
}

static gboolean
interp_local_equal (StackValue *locals, int local1, int local2)
{
if (local1 == local2)
return TRUE;
if (locals [local1].opcode != MINT_NOP) {
g_assert (MINT_IS_LDLOC (locals [local1].opcode));
// local1 is a copy of local2
if (locals [local1].data == local2)
return TRUE;
}
if (locals [local2].opcode != MINT_NOP) {
g_assert (MINT_IS_LDLOC (locals [local2].opcode));
// local2 is a copy of local1
if (locals [local2].data == local1)
return TRUE;
}
return FALSE;
}

static void
interp_cprop (TransformData *td)
{
Expand Down Expand Up @@ -6424,24 +6444,26 @@ interp_cprop (TransformData *td)
int loaded_local = ins->data [0];
local_ref_count [loaded_local]++;
InterpInst *prev_ins = interp_prev_ins (ins);
if (MINT_IS_STLOC (prev_ins->opcode) && !interp_is_bb_start (td, prev_ins, ins) && prev_ins->data [0] == loaded_local) {
if (MINT_IS_STLOC (prev_ins->opcode) && !interp_is_bb_start (td, prev_ins, ins) && interp_local_equal (locals, prev_ins->data [0], loaded_local)) {
int mt = prev_ins->opcode - MINT_STLOC_I1;
if (ins->opcode - MINT_LDLOC_I1 == mt) {
if (mt == MINT_TYPE_I4)
replace_op = MINT_STLOC_NP_I4;
else if (mt == MINT_TYPE_O || mt == MINT_TYPE_P)
replace_op = MINT_STLOC_NP_O;
if (replace_op) {
int stored_local = prev_ins->data [0];
if (td->verbose_level)
g_print ("Add stloc.np : ldloc (off %p), stloc (off %p)\n", ins->il_offset, prev_ins->il_offset);
// We know what local is on the stack now. Track it
sp->ins = NULL;
sp->val.opcode = ins->opcode;
sp->val.data = loaded_local;
sp->val.data = stored_local;

// Clear the previous stloc instruction
interp_clear_ins (td, prev_ins);
ins->opcode = replace_op;
ins->data [0] = stored_local;
mono_interp_stats.stloc_nps++;
local_ref_count [loaded_local]--;
}
Expand Down

0 comments on commit 05099ad

Please sign in to comment.