diff --git a/src/spesh/dump.c b/src/spesh/dump.c index e7d6bcd204..874950ef51 100644 --- a/src/spesh/dump.c +++ b/src/spesh/dump.c @@ -400,10 +400,12 @@ static void dump_facts(MVMThreadContext *tc, DumpStr *ds, MVMSpeshGraph *g) { for (j = 0; j < num_facts; j++) { MVMint32 usages = g->facts[i][j].usages; MVMint32 flags = g->facts[i][j].flags; + MVMuint16 deopt_required = g->facts[i][j].deopt_required; if (i < 10) append(ds, " "); if (j < 10) append(ds, " "); if (flags || g->facts[i][j].dead_writer || g->facts[i][j].writer && g->facts[i][j].writer->info->opcode == MVM_SSA_PHI) { - appendf(ds, " r%d(%d): usages=%d, flags=%-5d", i, j, usages, flags); + appendf(ds, " r%d(%d): usages=%d%s, flags=%-5d", i, j, usages, + deopt_required ? "+deopt" : "", flags); if (flags & 1) { append(ds, " KnTyp"); } diff --git a/src/spesh/facts.c b/src/spesh/facts.c index e34e8edece..ee14892d3b 100644 --- a/src/spesh/facts.c +++ b/src/spesh/facts.c @@ -477,7 +477,9 @@ static void add_bb_facts(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshBB *bb, if ((is_phi && i > 0) || (!is_phi && (ins->info->operands[i] & MVM_operand_rw_mask) == MVM_operand_read_reg)) { MVMSpeshFacts *facts = &(g->facts[ins->operands[i].reg.orig][ins->operands[i].reg.i]); - facts->usages += facts->deopt_idx == cur_deopt_idx ? 1 : 2; + facts->usages++; + if (facts->deopt_idx != cur_deopt_idx) + facts->deopt_required = 1; } /* Writes need the current deopt index and the writing instruction @@ -747,3 +749,10 @@ void MVM_spesh_facts_discover(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshPl add_bb_facts(tc, g, g->entry, p, -1); tweak_block_handler_usage(tc, g); } + +/* Checks if an operand is in use, either by having a non-zero usage count or + * being required for deopt. */ +MVMint32 MVM_spesh_facts_is_used(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshOperand operand) { + MVMSpeshFacts *facts = MVM_spesh_get_facts(tc, g, operand); + return facts->usages > 0 || facts->deopt_required; +} diff --git a/src/spesh/facts.h b/src/spesh/facts.h index d42afe3d9c..33839e9a69 100644 --- a/src/spesh/facts.h +++ b/src/spesh/facts.h @@ -31,8 +31,11 @@ struct MVMSpeshFacts { /* The log guard the facts depend on, if any. */ MVMuint32 log_guard; + /* Does the instruction need to be preserved for the sake of deopt? */ + MVMuint16 deopt_required; + /* Has the instruction that wrote this value been deleted? */ - MVMuint32 dead_writer; + MVMuint16 dead_writer; }; /* Various fact flags. */ @@ -57,3 +60,4 @@ void MVM_spesh_facts_depend(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshFacts *target, MVMSpeshFacts *source); void MVM_spesh_facts_object_facts(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshOperand tgt, MVMObject *obj); +MVMint32 MVM_spesh_facts_is_used(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshOperand operand); diff --git a/src/spesh/optimize.c b/src/spesh/optimize.c index 762ea8f8e5..92ea9bf53e 100644 --- a/src/spesh/optimize.c +++ b/src/spesh/optimize.c @@ -2416,8 +2416,7 @@ static void eliminate_dead_ins(MVMThreadContext *tc, MVMSpeshGraph *g) { while (ins) { MVMSpeshIns *prev = ins->prev; if (ins->info->opcode == MVM_SSA_PHI) { - MVMSpeshFacts *facts = get_facts_direct(tc, g, ins->operands[0]); - if (facts->usages == 0) { + if (!MVM_spesh_facts_is_used(tc, g, ins->operands[0])) { /* Remove this phi. */ MVM_spesh_manipulate_delete_ins(tc, g, bb, ins); death = 1; @@ -2426,8 +2425,7 @@ static void eliminate_dead_ins(MVMThreadContext *tc, MVMSpeshGraph *g) { else if (ins->info->pure) { /* Sanity check to make sure it's a write reg as first operand. */ if ((ins->info->operands[0] & MVM_operand_rw_mask) == MVM_operand_write_reg) { - MVMSpeshFacts *facts = get_facts_direct(tc, g, ins->operands[0]); - if (facts->usages == 0) { + if (!MVM_spesh_facts_is_used(tc, g, ins->operands[0])) { /* Remove this instruction. */ MVM_spesh_manipulate_delete_ins(tc, g, bb, ins); death = 1; @@ -2512,7 +2510,7 @@ static void try_eliminate_set(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshBB ins->prev->operands[0].reg.orig == ins->operands[1].reg.orig && ins->prev->operands[0].reg.i == ins->operands[1].reg.i) { MVMSpeshFacts *elim_facts = get_facts_direct(tc, g, ins->operands[1]); - if (elim_facts->usages == 1 && within_inline(tc, g, bb, ins->operands[0])) { + if (elim_facts->usages == 1 && !elim_facts->deopt_required && within_inline(tc, g, bb, ins->operands[0])) { ins->prev->operands[0].reg = ins->operands[0].reg; get_facts_direct(tc, g, ins->prev->operands[0])->writer = ins->prev; MVM_spesh_manipulate_delete_ins(tc, g, bb, ins);