Skip to content

Commit

Permalink
Correct tracking of log guards at PHI nodes
Browse files Browse the repository at this point in the history
Previously, we only had them on the facts of the PHI node itself.
However, those facts could then be copied and relied on elsewhere. With
this change, we now keep a list of the log guards that we depend on for
each fact, and at a PHI node we copy all the input lists into a target
list. We then, when we depend on or copy facts, just assign the input
log guards list and count (which is safe since it's immutable, and we
use the region allocator so there's no memory management concerns).
  • Loading branch information
jnthn committed Aug 22, 2018
1 parent da8bd3d commit eb6110f
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 44 deletions.
14 changes: 7 additions & 7 deletions src/spesh/facts.c
Expand Up @@ -13,17 +13,16 @@ static void copy_facts(MVMThreadContext *tc, MVMSpeshGraph *g, MVMuint16 to_orig
tfacts->type = ffacts->type;
tfacts->decont_type = ffacts->decont_type;
tfacts->value = ffacts->value;
tfacts->log_guard = ffacts->log_guard;
tfacts->log_guards = ffacts->log_guards;
tfacts->num_log_guards = ffacts->num_log_guards;
}

/* Called when one set of facts depend on another, allowing any log guard
* that is to thank to be marked used as needed later on. */
void MVM_spesh_facts_depend(MVMThreadContext *tc, MVMSpeshGraph *g,
MVMSpeshFacts *target, MVMSpeshFacts *source) {
if (source->flags & MVM_SPESH_FACT_FROM_LOG_GUARD) {
target->flags |= MVM_SPESH_FACT_FROM_LOG_GUARD;
target->log_guard = source->log_guard;
}
target->log_guards = source->log_guards;
target->num_log_guards = source->num_log_guards;
}

/* Handles object-creating instructions. */
Expand Down Expand Up @@ -421,8 +420,9 @@ static void log_facts(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshBB *bb,
}
g->log_guards[g->num_log_guards].ins = guard;
g->log_guards[g->num_log_guards].bb = ins->next ? bb : bb->linear_next;
facts->flags |= MVM_SPESH_FACT_FROM_LOG_GUARD;
facts->log_guard = g->num_log_guards;
facts->log_guards = MVM_spesh_alloc(tc, g, sizeof(MVMint32));
facts->log_guards[0] = g->num_log_guards;
facts->num_log_guards++;
g->num_log_guards++;
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/spesh/facts.h
Expand Up @@ -25,8 +25,9 @@ struct MVMSpeshFacts {
* together with writer form a define-use chain. */
MVMSpeshUsages usage;

/* The log guard the facts depend on, if any. */
MVMuint32 log_guard;
/* The log guard(s) the facts depend on, if any. */
MVMuint32 *log_guards;
MVMuint32 num_log_guards;

/* Has the instruction that wrote this value been deleted? */
MVMuint16 dead_writer;
Expand All @@ -41,13 +42,11 @@ struct MVMSpeshFacts {
#define MVM_SPESH_FACT_KNOWN_DECONT_TYPE 32 /* Has a known type after decont. */
#define MVM_SPESH_FACT_DECONT_CONCRETE 64 /* Is concrete after decont. */
#define MVM_SPESH_FACT_DECONT_TYPEOBJ 128 /* Is a type object after decont. */
#define MVM_SPESH_FACT_FROM_LOG_GUARD 256 /* Depends on a guard being met. */
#define MVM_SPESH_FACT_HASH_ITER 512 /* Is an iter over hashes. */
#define MVM_SPESH_FACT_ARRAY_ITER 1024 /* Is an iter over arrays
(mutually exclusive with HASH_ITER, but neither of them is necessarily set) */
#define MVM_SPESH_FACT_KNOWN_BOX_SRC 2048 /* We know what register this value was boxed from */
#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 */
#define MVM_SPESH_FACT_RW_CONT 8192 /* Known to be an rw container */

void MVM_spesh_facts_discover(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshPlanned *p,
MVMuint32 is_specialized);
Expand Down
68 changes: 36 additions & 32 deletions src/spesh/optimize.c
Expand Up @@ -56,16 +56,9 @@ MVMSpeshFacts * MVM_spesh_get_facts(MVMThreadContext *tc, MVMSpeshGraph *g, MVMS

/* Mark facts for an operand as being relied upon. */
void MVM_spesh_use_facts(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshFacts *facts) {
if (facts->flags & MVM_SPESH_FACT_FROM_LOG_GUARD)
g->log_guards[facts->log_guard].used = 1;
if (facts->flags & MVM_SPESH_FACT_MERGED_WITH_LOG_GUARD) {
MVMSpeshIns *thePHI = facts->writer;
MVMuint32 op_i;

for (op_i = 1; op_i < thePHI->info->num_operands; op_i++) {
MVM_spesh_get_and_use_facts(tc, g, thePHI->operands[op_i]);
}
}
MVMuint32 i;
for (i = 0; i < facts->num_log_guards; i++)
g->log_guards[facts->log_guards[i]].used = 1;
}

/* Obtains a string constant. */
Expand All @@ -77,11 +70,11 @@ MVMString * MVM_spesh_get_string(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpes
static void copy_facts_resolved(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshFacts *tfacts,
MVMSpeshFacts *ffacts) {
tfacts->flags = ffacts->flags;
tfacts->flags &= ~MVM_SPESH_FACT_MERGED_WITH_LOG_GUARD;
tfacts->type = ffacts->type;
tfacts->decont_type = ffacts->decont_type;
tfacts->value = ffacts->value;
tfacts->log_guard = ffacts->log_guard;
tfacts->log_guards = ffacts->log_guards;
tfacts->num_log_guards = ffacts->num_log_guards;
}
static void copy_facts(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshOperand to,
MVMSpeshOperand from) {
Expand Down Expand Up @@ -2307,28 +2300,29 @@ static void analyze_phi(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshIns *ins
MVMint32 common_flags;
MVMObject *common_type;
MVMObject *common_decont_type;
MVMuint32 needs_merged_with_log_guard = 0;
MVMSpeshFacts *target_facts = get_facts_direct(tc, g, ins->operands[0]);
MVMSpeshFacts *cur_operand_facts;

eliminate_phi_dead_reads(tc, g, ins);

common_flags = get_facts_direct(tc, g, ins->operands[1])->flags;
common_type = get_facts_direct(tc, g, ins->operands[1])->type;
common_decont_type = get_facts_direct(tc, g, ins->operands[1])->decont_type;
/* If we have facts that we merge that depended on log guards, then we need
* to carry them forward. */
MVMuint32 total_log_guards = 0;

needs_merged_with_log_guard = common_flags & MVM_SPESH_FACT_FROM_LOG_GUARD;

for(operand = 2; operand < ins->info->num_operands; operand++) {
common_flags = common_flags & get_facts_direct(tc, g, ins->operands[operand])->flags;
common_type = common_type == get_facts_direct(tc, g, ins->operands[operand])->type && common_type ? common_type : NULL;
common_decont_type = common_decont_type == get_facts_direct(tc, g, ins->operands[operand])->decont_type && common_decont_type ? common_decont_type : NULL;
eliminate_phi_dead_reads(tc, g, ins);

/* We have to be a bit more careful if one or more of the facts we're
* merging came from a log guard, as that means we'll have to propagate
* the information what guards have been relied upon back "outwards"
* through the PHI node we've merged stuff with. */
if (get_facts_direct(tc, g, ins->operands[operand])->flags & MVM_SPESH_FACT_FROM_LOG_GUARD)
needs_merged_with_log_guard = 1;
cur_operand_facts = get_facts_direct(tc, g, ins->operands[1]);
common_flags = cur_operand_facts->flags;
common_type = cur_operand_facts->type;
common_decont_type = cur_operand_facts->decont_type;
total_log_guards = cur_operand_facts->num_log_guards;

for (operand = 2; operand < ins->info->num_operands; operand++) {
cur_operand_facts = get_facts_direct(tc, g, ins->operands[operand]);
common_flags = common_flags & cur_operand_facts->flags;
common_type = common_type == cur_operand_facts->type && common_type ? common_type : NULL;
common_decont_type = common_decont_type == cur_operand_facts->decont_type && common_decont_type
? common_decont_type
: NULL;
total_log_guards += cur_operand_facts->num_log_guards;
}

if (common_flags) {
Expand Down Expand Up @@ -2381,8 +2375,18 @@ static void analyze_phi(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshIns *ins
/*if (common_flags & MVM_SPESH_FACT_KNOWN_BOX_SRC) fprintf(stderr, "box_source ");*/
/*fprintf(stderr, "\n");*/

if (needs_merged_with_log_guard) {
target_facts->flags |= MVM_SPESH_FACT_MERGED_WITH_LOG_GUARD;
if (total_log_guards) {
MVMuint32 insert_pos = 0;
target_facts->num_log_guards = total_log_guards;
target_facts->log_guards = MVM_spesh_alloc(tc, g, total_log_guards * sizeof(MVMint32));
for (operand = 1; operand < ins->info->num_operands; operand++) {
cur_operand_facts = get_facts_direct(tc, g, ins->operands[operand]);
if (cur_operand_facts->num_log_guards) {
memcpy(target_facts->log_guards + insert_pos, cur_operand_facts->log_guards,
cur_operand_facts->num_log_guards * sizeof(MVMint32));
insert_pos += cur_operand_facts->num_log_guards;
}
}
}
} else {
/*fprintf(stderr, "a PHI node of %d operands had no intersecting flags\n", ins->info->num_operands);*/
Expand Down

0 comments on commit eb6110f

Please sign in to comment.