diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index a90bbb5ef..db4d570b3 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -104,6 +104,7 @@ extern void tb_regvar(struct procedure* proc, arith offset, int size, int type, extern void pass_convert_locals_to_ssa(struct procedure* proc); extern void pass_convert_stack_ops(struct procedure* proc); extern void pass_eliminate_trivial_blocks(struct procedure* proc); +extern void pass_find_phi_congruence_groups(void); extern void pass_group_irs(struct procedure* proc); extern void pass_instruction_selector(void); extern void pass_live_vreg_analysis(void); diff --git a/mach/proto/mcg/pass_phigroups.c b/mach/proto/mcg/pass_phigroups.c new file mode 100644 index 000000000..c773aa5ad --- /dev/null +++ b/mach/proto/mcg/pass_phigroups.c @@ -0,0 +1,85 @@ +#include "mcg.h" + +static PMAPOF(struct vreg, struct vreg) phimap; + +static void make_phimap(void) +{ + int i, j; + + phimap.count = 0; + for (i=0; iphis.count; j++) + { + struct vreg* vreg = bb->phis.item[j].left; + struct phi* phi = bb->phis.item[j].right; + struct vreg* prevvreg = phi->ir->result; + + pmap_add(&phimap, vreg, prevvreg); + } + } +} + +static void recursively_associate_group(struct phicongruence* c, struct vreg* vreg) +{ + int i; + + vreg->congruence = c; + array_appendu(&c->vregs, vreg); + tracef('V', "V: %%%d is a member of congruence group %d\n", + vreg->id, c->id); + + if (vreg->defined) + { + struct constraint* constraint = pmap_findleft(&vreg->defined->constraints, vreg); + if ((c->attrs == 0) || (constraint->attrs < c->attrs)) + c->attrs = constraint->attrs; + + array_appendu(&c->definitions, vreg->defined); + } + + for (;;) + { + struct vreg* child = pmap_findleft(&phimap, vreg); + if (!child) + break; + + pmap_remove(&phimap, vreg, child); + recursively_associate_group(c, child); + } + + for (;;) + { + struct vreg* child = pmap_findright(&phimap, vreg); + if (!child) + break; + + pmap_remove(&phimap, child, vreg); + recursively_associate_group(c, child); + } +} + +static void associate_groups(void) +{ + static int number = 0; + + while (phimap.count > 0) + { + struct phicongruence* c = calloc(1, sizeof(*c)); + c->id = number++; + recursively_associate_group(c, phimap.item[0].left); + } +} + +void pass_find_phi_congruence_groups(void) +{ + make_phimap(); + associate_groups(); +} + +/* vim: set sw=4 ts=4 expandtab : */ + + + diff --git a/mach/proto/mcg/pass_registerallocator.c b/mach/proto/mcg/pass_registerallocator.c index 0bacdd225..2e2ad0764 100644 --- a/mach/proto/mcg/pass_registerallocator.c +++ b/mach/proto/mcg/pass_registerallocator.c @@ -164,10 +164,9 @@ void pass_register_allocator(void) { struct vreg* vreg = bb->phis.item[j].left; struct phi* phi = bb->phis.item[j].right; - if (!pmap_findright(old, vreg) && (vreg->used.count > 0)) + if (!pmap_findright(old, vreg)) { - struct hop* used = vreg->used.item[0]; - struct constraint* c = pmap_findleft(&used->constraints, vreg); + struct phicongruence* c = vreg->congruence; struct hreg* hreg = allocate_hreg(old, vreg, c->attrs); tracef('R', "R: import fallback hreg %s for phi input %%%d from %s\n", diff --git a/mach/proto/mcg/procedure.c b/mach/proto/mcg/procedure.c index b2970b67b..329c384d3 100644 --- a/mach/proto/mcg/procedure.c +++ b/mach/proto/mcg/procedure.c @@ -168,6 +168,7 @@ void procedure_compile(struct procedure* proc) pass_instruction_selector(); print_hops('7', proc); + pass_find_phi_congruence_groups(); pass_live_vreg_analysis(); print_hops('8', proc); pass_register_allocator(); diff --git a/mach/proto/mcg/reg.h b/mach/proto/mcg/reg.h index 743b9c3e5..fc72f2ae0 100644 --- a/mach/proto/mcg/reg.h +++ b/mach/proto/mcg/reg.h @@ -3,6 +3,14 @@ #define WITH_ATTR(a) (1<<(a)) +struct phicongruence +{ + int id; + ARRAYOF(struct vreg) vregs; + ARRAYOF(struct hop) definitions; + uint32_t attrs; +}; + struct hreg { const char* name; @@ -14,6 +22,7 @@ struct hreg struct vreg { int id; + struct phicongruence* congruence; struct hop* defined; ARRAYOF(struct hop) used; };