Skip to content

Commit

Permalink
Only split SSA versions to dominance frontiers
Browse files Browse the repository at this point in the history
When we need to insert additional guards while translating dispatch
programs or stacking up guards ahead of a call, we perform an SSA
version split, since gurad instructions write a new version (so the
facts can be placed on the new version only). When looking for reads to
update, it would walk the CFG successors. However, this is incorrect.
Consider:

      A
     / \
    B   C
     \ /
      D

If we insert a guard in C, then we cannot depend on the property it
enforced in D (since we might never execute C on the way to it).
By contrast, a guard in A could update reads safely in all of B, C,
and D. We want to update reads only in the set of basic blocks where,
if they are executed, then we *must* have been in the one where the
guard split takes place before them. Handily, this is the definition of
dominance, so we switch from updating successors to updating children.
  • Loading branch information
jnthn committed Sep 15, 2021
1 parent 06453a5 commit 8667fee
Showing 1 changed file with 7 additions and 12 deletions.
19 changes: 7 additions & 12 deletions src/spesh/manipulate.c
Expand Up @@ -408,22 +408,20 @@ MVMSpeshOperand MVM_spesh_manipulate_new_version(MVMThreadContext *tc, MVMSpeshG
}

/* Performs an SSA version split at the specified instruction, such that the
* reads of the SSA value after (and including) the specified instruction
* reads of the SSA value dominated by (and including) the specified instruction
* will use a new version. Returns the new version, which will at that point
* lack a writer; a writer should be inserted for it. */
MVMSpeshOperand MVM_spesh_manipulate_split_version(MVMThreadContext *tc, MVMSpeshGraph *g,
MVMSpeshOperand split, MVMSpeshBB *bb,
MVMSpeshIns *at) {
MVMSpeshOperand new_version = MVM_spesh_manipulate_new_version(tc, g, split.reg.orig);
/* More than we need by definition */
/* Queue of children to process; more than we need by definition */
MVMSpeshBB **bbq = alloca(sizeof(MVMSpeshBB*) * g->num_bbs);
MVMuint8 *seen_bb = alloca(g->num_bbs);
memset(seen_bb, 0, g->num_bbs);
MVMint32 top = 0;
/* Push initial basic block */
bbq[top++] = bb;
seen_bb[bb->idx] = 1;
while (top != 0) {
/* Update instructions in this basic block. */
MVMuint32 i;
MVMSpeshBB *cur_bb = bbq[--top];
MVMSpeshIns *ins = cur_bb == bb ? at : cur_bb->first_ins;
Expand All @@ -440,13 +438,10 @@ MVMSpeshOperand MVM_spesh_manipulate_split_version(MVMThreadContext *tc, MVMSpes
}
ins = ins->next;
}
for (i = 0; i < cur_bb->num_succ; i++) {
MVMSpeshBB *succ = cur_bb->succ[i];
if (!seen_bb[succ->idx]) {
bbq[top++] = succ;
seen_bb[succ->idx] = 1;
}
}

/* Add dominance children to the queue. */
for (i = 0; i < cur_bb->num_children; i++)
bbq[top++] = cur_bb->children[i];
}
MVM_spesh_copy_facts(tc, g, new_version, split);
return new_version;
Expand Down

0 comments on commit 8667fee

Please sign in to comment.