Clone all the vregs just before and after every instruction, so converting the
authorDavid Given <dg@cowlark.com>
Fri, 13 Jan 2017 20:17:16 +0000 (21:17 +0100)
committerDavid Given <dg@cowlark.com>
Fri, 13 Jan 2017 20:17:16 +0000 (21:17 +0100)
program into elementary form.

mach/proto/mcg/hop.c
mach/proto/mcg/hop.h
mach/proto/mcg/pass_assignvregs.c

index 5899275..85c8595 100644 (file)
@@ -268,7 +268,14 @@ char* hop_render(struct hop* hop)
         appendf("@");
 
     if (hop->is_move && (hop->insels.count == 0))
-        appendf("(move)\n");
+    {
+        appendf("(move");
+        for (i=0; i<hop->copies.count; i++)
+            appendf(" %%%d->%%%d",
+                hop->copies.item[i].left->id,
+                hop->copies.item[i].right->id);
+        appendf(")");
+    }
 
        for (i=0; i<hop->insels.count; i++)
        {
index 7e4b443..0c56984 100644 (file)
@@ -46,6 +46,7 @@ struct hop
        ARRAYOF(struct value) corrupted;
 
        struct hashtable* vregmapping;
+       PMAPOF(struct vreg, struct vreg) copies;
 };
 
 extern struct hop* new_hop(struct basicblock* bb, struct ir* ir);
index 57bd2f4..e58a528 100644 (file)
@@ -6,16 +6,41 @@ static struct basicblock* current_bb;
 
 static int vregcount = 0;
 
-static void create_and_map_vreg(struct hashtable* mapping, struct value* value)
+static struct vreg* create_vreg(struct value* value)
 {
     struct vreg* vreg = heap_alloc(&proc_heap, 1, sizeof(*vreg));
     vreg->id = vregcount++;
     vreg->value = value;
+    return vreg;
+}
 
+static void create_and_map_vreg(struct hashtable* mapping, struct value* value)
+{
+    struct vreg* vreg = create_vreg(value);
     assert(!hashtable_get(mapping, value));
     hashtable_put(mapping, value, vreg);
 }
 
+static struct hop* create_move(struct hashtable* previous_mapping)
+{
+    struct hop* hop = new_hop(current_bb, NULL);
+    hop->vregmapping = heap_alloc(&proc_heap, 1, sizeof(struct hashtable));;
+    *hop->vregmapping = empty_hashtable_of_values;
+    hop->is_move = true;
+
+    struct hashtable_iterator hit = {};
+    while (hashtable_next(previous_mapping, &hit))
+    {
+        struct value* value = hit.key;
+        struct vreg* oldvreg = hit.value;
+        struct vreg* newvreg = create_vreg(value);
+        hashtable_put(hop->vregmapping, value, newvreg);
+        pmap_add(&hop->copies, oldvreg, newvreg);
+    }
+
+    return hop;
+}
+
 static bool hop_reads_value(struct hop* hop, struct value* value)
 {
     int i;
@@ -53,12 +78,16 @@ static void assign_vregs(void)
     previous_mapping = current_bb->inputmapping;
     for (i=0; i<current_bb->hops.count; i++)
     {
-        hop = current_bb->hops.item[i];
+        /* Insert a parallel-move hop to copy all the vregs. */
 
-        /* TODO: clone vregs here */
+        struct hop* move = create_move(previous_mapping);
+        array_insert(&current_bb->hops, move, i);
+        i++;
+        previous_mapping = move->vregmapping;
 
         /* Copy the previous mapping to this hop, pruning out any unused values. */
 
+        hop = current_bb->hops.item[i];
         current_mapping = hop->vregmapping = heap_alloc(&proc_heap, 1, sizeof(struct hashtable));;
         *current_mapping = empty_hashtable_of_values;
         {
@@ -81,7 +110,11 @@ static void assign_vregs(void)
         previous_mapping = current_mapping;
     }
 
-    current_bb->outputmapping = previous_mapping;
+    /* Insert one final move at the end of the block. */
+
+    hop = create_move(previous_mapping);
+    array_append(&current_bb->hops, hop);
+    current_bb->outputmapping = hop->vregmapping;
 }
 
 void pass_assign_vregs(void)