Skip to content

Commit

Permalink
Do dead instruction elim pass after usage setup
Browse files Browse the repository at this point in the history
But before we do the deopt analysis. While it's of course possible
that there was dead code in the input program, the main purpose of
this is to trim away dead PHI nodes, recursively, so that they will
not make extra work for the deopt analyzer nor cause things to be
kept alive bogusly just because a PHI was used across a deopt point.

This seems to have a positive effect on spectest time, probably due
to the deopt usage algorithm having a bit less to do, as well as
resulting in elimination of more instructions during optimization
that were falsely retained.
  • Loading branch information
jnthn committed Aug 9, 2018
1 parent 210a402 commit bfbbb0f
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 45 deletions.
3 changes: 2 additions & 1 deletion build/Makefile.in
Expand Up @@ -196,6 +196,7 @@ OBJECTS = src/core/callsite@obj@ \
src/spesh/facts@obj@ \
src/spesh/optimize@obj@ \
src/spesh/dead_bb_elimination@obj@ \
src/spesh/dead_ins_elimination@obj@ \
src/spesh/deopt@obj@ \
src/spesh/log@obj@ \
src/spesh/threshold@obj@ \
Expand Down Expand Up @@ -359,7 +360,7 @@ HEADERS = src/moar.h \
src/spesh/usages.h \
src/spesh/facts.h \
src/spesh/optimize.h \
src/spesh/dead_bb_elimination.h \
src/spesh/dead_ins_elimination.h \
src/spesh/deopt.h \
src/spesh/log.h \
src/spesh/threshold.h \
Expand Down
1 change: 1 addition & 0 deletions src/moar.h
Expand Up @@ -152,6 +152,7 @@ MVM_PUBLIC const MVMint32 MVM_jit_support(void);
#include "spesh/facts.h"
#include "spesh/optimize.h"
#include "spesh/dead_bb_elimination.h"
#include "spesh/dead_ins_elimination.h"
#include "spesh/deopt.h"
#include "spesh/log.h"
#include "spesh/threshold.h"
Expand Down
2 changes: 1 addition & 1 deletion src/spesh/candidate.c
Expand Up @@ -76,7 +76,7 @@ void MVM_spesh_candidate_add(MVMThreadContext *tc, MVMSpeshPlanned *p) {
if (p->cs_stats->cs)
MVM_spesh_args(tc, sg, p->cs_stats->cs, p->type_tuple);
spesh_gc_point(tc);
MVM_spesh_facts_discover(tc, sg, p);
MVM_spesh_facts_discover(tc, sg, p, 0);
spesh_gc_point(tc);
MVM_spesh_optimize(tc, sg, p);
spesh_gc_point(tc);
Expand Down
38 changes: 38 additions & 0 deletions src/spesh/dead_ins_elimination.c
@@ -0,0 +1,38 @@
#include "moar.h"

/* Eliminates any unused instructions. */
void MVM_spesh_eliminate_dead_ins(MVMThreadContext *tc, MVMSpeshGraph *g) {
/* Keep eliminating to a fixed point. */
MVMint8 death = 1;
while (death) {
MVMSpeshBB *bb = g->entry;
death = 0;
while (bb) {
if (!bb->inlined) {
MVMSpeshIns *ins = bb->last_ins;
while (ins) {
MVMSpeshIns *prev = ins->prev;
if (ins->info->opcode == MVM_SSA_PHI) {
if (!MVM_spesh_usages_is_used(tc, g, ins->operands[0])) {
/* Remove this phi. */
MVM_spesh_manipulate_delete_ins(tc, g, bb, ins);
death = 1;
}
}
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) {
if (!MVM_spesh_usages_is_used(tc, g, ins->operands[0])) {
/* Remove this instruction. */
MVM_spesh_manipulate_delete_ins(tc, g, bb, ins);
death = 1;
}
}
}
ins = prev;
}
}
bb = bb->linear_next;
}
}
}
1 change: 1 addition & 0 deletions src/spesh/dead_ins_elimination.h
@@ -0,0 +1 @@
void MVM_spesh_eliminate_dead_ins(MVMThreadContext *tc, MVMSpeshGraph *g);
16 changes: 14 additions & 2 deletions src/spesh/facts.c
Expand Up @@ -687,8 +687,20 @@ static void tweak_block_handler_usage(MVMThreadContext *tc, MVMSpeshGraph *g) {
}

