diff --git a/mach/proto/mcg/basicblock.h b/mach/proto/mcg/basicblock.h index 7935c9ede..75aa38e84 100644 --- a/mach/proto/mcg/basicblock.h +++ b/mach/proto/mcg/basicblock.h @@ -10,7 +10,7 @@ struct basicblock 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; diff --git a/mach/proto/mcg/dominance.c b/mach/proto/mcg/dominance.c new file mode 100644 index 000000000..9843f376c --- /dev/null +++ b/mach/proto/mcg/dominance.c @@ -0,0 +1,123 @@ +#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; inexts.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; iname); + } +} + +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; jprevs.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 %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 new file mode 100644 index 000000000..ee5d39b68 --- /dev/null +++ b/mach/proto/mcg/dominance.h @@ -0,0 +1,13 @@ +#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/mcg.h b/mach/proto/mcg/mcg.h index 601249f07..1fdb7d96c 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -27,6 +27,7 @@ #include "reg.h" #include "basicblock.h" #include "procedure.h" +#include "dominance.h" extern char em_pseu[][4]; extern char em_mnem[][4]; diff --git a/mach/proto/mcg/pass_ssa.c b/mach/proto/mcg/pass_ssa.c index 265ade1f5..2a030b132 100644 --- a/mach/proto/mcg/pass_ssa.c +++ b/mach/proto/mcg/pass_ssa.c @@ -1,8 +1,6 @@ #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; @@ -11,110 +9,6 @@ static ARRAYOF(struct basicblock) needsphis; 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; inexts.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; iname); - } -} - -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; jprevs.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 %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: @@ -324,9 +218,7 @@ void pass_convert_locals_to_ssa(struct procedure* proc) 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; ilocals.count; i++) diff --git a/mach/proto/mcg/registerallocator.c b/mach/proto/mcg/registerallocator.c index eae72fac6..664245826 100644 --- a/mach/proto/mcg/registerallocator.c +++ b/mach/proto/mcg/registerallocator.c @@ -2,32 +2,31 @@ 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; inexts.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; iblocks.item[0]); + assert(blocks.count == proc->blocks.count); } /* vim: set sw=4 ts=4 expandtab : */