From: David Given Date: Mon, 12 Dec 2016 22:43:22 +0000 (+0100) Subject: Add standard functions for rewriting IRs (because we do that in several X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=dbfdc68fa3d2f52333c4e59274145ebaac429c7a;p=ack.git Add standard functions for rewriting IRs (because we do that in several places). --- diff --git a/mach/proto/mcg/ir.c b/mach/proto/mcg/ir.c index 550f97aad..1a7436f5c 100644 --- a/mach/proto/mcg/ir.c +++ b/mach/proto/mcg/ir.c @@ -169,4 +169,89 @@ void ir_print(char k, const struct ir* ir) tracef(k, "\n"); } +struct replacement_data +{ + struct ir* src; + struct ir* dest; + struct basicblock* source_bb; +}; + +static bool replace_irs_cb(struct ir* ir, void* user) +{ + struct replacement_data* rd = user; + + if (ir->left == rd->src) + ir->left = rd->dest; + if (ir->right == rd->src) + ir->right = rd->dest; + + return false; +} + +static bool replace_phis_cb(struct ir* ir, void* user) +{ + int i; + struct replacement_data* rd = user; + + if (ir->opcode != IR_PHI) + return true; + + for (i=0; iu.phivalue.count; i++) + { + if (ir->u.phivalue.item[i].right == rd->src) + { + ir->u.phivalue.item[i].right = rd->dest; + ir->u.phivalue.item[i].left = rd->source_bb; + } + } + + return false; +} + +/* Replaces IR references in this block, and any phis referring to the source IR in + * the block's successors --- but no further. */ +void ir_rewrite_single_block(struct basicblock* bb, struct ir* src, struct ir* dest) +{ + int i, j; + struct replacement_data rd; + + rd.src = src; + rd.dest = dest; + rd.source_bb = bb; + + for (i=0; iirs.count; i++) + { + struct ir* ir = bb->irs.item[i]; + ir_walk(ir, replace_irs_cb, &rd); + } + + for (i=0; inexts.count; i++) + { + struct basicblock* nextbb = bb->nexts.item[i]; + + for (j=0; jirs.count; j++) + { + struct ir* ir = nextbb->irs.item[j]; + ir_walk(ir, replace_phis_cb, &rd); + } + } +} + +/* Rewrites IR references in all blocks downstream in the dominance graph, and all phis + * in all nexts (which may be backreferences). */ +void ir_rewrite(struct basicblock* bb, struct ir* src, struct ir* dest) +{ + int i; + + ir_rewrite_single_block(bb, src, dest); + + for (i=0; i