Keep track of which vregs need to be in real registers (i.e. are being used to
authorDavid Given <dg@cowlark.com>
Fri, 20 Jan 2017 20:28:32 +0000 (21:28 +0100)
committerDavid Given <dg@cowlark.com>
Fri, 20 Jan 2017 20:28:32 +0000 (21:28 +0100)
do work) and which ones aren't (and so can be spilt). Do some long-needed
cleanup and removal of dead code.

mach/proto/mcg/mcg.h
mach/proto/mcg/pass_prologueepilogue.c
mach/proto/mcg/pass_registerallocator.c
mach/proto/mcg/pass_spillibility.c [new file with mode: 0644]
mach/proto/mcg/pass_splitliveranges.c [deleted file]
mach/proto/mcg/pass_vregusage.c [deleted file]
mach/proto/mcg/procedure.c
mach/proto/mcg/reg.h

index 19f2590..692127e 100644 (file)
@@ -108,11 +108,11 @@ extern void tb_procedure(void);
 extern void tb_regvar(struct procedure* proc, arith offset, int size, int type, int priority);
 
 extern void pass_assign_vregs(void);
+extern void pass_calculate_vreg_spillibility(void);
 extern void pass_convert_inputs_to_phis(void);
 extern void pass_convert_locals_to_ssa(void);
 extern void pass_convert_nonlocal_phis(void);
 extern void pass_convert_stack_ops(void);
-extern void pass_determine_vreg_usage(void);
 extern void pass_eliminate_trivial_blocks(void);
 extern void pass_find_phi_congruence_groups(void);
 extern void pass_group_irs(void);
@@ -125,7 +125,6 @@ extern void pass_register_allocator(void);
 extern void pass_remove_dead_blocks(void);
 extern void pass_remove_dead_phis(void);
 extern void pass_split_critical_edges(void);
-extern void pass_split_live_ranges(void);
 extern void pass_wire_up_return_values(void);
 
 extern void platform_calculate_offsets(void);
