From: David Given Date: Tue, 4 Oct 2016 21:42:00 +0000 (+0200) Subject: Add a pass to do critical edge splitting. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=ac62c34e1975c56055af20a1ee4d42455ece3bde;p=ack.git Add a pass to do critical edge splitting. --- diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index a5fa1102c..dc70028c9 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -100,13 +100,14 @@ extern void tb_fileend(void); extern void tb_procedure(struct procedure* proc); extern void tb_regvar(struct procedure* proc, arith offset, int size, int type, int priority); +extern void pass_convert_locals_to_ssa(struct procedure* proc); extern void pass_convert_stack_ops(struct procedure* proc); -extern void pass_remove_dead_blocks(struct procedure* proc); extern void pass_eliminate_trivial_blocks(struct procedure* proc); +extern void pass_group_irs(struct procedure* proc); extern void pass_instruction_selector(struct procedure* proc); extern void pass_promote_float_ops(struct procedure* proc); -extern void pass_group_irs(struct procedure* proc); -extern void pass_convert_locals_to_ssa(struct procedure* proc); +extern void pass_remove_dead_blocks(struct procedure* proc); +extern void pass_split_critical_edges(struct procedure* proc); #endif diff --git a/mach/proto/mcg/pass_splitcriticaledges.c b/mach/proto/mcg/pass_splitcriticaledges.c new file mode 100644 index 000000000..a7fa63ee9 --- /dev/null +++ b/mach/proto/mcg/pass_splitcriticaledges.c @@ -0,0 +1,91 @@ +#include "mcg.h" + +/* Insert empty nodes at certain places in the basic block graph so that when + * we convert out of SSA form, we have somewhere to insert copies. This is + * necessary for correctness in certain circumstances. The best explanation of + * why I've found is here, starting at the bottom of page 23. + * + * Briggs, Preston, et al. + * "Practical improvements to the construction and destruction of static single assignment form." + * Software-Practice and experience 28.8 (1998): 859-882. + * + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.25.749 + */ + +static struct procedure* current_proc; + +struct rewrite_params +{ + struct basicblock* find; + struct basicblock* replace; +}; + +static bool find_replace_cb(struct ir* ir, void* user) +{ + struct rewrite_params* rwp = user; + + if ((ir->opcode == IR_BLOCK) && (ir->u.bvalue == rwp->find)) + ir->u.bvalue = rwp->replace; + + return false; +} + +static void split_edge(struct basicblock* source, struct basicblock* sink) +{ + int i; + struct rewrite_params rwp; + struct basicblock* bb = bb_get(NULL); + + array_append(&bb->irs, + new_ir1( + IR_JUMP, 0, + new_bbir(sink) + ) + ); + + rwp.find = sink; + rwp.replace = bb; + + for (i=0; iirs.count; i++) + ir_walk(source->irs.item[i], find_replace_cb, &rwp); + + array_remove(&source->nexts, sink); + array_append(&source->nexts, bb); + + array_append(&bb->prevs, source); + array_append(&bb->nexts, sink); + + array_remove(&sink->prevs, source); + array_append(&sink->prevs, bb); + + array_append(¤t_proc->blocks, bb); +} + +static void consider_edges_leading_to(struct basicblock* bb) +{ + if (bb->prevs.count > 1) + { + int i; + + for (i=0; iprevs.count; i++) + { + struct basicblock* prev = bb->prevs.item[i]; + if (prev->nexts.count > 1) + split_edge(prev, bb); + } + } +} + +void pass_split_critical_edges(struct procedure* proc) +{ + int i; + + current_proc = proc; + + for (i=0; iblocks.count; i++) + consider_edges_leading_to(proc->blocks.item[i]); +} + +/* vim: set sw=4 ts=4 expandtab : */ + + diff --git a/mach/proto/mcg/procedure.c b/mach/proto/mcg/procedure.c index 5ea0372b9..8fbccd5d6 100644 --- a/mach/proto/mcg/procedure.c +++ b/mach/proto/mcg/procedure.c @@ -15,7 +15,23 @@ static void print_blocks(char k, struct procedure* proc) bb->is_fake ? "FAKE " : "", bb->name); - for (int j=0; jirs.count; j++) + if (bb->prevs.count > 0) + { + tracef(k, "%c: FROM:", k); + for (j=0; jprevs.count; j++) + tracef(k, " %s", bb->prevs.item[j]->name); + tracef(k, "\n"); + } + + if (bb->nexts.count > 0) + { + tracef(k, "%c: TO:", k); + for (j=0; jnexts.count; j++) + tracef(k, " %s", bb->nexts.item[j]->name); + tracef(k, "\n"); + } + + for (j=0; jirs.count; j++) ir_print(k, bb->irs.item[j]); } } @@ -40,8 +56,10 @@ void procedure_compile(struct procedure* proc) print_blocks('3', proc); pass_convert_locals_to_ssa(proc); print_blocks('4', proc); - pass_promote_float_ops(proc); + pass_split_critical_edges(proc); print_blocks('5', proc); + pass_promote_float_ops(proc); + print_blocks('6', proc); pass_instruction_selector(proc);