ack/mach/proto/mcg/pass_removedeadphis.c
David Given 4723a1442f Add code to remove unused phis, converting to pruned SSA form, to avoid
confusing the register allocator later.
2016-10-12 21:50:12 +02:00

89 lines
1.7 KiB
C

#include "mcg.h"
static ARRAYOF(struct ir) phis;
static bool changed;
static void collect_phis(struct basicblock* bb)
{
int i;
for (i=0; i<bb->irs.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; i<bb->irs.count; i++)
{
struct ir* ir = bb->irs.item[i];
switch (ir->opcode)
{
case IR_PHI:
for (j=0; j<ir->u.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; i<bb->irs.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<cfg.preorder.count; i++)
collect_phis(cfg.preorder.item[i]);
for (i=0; i<cfg.preorder.count; i++)
remove_referenced_phis(cfg.preorder.item[i]);
for (i=0; i<cfg.preorder.count; i++)
purge_unused_phis(cfg.preorder.item[i]);
}
while (changed);
}
/* vim: set sw=4 ts=4 expandtab : */