aboutsummaryrefslogtreecommitdiff
path: root/cfg.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <[email protected]>2017-02-27 10:34:22 -0500
committerQuentin Carbonneaux <[email protected]>2017-02-27 10:34:29 -0500
commite80252a52bf25f762bc986ce6e4e0d17fbb130d0 (patch)
tree06b476558944a83d6c3e11ecc322a568caf1fe94 /cfg.c
parent3aecf460f5ab60c96ba90042ffd1cd7df41eeca5 (diff)
scrub assembly output
Notably, this adds a new pass to get rid of jumps on jumps.
Diffstat (limited to 'cfg.c')
-rw-r--r--cfg.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/cfg.c b/cfg.c
index e210589..e695f39 100644
--- a/cfg.c
+++ b/cfg.c
@@ -278,3 +278,47 @@ fillloop(Fn *fn)
b->loop = 1;
loopiter(fn, multloop);
}
+
+static void
+uffind(Blk **pb, Blk **uf, Fn *fn)
+{
+ Blk **pb1;
+
+ pb1 = &uf[(*pb)->id];
+ if (*pb1 != *pb)
+ uffind(pb1, uf, fn);
+ *pb = *pb1;
+}
+
+/* requires rpo and no phis, breaks cfg */
+void
+simpljmp(Fn *fn)
+{
+
+ Blk **uf; /* union-find */
+ Blk *b;
+ uint n;
+ int c;
+
+ uf = alloc(fn->nblk * sizeof uf[0]);
+ for (n=0; n<fn->nblk; n++)
+ uf[n] = fn->rpo[n];
+ for (b=fn->start; b; b=b->link) {
+ assert(!b->phi);
+ if (b->nins == 0)
+ if (b->jmp.type == Jjmp)
+ uf[b->id] = b->s1;
+ }
+ for (b=fn->start; b; b=b->link) {
+ if (b->s1)
+ uffind(&b->s1, uf, fn);
+ if (b->s2)
+ uffind(&b->s2, uf, fn);
+ c = b->jmp.type - Jxjc;
+ if (0 <= c && c <= NXICmp)
+ if (b->s1 == b->s2) {
+ b->jmp.type = Jjmp;
+ b->s2 = 0;
+ }
+ }
+}