A bb's regsin are no longer the same as those of its first instruction;
authorDavid Given <dg@cowlark.com>
Wed, 16 Nov 2016 19:52:15 +0000 (20:52 +0100)
committerDavid Given <dg@cowlark.com>
Wed, 16 Nov 2016 19:52:15 +0000 (20:52 +0100)
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
mach/proto/mcg/pass_registerallocator.c

index 323fa4d..362a05f 100644 (file)
@@ -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;
index 3e0c9b4..a5436bc 100644 (file)
@@ -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; i<dominance.preorder.count; 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);
 
@@ -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; k<bb->regsin->count; k++)
+            for (k=0; k<bb->regsin.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