+++ /dev/null
-#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 : */
-
+++ /dev/null
-#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 : */
-
--- /dev/null
+#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 : */
+
--- /dev/null
+#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 : */
+
#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];
#include "mcg.h"
-static PMAPOF(struct basicblock, struct basicblock) graph;
static ARRAYOF(struct ir) pops;
static ARRAYOF(struct ir) pushes;
/* 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);
}
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);
}
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;
#include "mcg.h"
-static struct basicblock* entry;
static PMAPOF(struct basicblock, struct basicblock) dominancefrontiers;
static struct local* current_local;
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++)
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);
}
}
}
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;
/* 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];
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++)
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 : */