ARRAYOF(struct basicblock) prevs;
ARRAYOF(struct basicblock) nexts;
- int order; /* used by SSA code */
+ int order; /* used by dominance graph code */
ARRAYOF(struct vreg) liveins;
--- /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 : */
+
#include "reg.h"
#include "basicblock.h"
#include "procedure.h"
+#include "dominance.h"
extern char em_pseu[][4];
extern char em_mnem[][4];
#include "mcg.h"
static struct basicblock* entry;
-static ARRAYOF(struct basicblock) postorder;
-static PMAPOF(struct basicblock, struct basicblock) dominators;
static PMAPOF(struct basicblock, struct basicblock) dominancefrontiers;
static struct local* current_local;
static ARRAYOF(struct ir) definitions;
static ARRAYOF(struct basicblock) rewritten;
-static void recursively_walk_blocks(struct basicblock* bb);
-
-static void recursively_walk_graph_postorder(struct basicblock* bb)
-{
- static ARRAYOF(struct basicblock) pending;
- int i;
-
- if (array_contains(&postorder, bb) || array_contains(&pending, bb))
- return;
-
- array_appendu(&pending, bb);
-
- i = 0;
- for (i=0; i<bb->nexts.count; i++)
- recursively_walk_graph_postorder(bb->nexts.item[i]);
-
- array_remove(&pending, bb);
- bb->order = postorder.count;
- array_appendu(&postorder, bb);
-}
-
-static void walk_graph_postorder()
-{
- int i;
-
- postorder.count = 0;
- recursively_walk_graph_postorder(entry);
-
- for (i=0; i<postorder.count; i++)
- {
- tracef('S', "S: postorder: %s\n",
- 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;
-}
-
-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;
-
- 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];
-
- 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('S', "S: domination: %s -> %s\n",
- dominators.item[i].left->name,
- dominators.item[i].right->name);
- }
-}
-
static void calculate_dominance_frontier_graph(void)
{
/* This is the algorithm described here:
int i;
entry = proc->blocks.item[0];
- walk_graph_postorder();
- assert(postorder.count == proc->blocks.count);
- calculate_dominance_graph();
+ calculate_dominance_graph(proc);
calculate_dominance_frontier_graph();
for (i=0; i<proc->locals.count; i++)
static ARRAYOF(struct basicblock) blocks;
-static void recursively_walk_blocks(struct basicblock* bb)
+static void recursively_walk_dominance_graph(struct basicblock* bb)
{
int i;
- if (array_appendu(&blocks, bb))
- return;
+ array_append(&blocks, bb);
tracef('R', "R: considering block %s\n", bb->name);
- for (i=0; i<bb->nexts.count; i++)
- recursively_walk_blocks(bb->nexts.item[i]);
-}
-
-static void order_blocks(struct procedure* proc)
-{
- /* Put them into preorder; this ensures that when we do the allocation,
- * we do all of a block's predecessors before the block (except for
- * backward edges). */
+ /* Skip the entry block (which is its own dominator). */
- blocks.count = 0;
- recursively_walk_blocks(proc->blocks.item[0]);
- assert(blocks.count == proc->blocks.count);
+ for (i=1; i<dominators.count; i++)
+ {
+ struct basicblock* left = dominators.item[i].left;
+ struct basicblock* right = dominators.item[i].right;
+ if (right == bb)
+ recursively_walk_dominance_graph(left);
+ }
}
void register_allocator(struct procedure* proc)
{
- order_blocks(proc);
+ calculate_dominance_graph(proc);
+
+ blocks.count = 0;
+ recursively_walk_dominance_graph(proc->blocks.item[0]);
+ assert(blocks.count == proc->blocks.count);
}
/* vim: set sw=4 ts=4 expandtab : */