From 81bc2c74c51e391461940bf827b4ae70958af84c Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 16 Nov 2016 20:52:15 +0100 Subject: [PATCH] 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. --- mach/proto/mcg/basicblock.h | 8 +++----- mach/proto/mcg/pass_registerallocator.c | 25 +++++++++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/mach/proto/mcg/basicblock.h b/mach/proto/mcg/basicblock.h index 323fa4dd5..362a05f7f 100644 --- a/mach/proto/mcg/basicblock.h +++ b/mach/proto/mcg/basicblock.h @@ -24,11 +24,9 @@ struct basicblock ARRAYOF(struct vreg) liveins; ARRAYOF(struct vreg) liveouts; - /* Register assignments on entry and exit. These are *pointers* (because - * they just point to the regsin/regsout of the first and last hop - * respectively). */ - register_assignment_t* regsin; - register_assignment_t* regsout; + /* Register assignments on entry and exit. */ + register_assignment_t regsin; + register_assignment_t* regsout; /* points at regsout of the last insn. */ bool is_fake : 1; bool is_root : 1; diff --git a/mach/proto/mcg/pass_registerallocator.c b/mach/proto/mcg/pass_registerallocator.c index 3e0c9b43b..a5436bc73 100644 --- a/mach/proto/mcg/pass_registerallocator.c +++ b/mach/proto/mcg/pass_registerallocator.c @@ -54,7 +54,6 @@ static void wire_up_blocks_ins_outs(void) { struct basicblock* bb = dominance.preorder.item[i]; assert(bb->hops.count >= 1); - bb->regsin = &bb->hops.item[0]->regsin; bb->regsout = &bb->hops.item[bb->hops.count-1]->regsout; } } @@ -462,7 +461,7 @@ static void assign_hregs_to_vregs(void) for (i=0; iregsin; + register_assignment_t* old = &bb->regsin; tracef('R', "R: considering block %s\n", bb->name); @@ -568,8 +567,7 @@ static void assign_hregs_to_vregs(void) } tracef('R', "]\n"); - if (j > 0) - j += insert_moves(bb, j, old, in); + j += insert_moves(bb, j, old, in); old = out; } @@ -692,15 +690,16 @@ static void insert_phi_copies(void) { struct vreg* vreg = bb->phis.item[k].left; 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) { /* We inserted critical edges to guarantee this. */ assert(prevbb->nexts.count == 1); - tracef('R', "R: map %%%d -> %%%d (%s)\n", - phi->ir->result->id, + tracef('R', "R: phi map %%%d (%s) -> %%%d (%s)\n", + phi->ir->result->id, src->id, vreg->id, dest->id); pmap_put(&destregs, dest, phi->ir->result); @@ -709,12 +708,18 @@ static void insert_phi_copies(void) /* Add any non-phi inputs. */ - for (k=0; kregsin->count; k++) + for (k=0; kregsin.count; k++) { - struct hreg* hreg = bb->regsin->item[k].left; - struct vreg* vreg = bb->regsin->item[k].right; + struct hreg*hreg = bb->regsin.item[k].left; + struct vreg* vreg = bb->regsin.item[k].right; + struct hreg* src = pmap_findright(prevbb->regsout, 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); + } } /* The last instruction of a block should be the jump that sends us