Refactor the cfg and dominance stuff to make it a lot nicer.
authorDavid Given <dg@cowlark.com>
Thu, 6 Oct 2016 19:34:21 +0000 (21:34 +0200)
committerDavid Given <dg@cowlark.com>
Thu, 6 Oct 2016 19:34:21 +0000 (21:34 +0200)
mach/proto/mcg/dominance.c [deleted file]
mach/proto/mcg/dominance.h [deleted file]
mach/proto/mcg/graph.c [new file with mode: 0644]
mach/proto/mcg/graph.h [new file with mode: 0644]
mach/proto/mcg/mcg.h
mach/proto/mcg/pass_convertstackops.c
mach/proto/mcg/pass_registerallocator.c
mach/proto/mcg/pass_splitcriticaledges.c
mach/proto/mcg/pass_ssa.c
mach/proto/mcg/procedure.c

diff --git a/mach/proto/mcg/dominance.c b/mach/proto/mcg/dominance.c
deleted file mode 100644 (file)
index 9843f37..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-#include "mcg.h"
-
-struct array postorder;
-struct array preorder;
-struct pmap dominators;
-
-static void recursively_walk_blocks(struct basicblock* bb);
-
-static void recursively_walk_graph(struct basicblock* bb)
-{
-    static ARRAYOF(struct basicblock) pending;
-    int i;
-
-    if (array_contains(&postorder, bb) || array_contains(&pending, bb))
-        return;
-
-    array_appendu(&preorder, bb);
-    array_appendu(&pending, bb);
-
-    i = 0;
-    for (i=0; i<bb->nexts.count; i++)
-        recursively_walk_graph(bb->nexts.item[i]);
-
-    array_remove(&pending, bb);
-    bb->order = postorder.count;
-    array_appendu(&postorder, bb);
-}
-
-static void walk_graph_postorder(struct basicblock* entry)
-{
-    int i;
-
-    preorder.count = 0;
-    postorder.count = 0;
-    recursively_walk_graph(entry);
-
-    for (i=0; i<postorder.count; i++)
-    {
-        tracef('D', "D: postorder: %s\n",
-            ((struct basicblock*)postorder.item[i])->name);
-    }
-}
-
-static struct basicblock* intersect(struct basicblock* p1, struct basicblock* p2)
-{
-    while (p1 != p2)
-    {
-        while (p1->order < p2->order)
-            p1 = pmap_get(&dominators, p1);
-
-        while (p2->order < p1->order)
-            p2 = pmap_get(&dominators, p2);
-    }
-
-    return p1;
-}
-
-void calculate_dominance_graph(struct procedure* proc)
-{
-    /* This is the algorithm described here:
-     *
-     * Cooper, Keith D., Timothy J. Harvey, and Ken Kennedy.
-     * "A simple, fast dominance algorithm."
-     * Software Practice & Experience 4.1-10 (2001): 1-8.
-     *
-     * https://www.cs.rice.edu/~keith/EMBED/dom.pdf
-     */
-
-    int i, j;
-    bool changed;
-    struct basicblock* entry = proc->blocks.item[0];
-
-    entry = proc->blocks.item[0];
-    walk_graph_postorder(entry);
-    assert(postorder.count == proc->blocks.count);
-
-    dominators.count = 0;
-
-    /* The entry block dominates itself. */
-
-    pmap_put(&dominators, entry, entry);
-
-    do
-    {
-        changed = false;
-
-        for (i = postorder.count-2; i >= 0; i--)
-        {
-            struct basicblock* b = postorder.item[i];
-            struct basicblock* new_idom = NULL;
-            for (j=0; j<b->prevs.count; j++)
-            {
-                struct basicblock* p = b->prevs.item[j];
-                
-                /* Skip unprocessed blocks. */
-                if (!pmap_get(&dominators, p))
-                    continue;
-
-                if (!new_idom)
-                    new_idom = p;
-                else if (pmap_get(&dominators, p))
-                    new_idom = intersect(p, new_idom);
-            }
-
-            if (pmap_get(&dominators, b) != new_idom)
-            {
-                pmap_put(&dominators, b, new_idom);
-                changed = true;
-            }
-        }
-    }
-    while (changed);
-
-    for (i=0; i<dominators.count; i++)
-    {
-        tracef('D', "D: domination: %s -> %s\n",
-            ((struct basicblock*)dominators.item[i].left)->name,
-            ((struct basicblock*)dominators.item[i].right)->name);
-    }
-}
-
-/* vim: set sw=4 ts=4 expandtab : */
-
diff --git a/mach/proto/mcg/dominance.h b/mach/proto/mcg/dominance.h
deleted file mode 100644 (file)
index ee5d39b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef DOMINANCE_H
-#define DOMINANCE_H
-
-extern struct array postorder;
-extern struct array preorder;
-extern struct pmap dominators;
-
-extern void calculate_dominance_graph(struct procedure* proc);
-
-#endif
-
-/* vim: set sw=4 ts=4 expandtab : */
-
diff --git a/mach/proto/mcg/graph.c b/mach/proto/mcg/graph.c
new file mode 100644 (file)
index 0000000..2897bc7
--- /dev/null
@@ -0,0 +1,208 @@
+#include "mcg.h"
+
+struct graph_data cfg;
+struct dominance_data dominance;
+
+static ARRAYOF(struct basicblock) pending;
+
+static bool collect_outputs_cb(struct ir* ir, void* user)
+{
+    struct basicblock* caller = user;
+
+    if (ir->opcode == IR_BLOCK)
+    {
+        array_appendu(&caller->nexts, ir->u.bvalue);
+        array_appendu(&ir->u.bvalue->prevs, caller);
+    }
+    return false;
+}
+
+static void update_block_pointers_from_ir(struct procedure* proc)
+{
+    int i, j;
+
+    for (i=0; i<proc->blocks.count; i++)
+    {
+        struct basicblock* bb = proc->blocks.item[i];
+        bb->prevs.count = bb->nexts.count = 0;
+    }
+
+    for (i=0; i<proc->blocks.count; i++)
+    {
+        struct basicblock* bb = proc->blocks.item[i];
+        for (j=0; j<bb->irs.count; j++)
+            ir_walk(bb->irs.item[j], collect_outputs_cb, bb);
+    }
+
+    for (i=0; i<proc->blocks.count; i++)
+    {
+        struct basicblock* bb = proc->blocks.item[i];
+
+        for (j=0; j<bb->nexts.count; j++)
+        {
+            tracef('D', "D: cfg graph %s -> %s\n",
+                bb->name,
+                bb->nexts.item[j]->name);
+        }
+    }
+}
+
+static void recursively_walk_cfg_graph(struct basicblock* bb)
+{
+    int i;
+
+    if (array_contains(&cfg.postorder, bb) || array_contains(&pending, bb))
+        return;
+
+    array_appendu(&cfg.preorder, bb);
+    array_appendu(&pending, bb);
+
+    for (i=0; i<bb->nexts.count; i++)
+        recursively_walk_cfg_graph(bb->nexts.item[i]);
+
+    array_remove(&pending, bb);
+    bb->order = cfg.postorder.count;
+    array_appendu(&cfg.postorder, bb);
+}
+
+static void walk_cfg_graph(void)
+{
+    int i;
+
+    cfg.preorder.count = 0;
+    cfg.postorder.count = 0;
+    pending.count = 0;
+    recursively_walk_cfg_graph(cfg.entry);
+
+    for (i=0; i<cfg.preorder.count; i++)
+    {
+        tracef('G', "G: cfg preorder: %s\n",
+            cfg.preorder.item[i]->name);
+    }
+}
+
+static struct basicblock* intersect(struct basicblock* p1, struct basicblock* p2)
+{
+    while (p1 != p2)
+    {
+        while (p1->order < p2->order)
+            p1 = pmap_get(&dominance.graph, p1);
+
+        while (p2->order < p1->order)
+            p2 = pmap_get(&dominance.graph, p2);
+    }
+
+    return p1;
+}
+
+static void calculate_dominance_graph(void)
+{
+    /* This is the algorithm described here:
+     *
+     * Cooper, Keith D., Timothy J. Harvey, and Ken Kennedy.
+     * "A simple, fast dominance algorithm."
+     * Software Practice & Experience 4.1-10 (2001): 1-8.
+     *
+     * https://www.cs.rice.edu/~keith/EMBED/dom.pdf
+     */
+
+    int i, j;
+    bool changed;
+
+    dominance.graph.count = 0;
+
+    /* The entry block dominates itself. */
+
+    pmap_put(&dominance.graph, cfg.entry, cfg.entry);
+
+    do
+    {
+        changed = false;
+
+        for (i = cfg.postorder.count-2; i >= 0; i--)
+        {
+            struct basicblock* b = cfg.postorder.item[i];
+            struct basicblock* new_idom = NULL;
+            for (j=0; j<b->prevs.count; j++)
+            {
+                struct basicblock* p = b->prevs.item[j];
+                
+                /* Skip unprocessed blocks. */
+                if (!pmap_get(&dominance.graph, p))
+                    continue;
+
+                if (!new_idom)
+                    new_idom = p;
+                else if (pmap_get(&dominance.graph, p))
+                    new_idom = intersect(p, new_idom);
+            }
+
+            if (pmap_get(&dominance.graph, b) != new_idom)
+            {
+                pmap_put(&dominance.graph, b, new_idom);
+                changed = true;
+            }
+        }
+    }
+    while (changed);
+
+    for (i=0; i<dominance.graph.count; i++)
+    {
+        tracef('G', "G: dominance graph: %s -> %s\n",
+            dominance.graph.item[i].right->name,
+            dominance.graph.item[i].left->name);
+    }
+}
+
+static void recursively_walk_dominance_graph(struct basicblock* bb)
+{
+    int i;
+
+    if (array_contains(&dominance.postorder, bb) || array_contains(&pending, bb))
+        return;
+
+    array_appendu(&dominance.preorder, bb);
+    array_appendu(&pending, bb);
+
+    for (i=0; i<dominance.graph.count; i++)
+        if (dominance.graph.item[i].right == bb)
+            recursively_walk_dominance_graph(dominance.graph.item[i].left);
+
+    array_remove(&pending, bb);
+    array_appendu(&dominance.postorder, bb);
+}
+
+static void walk_dominance_graph(void)
+{
+    int i;
+
+    dominance.preorder.count = 0;
+    dominance.postorder.count = 0;
+    pending.count = 0;
+    recursively_walk_dominance_graph(cfg.entry);
+
+    for (i=0; i<dominance.preorder.count; i++)
+    {
+        tracef('G', "G: dominance preorder: %s\n",
+            dominance.preorder.item[i]->name);
+    }
+}
+
+void update_graph_data(struct procedure* proc)
+{
+    cfg.entry = proc->blocks.item[0];
+    update_block_pointers_from_ir(proc);
+
+    walk_cfg_graph();
+    assert(cfg.postorder.count == proc->blocks.count);
+    assert(cfg.preorder.count == proc->blocks.count);
+
+    calculate_dominance_graph();
+    
+    walk_dominance_graph();
+    assert(dominance.postorder.count == dominance.graph.count);
+    assert(dominance.preorder.count == dominance.graph.count);
+}
+
+/* vim: set sw=4 ts=4 expandtab : */
+
diff --git a/mach/proto/mcg/graph.h b/mach/proto/mcg/graph.h
new file mode 100644 (file)
index 0000000..59c9313
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef GRAPH_H
+#define GRAPH_H
+
+struct graph_data
+{
+    struct basicblock* entry;
+    ARRAYOF(struct basicblock) preorder;
+    ARRAYOF(struct basicblock) postorder;
+};
+
+struct dominance_data
+{
+    PMAPOF(struct basicblock, struct basicblock) graph;
+    ARRAYOF(struct basicblock) preorder;
+    ARRAYOF(struct basicblock) postorder;
+};
+
+extern struct graph_data cfg;
+extern struct dominance_data dominance;
+
+extern void update_graph_data(struct procedure* proc);
+
+#endif
+
+/* vim: set sw=4 ts=4 expandtab : */
+
index 5d631e2..bad088e 100644 (file)
@@ -27,7 +27,7 @@
 #include "reg.h"
 #include "basicblock.h"
 #include "procedure.h"