index 3b0c517..30e452d 100644 (file)
@@ -4,32 +4,32 @@ void pass_add_prologue_epilogue(void)
 {
     int i, j, k;
 
-    current_proc->usedregs.count = 0;
-    for (i=0; i<cfg.preorder.count; i++)
-    {
-        struct basicblock* bb = cfg.preorder.item[i];
-
-        for (j=0; j<bb->hops.count; j++)
-        {
-            struct hop* hop = bb->hops.item[j];
-
-            for (k=0; k<hop->regsin.count; k++)
-            {
-                struct hreg* hreg = hop->regsin.item[k].left;
-                if (!hreg->is_stacked)
-                    array_appendu(&current_proc->usedregs, hreg);
-            }
-
-            for (k=0; k<hop->regsout.count; k++)
-            {
-                struct hreg* hreg = hop->regsout.item[k].left;
-                if (!hreg->is_stacked)
-                    array_appendu(&current_proc->usedregs, hreg);
-            }
-        }
-    }
-
-       platform_calculate_offsets();
+    // current_proc->usedregs.count = 0;
+    // for (i=0; i<cfg.preorder.count; i++)
+    // {
+    //     struct basicblock* bb = cfg.preorder.item[i];
+
+    //     for (j=0; j<bb->hops.count; j++)
+    //     {
+    //         struct hop* hop = bb->hops.item[j];
+
+    //         for (k=0; k<hop->regsin.count; k++)
+    //         {
+    //             struct hreg* hreg = hop->regsin.item[k].left;
+    //             if (!hreg->is_stacked)
+    //                 array_appendu(&current_proc->usedregs, hreg);
+    //         }
+
+    //         for (k=0; k<hop->regsout.count; k++)
+    //         {
+    //             struct hreg* hreg = hop->regsout.item[k].left;
+    //             if (!hreg->is_stacked)
+    //                 array_appendu(&current_proc->usedregs, hreg);
+    //         }
+    //     }
+    // }
+
+       // platform_calculate_offsets();
 
        array_insert(&current_proc->entry->hops, platform_prologue(), 0);
 
index 1c435e9..05f48e3 100644 (file)
@@ -8,7 +8,7 @@
  * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.32.5924
  */
 
-static const int DEGREE = 10;
+static const int DEGREE = 5;
 
 static struct graph interference;
 static struct graph affinity;
@@ -89,6 +89,8 @@ static void generate_graph(void)
 static void dump_vreg(struct vreg* vreg)
 {
     fprintf(regalloc_dot_file, "[%%%d]", vreg->id);
+    if (!vreg->needs_register)
+        fprintf(regalloc_dot_file, "S");
 }
 
 static void dump_interference_graph(void)
@@ -176,7 +178,7 @@ static bool attempt_to_coalesce(void)
     if (degree > DEGREE)
         return false;
 
-    tracef('R', "R: lowest degree affinity edge: %%%d->%%%d, degree %d\n",
+    tracef('R', "R: coalescing affinity edge: %%%d->%%%d, degree %d\n",
         v1->id, v2->id, degree);
     coalesce(v1, v2);
 
@@ -189,6 +191,11 @@ static bool attempt_to_coalesce(void)
     return true;
 }
 
+static bool attempt_to_simplify(void)
+{
+    return false;
+}
+
 static void iterate(void)
 {
     struct anode* spill;
@@ -201,8 +208,8 @@ static void iterate(void)
         if (attempt_to_coalesce())
             continue;
 
-        // if (attempt_to_simplify())
-        //     continue;
+        if (attempt_to_simplify())
+            continue;
 
         // if (attempt_to_spill_or_simplify())
         //     continue;
@@ -216,7 +223,7 @@ void pass_register_allocator(void)
     wire_together_bbs();
     generate_graph();
 
-    iterate();
+    //iterate();
 
     dump_interference_graph();
 
diff --git a/mach/proto/mcg/pass_spillibility.c b/mach/proto/mcg/pass_spillibility.c
new file mode 100644 (file)
index 0000000..f434dc0
--- /dev/null
@@ -0,0 +1,43 @@
+#include "mcg.h"
+
+static struct basicblock* current_bb;
+
+static void calculate_spillibility(void)
+{
+    int i;
+
+    for (i=0; i<current_bb->hops.count; i++)
+    {
+        struct hop* hop = current_bb->hops.item[i];
+        if (!hop->is_move)
+        {
+            struct hashtable_iterator hit = {};
+            while (hashtable_next(hop->valueusage, &hit))
+            {
+                struct value* value = hit.key;
+                struct valueusage* usage = hit.value;
+
+                if (!usage->through)
+                {
+                    if (usage->invreg)
+                        usage->invreg->needs_register = true;
+                    if (usage->outvreg)
+                        usage->outvreg->needs_register = true;
+                }
+            }
+        }
+    }
+}
+
+void pass_calculate_vreg_spillibility(void)
+{
+    int i;
+
+    for (i=0; i<dominance.preorder.count; i++)
+    {
+        current_bb = dominance.preorder.item[i];
+        calculate_spillibility();
+    }
+}
+
+/* vim: set sw=4 ts=4 expandtab : */
diff --git a/mach/proto/mcg/pass_splitliveranges.c b/mach/proto/mcg/pass_splitliveranges.c
deleted file mode 100644 (file)
index a37ca6d..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-#include "mcg.h"
-
-static struct basicblock* current_bb;
-
-static void rewrite_vregs(struct basicblock* bb,
-        int pos, struct vreg* src, struct vreg* dest)
-{
-    int i, j;
-
-    while (pos < bb->hops.count)
-    {
-        struct hop* hop = bb->hops.item[pos];
-
-        array_replace(&hop->ins, src, dest);
-        array_replace(&hop->throughs, src, dest);
-        array_replace(&hop->outs, src, dest);
-
-        for (i=0; i<hop->insels.count; i++)
-        {
-            struct insel* insel = hop->insels.item[i];
-            if ((insel->type == INSEL_VREG) && (insel->u.vreg == src))
-                insel->u.vreg = dest;
-        }
-        
-        for (i=0; i<hop->constraints.count; i++)
-        {
-            struct constraint* c = hop->constraints.item[i].right;
-
-            if (hop->constraints.item[i].left == src)
-                hop->constraints.item[i].left = dest;
-
-            if (c->equals_to == src)
-                c->equals_to = dest;
-        }
-
-        pos++;
-    }
-
-    for (i=0; i<bb->nexts.count; i++)
-    {
-        struct basicblock* nextbb = bb->nexts.item[i];
-
-        for (j=0; j<nextbb->phis.count; j++)
-        {
-            struct phi* phi = nextbb->phis.item[j].right;
-            if (phi->ir->result == src)
-                phi->ir->result = dest;
-        }
-    }
-}
-
-static void rewrite_blocks(struct basicblock* startbb, int startindex,
-        struct vreg* src, struct vreg* dest)
-{
-    int i;
-
-    for (i=0; i<dominance.preorder.count; i++)
-    {
-        struct basicblock* bb = dominance.preorder.item[i];
-        if (bb == startbb)
-            break;
-    }
-    assert(i < dominance.preorder.count);
-
-    while (i < dominance.preorder.count)
-    {
-        struct basicblock* bb = dominance.preorder.item[i];
-        rewrite_vregs(bb, startindex, src, dest);
-        startindex = 0;
-        i++;
-    }
-}
-
-static int insert_move_after(int index, struct vreg* src)
-{
-    struct vreg* dest;
-    struct hop* copy;
-
-    dest = new_vreg();
-    dest->type = src->type;
-    copy = new_copy_hop(current_bb, src, dest);
-
-    array_insert(&current_bb->hops, copy, index+1);
-
-    rewrite_blocks(current_bb, index+2, src, dest);
-    return 1;
-}
-
-void pass_split_live_ranges(void)
-{
-    int i, j, k;
-
-    for (i=0; i<dominance.preorder.count; i++)
-    {
-        current_bb = dominance.preorder.item[i];
-
-        for (j=0; j<current_bb->hops.count; j++)
-        {
-            struct hop* hop = current_bb->hops.item[j];
-
-            if (!hop->is_move)
-            {
-                for (k=0; k<hop->ins.count; k++)
-                {
-                    struct vreg* vreg = hop->ins.item[k];
-                    j += insert_move_after(j-1, vreg);
-                }
-
-                for (k=0; k<hop->outs.count; k++)
-                {
-                    struct vreg* vreg = hop->outs.item[k];
-                    insert_move_after(j, vreg);
-                }
-
-                for (k=0; k<hop->ins.count; k++)
-                {
-                    struct vreg* vreg = hop->ins.item[k];
-                    j += insert_move_after(j, vreg);
-                }
-            }
-        }
-    }
-}
-
-/* vim: set sw=4 ts=4 expandtab : */
\ No newline at end of file
diff --git a/mach/proto/mcg/pass_vregusage.c b/mach/proto/mcg/pass_vregusage.c
deleted file mode 100644 (file)
index e8d400f..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "mcg.h"
-
-static struct set vregs;
-
-static void assign_uses_cb(struct hop* hop, void* user)
-{
-    int i;
-
-    for (i=0; i<hop->ins.count; i++)
-        array_appendu(&hop->ins.item[i]->usedhops, hop);
-
-    for (i=0; i<hop->outs.count; i++)
-    {
-        struct vreg* vreg = hop->outs.item[i];
-        assert(vreg->defined == NULL);
-        vreg->defined = hop;
-        set_add(&vregs, vreg);
-    }
-}
-
-static bool is_spillable_vreg(struct vreg* vreg)
-{
-    int i;
-
-    if (vreg->defined && !vreg->defined->is_move)
-        return false;
-    
-    for (i=0; i<vreg->usedhops.count; i++)
-        if (!vreg->usedhops.item[i]->is_move)
-            return false;
-
-    return true;
-}
-
-void pass_determine_vreg_usage(void)
-{
-    int i, j;
-
-    set_empty(&vregs);
-    hop_walk(assign_uses_cb, NULL);
-
-    for (i=0; i<dominance.preorder.count; i++)
-    {
-        struct basicblock* bb = dominance.preorder.item[i];
-        for (j=0; j<bb->phis.count; j++)
-        {
-            struct vreg* dest = bb->phis.item[j].left;
-            struct phi* phi = bb->phis.item[j].right;
-            struct vreg* src = phi->ir->result;
-            array_appendu(&src->usedphis, bb);
-            set_add(&vregs, src);
-            set_add(&vregs, dest);
-        }
-    }
-
-    {
-        struct set_iterator sit = {};
-        while (set_next(&vregs, &sit))
-        {
-            struct vreg* vreg = sit.item;
-            vreg->is_spillable = is_spillable_vreg(vreg);
-        }
-    }
-}
-
-/* vim: set sw=4 ts=4 expandtab : */
index cb9ba62..8216072 100644 (file)
@@ -222,12 +222,10 @@ void procedure_compile(struct procedure* proc)
     pass_live_value_analysis();
     print_hops('8');
     pass_assign_vregs();
+    pass_calculate_vreg_spillibility();
     print_hops('9');
     pass_register_allocator();
 #if 0
-    pass_split_live_ranges();
-    pass_determine_vreg_usage();
-
     pass_add_prologue_epilogue();
     print_hops('9');
 
index 63c23b3..d8e4053 100644 (file)
@@ -18,6 +18,7 @@ struct vreg
     int id;
     struct value* value;
     struct vreg* coalesced_with;
+    bool needs_register;
 };
 
 extern struct hreg* new_hreg(const struct burm_register_data* brd);