/* Kicks off fact discovery from the top of the (dominator) tree. */
void MVM_spesh_facts_discover(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshPlanned *p) {
void MVM_spesh_facts_discover(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshPlanned *p,
MVMuint32 is_specialized) {
/* The facts pass sets up usage normal usage information. */
add_bb_facts(tc, g, g->entry, p);
tweak_block_handler_usage(tc, g);
MVM_spesh_usages_create_deopt_usage(tc, g);

/* We do an initial dead instruction pass before then computing the deopt
* usages. This dead instrution elimination pass acts also as a PHI prune,
* since we have numerous dead PHI instructions that can cause bogus
* deopt retentions, as well as increase the amount of work that the
* deopt usage algorithm has to do. Note that we don't do this for an
* already specialized inlinee, since information was already discarded. */
if (!is_specialized) {
MVM_spesh_eliminate_dead_ins(tc, g);
MVM_spesh_usages_create_deopt_usage(tc, g);
}
}
3 changes: 2 additions & 1 deletion src/spesh/facts.h
Expand Up @@ -49,7 +49,8 @@ struct MVMSpeshFacts {
#define MVM_SPESH_FACT_MERGED_WITH_LOG_GUARD 4096 /* These facts were merged at a PHI node, but at least one of the incoming facts had a "from log guard" flag set, so we'll have to look for that fact and increment its uses if we use this here fact. */
#define MVM_SPESH_FACT_RW_CONT 8192 /* Known to be an rw container */

void MVM_spesh_facts_discover(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshPlanned *p);
void MVM_spesh_facts_discover(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshPlanned *p,
MVMuint32 is_specialized);
void MVM_spesh_facts_depend(MVMThreadContext *tc, MVMSpeshGraph *g,
MVMSpeshFacts *target, MVMSpeshFacts *source);
void MVM_spesh_facts_object_facts(MVMThreadContext *tc, MVMSpeshGraph *g,
Expand Down
4 changes: 2 additions & 2 deletions src/spesh/inline.c
Expand Up @@ -193,7 +193,7 @@ MVMSpeshGraph * MVM_spesh_inline_try_get_graph(MVMThreadContext *tc, MVMSpeshGra
* We also need to bump counts for any inline's code_ref_reg to make
* sure it stays available for deopt. */
MVMuint32 i;
MVM_spesh_facts_discover(tc, ig, NULL);
MVM_spesh_facts_discover(tc, ig, NULL, 1);
for (i = 0; i < ig->num_inlines; i++) {
/* We can't be very precise about this, because we don't know the
* SSA version in effect. So bump usages of all version of the
Expand Down Expand Up @@ -235,7 +235,7 @@ MVMSpeshGraph * MVM_spesh_inline_try_get_graph_from_unspecialized(MVMThreadConte
* the args specialization). */
ig = MVM_spesh_graph_create(tc, target_sf, 0, 1);
MVM_spesh_args_from_callinfo(tc, ig, call_info);
MVM_spesh_facts_discover(tc, ig, NULL);
MVM_spesh_facts_discover(tc, ig, NULL, 0);
MVM_spesh_optimize(tc, ig, NULL);

/* See if it's inlineable; clean up if not. */
Expand Down
39 changes: 1 addition & 38 deletions src/spesh/optimize.c
Expand Up @@ -2540,43 +2540,6 @@ static void optimize_bb(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshBB *bb,
}
}

/* Eliminates any unused instructions. */
static void eliminate_dead_ins(MVMThreadContext *tc, MVMSpeshGraph *g) {
/* Keep eliminating to a fixed point. */
MVMint8 death = 1;
while (death) {
MVMSpeshBB *bb = g->entry;
death = 0;
while (bb) {
if (!bb->inlined) {
MVMSpeshIns *ins = bb->last_ins;
while (ins) {
MVMSpeshIns *prev = ins->prev;
if (ins->info->opcode == MVM_SSA_PHI) {
if (!MVM_spesh_usages_is_used(tc, g, ins->operands[0])) {
/* Remove this phi. */
MVM_spesh_manipulate_delete_ins(tc, g, bb, ins);
death = 1;
}
}
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) {
if (!MVM_spesh_usages_is_used(tc, g, ins->operands[0])) {
/* Remove this instruction. */
MVM_spesh_manipulate_delete_ins(tc, g, bb, ins);
death = 1;
}
}
}
ins = prev;
}
}
bb = bb->linear_next;
}
}
}

/* Optimization turns many things into simple set instructions, which we can
* often further eliminate; others may become unrequired due to eliminated
* branches, and some may be from sub-optimizal original code. */
Expand Down Expand Up @@ -2878,7 +2841,7 @@ void MVM_spesh_optimize(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshPlanned
eliminate_unused_log_guards(tc, g);
eliminate_pointless_gotos(tc, g);
MVM_spesh_usages_remove_unused_deopt(tc, g);
eliminate_dead_ins(tc, g);
MVM_spesh_eliminate_dead_ins(tc, g);

merge_bbs(tc, g);

Expand Down

0 comments on commit bfbbb0f

Please sign in to comment.