-#include "dominance.h"
+#include "graph.h"
 
 extern char em_pseu[][4];
 extern char em_mnem[][4];
index d555b58..dbc1f82 100644 (file)
@@ -1,6 +1,5 @@
 #include "mcg.h"
 
-static PMAPOF(struct basicblock, struct basicblock) graph;
 static ARRAYOF(struct ir) pops;
 static ARRAYOF(struct ir) pushes;
 
index 27e4214..23121bc 100644 (file)
@@ -11,10 +11,10 @@ static void recursively_walk_dominance_graph(struct basicblock* bb)
 
        /* Skip the entry block (which is its own dominator). */
        
-       for (i=1; i<dominators.count; i++)
+       for (i=1; i<dominance.graph.count; i++)
        {
-               struct basicblock* left = dominators.item[i].left;
-               struct basicblock* right = dominators.item[i].right;
+               struct basicblock* left = dominance.graph.item[i].left;
+               struct basicblock* right = dominance.graph.item[i].right;
                if (right == bb)
                        recursively_walk_dominance_graph(left);
        }
@@ -22,10 +22,8 @@ static void recursively_walk_dominance_graph(struct basicblock* bb)
 
 void pass_register_allocator(struct procedure* proc)
 {
-       calculate_dominance_graph(proc);
-
        blocks.count = 0;
-       recursively_walk_dominance_graph(proc->blocks.item[0]);
+       recursively_walk_dominance_graph(cfg.entry);
        assert(blocks.count == proc->blocks.count);
 }
 
