diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index 567885886..0df947df7 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -112,6 +112,7 @@ extern void pass_live_vreg_analysis(void); extern void pass_promote_float_ops(struct procedure* proc); extern void pass_register_allocator(void); extern void pass_remove_dead_blocks(struct procedure* proc); +extern void pass_remove_dead_phis(void); extern void pass_split_critical_edges(struct procedure* proc); extern FILE* outputfile; diff --git a/mach/proto/mcg/pass_removedeadphis.c b/mach/proto/mcg/pass_removedeadphis.c new file mode 100644 index 000000000..b8b61fbbd --- /dev/null +++ b/mach/proto/mcg/pass_removedeadphis.c @@ -0,0 +1,88 @@ +#include "mcg.h" + +static ARRAYOF(struct ir) phis; +static bool changed; + +static void collect_phis(struct basicblock* bb) +{ + int i; + + for (i=0; iirs.count; i++) + { + struct ir* ir = bb->irs.item[i]; + if (ir->opcode == IR_PHI) + array_append(&phis, ir); + } +} + +static bool ir_walker_cb(struct ir* ir, void* user) +{ + if (ir->left) + array_remove(&phis, ir->left); + if (ir->right) + array_remove(&phis, ir->right); + + return false; +} + +static void remove_referenced_phis(struct basicblock* bb) +{ + int i, j; + + for (i=0; iirs.count; i++) + { + struct ir* ir = bb->irs.item[i]; + switch (ir->opcode) + { + case IR_PHI: + for (j=0; ju.phivalue.count; j++) + array_remove(&phis, ir->u.phivalue.item[j].right); + break; + + default: + ir_walk(ir, ir_walker_cb, NULL); + break; + } + } +} + +static void purge_unused_phis(struct basicblock* bb) +{ + int i; + + for (i=0; iirs.count; i++) + { + struct ir* ir = bb->irs.item[i]; + if ((ir->opcode == IR_PHI) && (array_contains(&phis, ir))) + { + array_remove(&bb->irs, ir); + i--; + changed = true; + } + } +} + +void pass_remove_dead_phis(void) +{ + int i; + + do + { + changed = false; + + phis.count = 0; + for (i=0; i