A bb's regsin are no longer the same as those of its first instruction;

occasionally the first hop of a block would try to rearrange its registers (due
to evicted throughs), resulting in the phi moves copying values into the wrong
registers.
This commit is contained in:
David Given 2016-11-16 20:52:15 +01:00
parent edfee33576
commit 81bc2c74c5
2 changed files with 18 additions and 15 deletions

View file

@ -24,11 +24,9 @@ struct basicblock
ARRAYOF(struct vreg) liveins; ARRAYOF(struct vreg) liveins;
ARRAYOF(struct vreg) liveouts; ARRAYOF(struct vreg) liveouts;
/* Register assignments on entry and exit. These are *pointers* (because /* Register assignments on entry and exit. */
* they just point to the regsin/regsout of the first and last hop register_assignment_t regsin;
* respectively). */ register_assignment_t* regsout; /* points at regsout of the last insn. */
register_assignment_t* regsin;
register_assignment_t* regsout;
bool is_fake : 1; bool is_fake : 1;
bool is_root : 1; bool is_root : 1;

View file

@ -54,7 +54,6 @@ static void wire_up_blocks_ins_outs(void)
{ {
struct basicblock* bb = dominance.preorder.item[i]; struct basicblock* bb = dominance.preorder.item[i];
assert(bb->hops.count >= 1); assert(bb->hops.count >= 1);
bb->regsin = &bb->hops.item[0]->regsin;
bb->regsout = &bb->hops.item[bb->hops.count-1]->regsout; bb->regsout = &bb->hops.item[bb->hops.count-1]->regsout;
} }
} }
@ -462,7 +461,7 @@ static void assign_hregs_to_vregs(void)
for (i=0; i<dominance.preorder.count; i++) for (i=0; i<dominance.preorder.count; i++)
{ {
struct basicblock* bb = dominance.preorder.item[i]; struct basicblock* bb = dominance.preorder.item[i];
register_assignment_t* old = bb->regsin; register_assignment_t* old = &bb->regsin;
tracef('R', "R: considering block %s\n", bb->name); tracef('R', "R: considering block %s\n", bb->name);
@ -568,8 +567,7 @@ static void assign_hregs_to_vregs(void)
} }
tracef('R', "]\n"); tracef('R', "]\n");
if (j > 0) j += insert_moves(bb, j, old, in);
j += insert_moves(bb, j, old, in);
old = out; old = out;
} }
@ -692,15 +690,16 @@ static void insert_phi_copies(void)
{ {
struct vreg* vreg = bb->phis.item[k].left; struct vreg* vreg = bb->phis.item[k].left;
struct phi* phi = bb->phis.item[k].right; struct phi* phi = bb->phis.item[k].right;
struct hreg* dest = pmap_findright(bb->regsin, vreg); struct hreg* src = pmap_findright(prevbb->regsout, phi->ir->result);
struct hreg* dest = pmap_findright(&bb->regsin, vreg);
if ((phi->prev == prevbb) && dest) if ((phi->prev == prevbb) && dest)
{ {
/* We inserted critical edges to guarantee this. */ /* We inserted critical edges to guarantee this. */
assert(prevbb->nexts.count == 1); assert(prevbb->nexts.count == 1);
tracef('R', "R: map %%%d -> %%%d (%s)\n", tracef('R', "R: phi map %%%d (%s) -> %%%d (%s)\n",
phi->ir->result->id, phi->ir->result->id, src->id,
vreg->id, dest->id); vreg->id, dest->id);
pmap_put(&destregs, dest, phi->ir->result); pmap_put(&destregs, dest, phi->ir->result);
@ -709,12 +708,18 @@ static void insert_phi_copies(void)
/* Add any non-phi inputs. */ /* Add any non-phi inputs. */
for (k=0; k<bb->regsin->count; k++) for (k=0; k<bb->regsin.count; k++)
{ {
struct hreg* hreg = bb->regsin->item[k].left; struct hreg*hreg = bb->regsin.item[k].left;
struct vreg* vreg = bb->regsin->item[k].right; struct vreg* vreg = bb->regsin.item[k].right;
struct hreg* src = pmap_findright(prevbb->regsout, vreg);
if (!pmap_findleft(&bb->phis, vreg)) if (!pmap_findleft(&bb->phis, vreg))
{
tracef('R', "R: input map %%%d (%s) -> (%s)\n",
vreg->id, src->id, hreg->id);
pmap_add(&destregs, hreg, vreg); pmap_add(&destregs, hreg, vreg);
}
} }
/* The last instruction of a block should be the jump that sends us /* The last instruction of a block should be the jump that sends us