index 9237be7..7962974 100644 (file)
@@ -36,12 +36,14 @@ static void split_edge(struct basicblock* source, struct basicblock* sink)
        struct rewrite_params rwp;
        struct basicblock* bb = bb_get(NULL);
        
-       array_append(&bb->irs,
+    struct ir* jump = 
                new_ir1(
                        IR_JUMP, 0,
                        new_bbir(sink)
-               )
-       );
+               );
+
+    jump->root = jump->left->root = jump;
+       array_append(&bb->irs, jump);
 
        rwp.find = sink;
        rwp.replace = bb;
index 2a030b1..0f7fc2d 100644 (file)
@@ -1,6 +1,5 @@
 #include "mcg.h"
 
-static struct basicblock* entry;
 static PMAPOF(struct basicblock, struct basicblock) dominancefrontiers;
 
 static struct local* current_local;
@@ -24,10 +23,10 @@ static void calculate_dominance_frontier_graph(void)
 
     dominancefrontiers.count = 0;
 
-    for (i=0; i<postorder.count; i++)
+    for (i=0; i<cfg.postorder.count; i++)
     {
-        struct basicblock* b = postorder.item[i];
-        struct basicblock* dominator = pmap_get(&dominators, b);
+        struct basicblock* b = cfg.postorder.item[i];
+        struct basicblock* dominator = pmap_get(&dominance.graph, b);
         if (b->prevs.count >= 2)
         {
             for (j=0; j<b->prevs.count; j++)
@@ -38,7 +37,7 @@ static void calculate_dominance_frontier_graph(void)
                     tracef('S', "S: %s is in %s's dominance frontier\n",
                         b->name, runner->name);
                     pmap_add(&dominancefrontiers, runner, b);
-                    runner = pmap_get(&dominators, runner);
+                    runner = pmap_get(&dominance.graph, runner);
                 }
             }
         }
