#include "mcg.h" static PMAPOF(struct basicblock, struct ir) pops; static PMAPOF(struct basicblock, struct ir) pushes; static struct ir* get_last_push(struct basicblock* bb) { int i; for (i=bb->irs.count-1; i>=0; i--) { struct ir* ir = bb->irs.item[i]; if (ir->opcode == IR_PUSH) return ir; if (ir_find(ir, IR_POP)) return NULL; } return NULL; } static struct ir* get_first_pop(struct basicblock* bb) { int i; for (i=0; iirs.count; i++) { struct ir* irr; struct ir* ir = bb->irs.item[i]; if (ir->opcode == IR_PUSH) return NULL; irr = ir_find(ir, IR_POP); if (irr) return irr; } return NULL; } static void convert_block(struct basicblock* bb) { int i, j; struct ir* ir; pushes.count = pops.count = 0; for (;;) { struct ir* lastpush = get_last_push(bb); if (!lastpush) return; /* Abort unless *every* successor block of this one starts with a pop * of the same size... */ for (i=0; inexts.count; i++) { struct basicblock* outbb = bb->nexts.item[i]; ir = get_first_pop(outbb); if (!ir || (ir->size != lastpush->size)) return; pmap_add(&pops, outbb, ir); /* Also abort unless *every* predecessor block of the one we've * just found *also* ends in a push of the same size. */ for (j=0; jprevs.count; j++) { struct basicblock* inbb = outbb->prevs.item[j]; ir = get_last_push(inbb); if (!ir || (ir->size != lastpush->size)) return; pmap_add(&pushes, inbb, ir); } } /* If we didn't actually find anything, give up. */ if ((pushes.count == 0) || (pops.count == 0)) return; /* Okay, now we can wire them all up. */ for (i=0; ileft; } for (i=0; isize); for (j=0; ju.phivalue, pushes.item[j].left, pushes.item[j].right); phi->root = phi; *ir = *phi; } } } void pass_convert_stack_ops(void) { int i; for (i=0; i