@@ -158,7 +157,7 @@ static void ssa_convert(void)
         ir->left->root = ir;
         ir->right->root = ir;
         ir->right->left->root = ir;
-        array_insert(&entry->irs, ir, 0);
+        array_insert(&cfg.entry->irs, ir, 0);
     }
 
     defining.count = 0;
@@ -166,9 +165,9 @@ static void ssa_convert(void)
 
     /* Find everwhere where the variable is *defined*. */
 
-    for (i=0; i<postorder.count; i++)
+    for (i=0; i<cfg.postorder.count; i++)
     {
-        struct basicblock* bb = postorder.item[i];
+        struct basicblock* bb = cfg.postorder.item[i];
         for (j=0; j<bb->irs.count; j++)
         {
             struct ir* ir = bb->irs.item[j];
@@ -210,15 +209,13 @@ static void ssa_convert(void)
 
     definitions.count = 0;
     rewritten.count = 0;
-    recursively_rewrite_tree(entry);
+    recursively_rewrite_tree(cfg.entry);
 }
 
 void pass_convert_locals_to_ssa(struct procedure* proc)
 {
     int i;
 
-    entry = proc->blocks.item[0];
-    calculate_dominance_graph(proc);
     calculate_dominance_frontier_graph();
 
     for (i=0; i<proc->locals.count; i++)
index 8685df5..69aba0a 100644 (file)
@@ -48,66 +48,26 @@ void procedure_compile(struct procedure* proc)
     pass_eliminate_trivial_blocks(proc);
     pass_remove_dead_blocks(proc);
 
-    procedure_update_bb_graph(proc);
+    update_graph_data(proc);
 
     /* Passes from here on can't alter the BB graph without also updating prevs
-     * and nexts. */
+     * and nexts (and then calling update_graph_data()). */
 
     print_blocks('2', proc);
     pass_convert_stack_ops(proc);
     print_blocks('3', proc);
     pass_convert_locals_to_ssa(proc);
     print_blocks('4', proc);
-    pass_split_critical_edges(proc);
-    print_blocks('5', proc);
     pass_promote_float_ops(proc);
+    print_blocks('5', proc);
+    pass_split_critical_edges(proc);
     print_blocks('6', proc);
 
+    update_graph_data(proc);
+
     pass_instruction_selector(proc);
     pass_register_allocator(proc);
 }
 
-static bool collect_outputs_cb(struct ir* ir, void* user)
-{
-    struct basicblock* caller = user;
-
-    if (ir->opcode == IR_BLOCK)
-    {
-        array_appendu(&caller->nexts, ir->u.bvalue);
-        array_appendu(&ir->u.bvalue->prevs, caller);
-    }
-    return false;
-}
-
-void procedure_update_bb_graph(struct procedure* proc)
-{
-    int i, j;
-
-    for (i=0; i<proc->blocks.count; i++)
-    {
-        struct basicblock* bb = proc->blocks.item[i];
-        bb->prevs.count = bb->nexts.count = 0;
-    }
-
-    for (i=0; i<proc->blocks.count; i++)
-    {
-        struct basicblock* bb = proc->blocks.item[i];
-        for (j=0; j<bb->irs.count; j++)
-            ir_walk(bb->irs.item[j], collect_outputs_cb, bb);
-    }
-
-    for (i=0; i<proc->blocks.count; i++)
-    {
-        struct basicblock* bb = proc->blocks.item[i];
-
-        for (j=0; j<bb->nexts.count; j++)
-        {
-            tracef('G', "G: graph %s -> %s\n",
-                bb->name,
-                bb->nexts.item[j]->name);
-        }
-    }
-}
-
 /* vim: set sw=4 ts=4 expandtab : */