| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- #include "all.h"
- Blk *
- newblk()
- {
- static Blk z;
- Blk *b;
- b = alloc(sizeof *b);
- *b = z;
- b->ins = vnew(0, sizeof b->ins[0], PFn);
- b->pred = vnew(0, sizeof b->pred[0], PFn);
- return b;
- }
- static void
- fixphis(Fn *f)
- {
- Blk *b;
- Phi *p;
- uint n, n0;
- for (b=f->start; b; b=b->link) {
- assert(b->id < f->nblk);
- for (p=b->phi; p; p=p->link) {
- for (n=n0=0; n<p->narg; n++)
- if (p->blk[n]->id != -1u) {
- p->blk[n0] = p->blk[n];
- p->arg[n0] = p->arg[n];
- n0++;
- }
- assert(n0 > 0);
- p->narg = n0;
- }
- }
- }
- static void
- addpred(Blk *bp, Blk *b)
- {
- vgrow(&b->pred, ++b->npred);
- b->pred[b->npred-1] = bp;
- }
- void
- fillpreds(Fn *f)
- {
- Blk *b;
- for (b=f->start; b; b=b->link)
- b->npred = 0;
- for (b=f->start; b; b=b->link) {
- if (b->s1)
- addpred(b, b->s1);
- if (b->s2 && b->s2 != b->s1)
- addpred(b, b->s2);
- }
- }
- static void
- porec(Blk *b, uint *npo)
- {
- Blk *s1, *s2;
- if (!b || b->id != -1u)
- return;
- b->id = 0; /* marker */
- s1 = b->s1;
- s2 = b->s2;
- if (s1 && s2 && s1->loop > s2->loop) {
- s1 = b->s2;
- s2 = b->s1;
- }
- porec(s1, npo);
- porec(s2, npo);
- b->id = (*npo)++;
- }
- static void
- fillrpo(Fn *f)
- {
- Blk *b, **p;
- for (b=f->start; b; b=b->link)
- b->id = -1u;
- f->nblk = 0;
- porec(f->start, &f->nblk);
- vgrow(&f->rpo, f->nblk);
- for (p=&f->start; (b=*p);) {
- if (b->id == -1u) {
- *p = b->link;
- } else {
- b->id = f->nblk-b->id-1;
- f->rpo[b->id] = b;
- p = &b->link;
- }
- }
- }
- /* fill rpo, preds; prune dead blks */
- void
- fillcfg(Fn *f)
- {
- fillrpo(f);
- fillpreds(f);
- fixphis(f);
- }
- /* for dominators computation, read
- * "A Simple, Fast Dominance Algorithm"
- * by K. Cooper, T. Harvey, and K. Kennedy.
- */
- static Blk *
- inter(Blk *b1, Blk *b2)
- {
- Blk *bt;
- if (b1 == 0)
- return b2;
- while (b1 != b2) {
- if (b1->id < b2->id) {
- bt = b1;
- b1 = b2;
- b2 = bt;
- }
- while (b1->id > b2->id) {
- b1 = b1->idom;
- assert(b1);
- }
- }
- return b1;
- }
- void
- filldom(Fn *fn)
- {
- Blk *b, *d;
- int ch;
- uint n, p;
- for (b=fn->start; b; b=b->link) {
- b->idom = 0;
- b->dom = 0;
- b->dlink = 0;
- }
- do {
- ch = 0;
- for (n=1; n<fn->nblk; n++) {
- b = fn->rpo[n];
- d = 0;
- for (p=0; p<b->npred; p++)
- if (b->pred[p]->idom
- || b->pred[p] == fn->start)
- d = inter(d, b->pred[p]);
- if (d != b->idom) {
- ch++;
- b->idom = d;
- }
- }
- } while (ch);
- for (b=fn->start; b; b=b->link)
- if ((d=b->idom)) {
- assert(d != b);
- b->dlink = d->dom;
- d->dom = b;
- }
- }
- int
- sdom(Blk *b1, Blk *b2)
- {
- assert(b1 && b2);
- if (b1 == b2)
- return 0;
- while (b2->id > b1->id)
- b2 = b2->idom;
- return b1 == b2;
- }
- int
- dom(Blk *b1, Blk *b2)
- {
- return b1 == b2 || sdom(b1, b2);
- }
- static void
- addfron(Blk *a, Blk *b)
- {
- uint n;
- for (n=0; n<a->nfron; n++)
- if (a->fron[n] == b)
- return;
- if (!a->nfron)
- a->fron = vnew(++a->nfron, sizeof a->fron[0], PFn);
- else
- vgrow(&a->fron, ++a->nfron);
- a->fron[a->nfron-1] = b;
- }
- /* fill the dominance frontier */
- void
- fillfron(Fn *fn)
- {
- Blk *a, *b;
- for (b=fn->start; b; b=b->link)
- b->nfron = 0;
- for (b=fn->start; b; b=b->link) {
- if (b->s1)
- for (a=b; !sdom(a, b->s1); a=a->idom)
- addfron(a, b->s1);
- if (b->s2)
- for (a=b; !sdom(a, b->s2); a=a->idom)
- addfron(a, b->s2);
- }
- }
- static void
- loopmark(Blk *hd, Blk *b, void f(Blk *, Blk *))
- {
- uint p;
- if (b->id < hd->id || b->visit == hd->id)
- return;
- b->visit = hd->id;
- f(hd, b);
- for (p=0; p<b->npred; ++p)
- loopmark(hd, b->pred[p], f);
- }
- void
- loopiter(Fn *fn, void f(Blk *, Blk *))
- {
- uint n, p;
- Blk *b;
- for (b=fn->start; b; b=b->link)
- b->visit = -1u;
- for (n=0; n<fn->nblk; ++n) {
- b = fn->rpo[n];
- for (p=0; p<b->npred; ++p)
- if (b->pred[p]->id >= n)
- loopmark(b, b->pred[p], f);
- }
- }
- /* dominator tree depth */
- void
- filldepth(Fn *fn)
- {
- Blk *b, *d;
- int depth;
- for (b=fn->start; b; b=b->link)
- b->depth = -1;
- fn->start->depth = 0;
- for (b=fn->start; b; b=b->link) {
- if (b->depth != -1)
- continue;
- depth = 1;
- for (d=b->idom; d->depth==-1; d=d->idom)
- depth++;
- depth += d->depth;
- b->depth = depth;
- for (d=b->idom; d->depth==-1; d=d->idom)
- d->depth = --depth;
- }
- }
- /* least common ancestor in dom tree */
- Blk *
- lca(Blk *b1, Blk *b2)
- {
- if (!b1)
- return b2;
- if (!b2)
- return b1;
- while (b1->depth > b2->depth)
- b1 = b1->idom;
- while (b2->depth > b1->depth)
- b2 = b2->idom;
- while (b1 != b2) {
- b1 = b1->idom;
- b2 = b2->idom;
- }
- return b1;
- }
- void
- multloop(Blk *hd, Blk *b)
- {
- (void)hd;
- b->loop *= 10;
- }
- void
- fillloop(Fn *fn)
- {
- Blk *b;
- for (b=fn->start; b; b=b->link)
- b->loop = 1;
- loopiter(fn, multloop);
- }
- static void
- uffind(Blk **pb, Blk **uf)
- {
- Blk **pb1;
- pb1 = &uf[(*pb)->id];
- if (*pb1) {
- uffind(pb1, uf);
- *pb = *pb1;
- }
- }
- /* requires rpo and no phis, breaks cfg */
- void
- simpljmp(Fn *fn)
- {
- Blk **uf; /* union-find */
- Blk **p, *b, *ret;
- ret = newblk();
- ret->id = fn->nblk++;
- ret->jmp.type = Jret0;
- uf = emalloc(fn->nblk * sizeof uf[0]);
- for (b=fn->start; b; b=b->link) {
- assert(!b->phi);
- if (b->jmp.type == Jret0) {
- b->jmp.type = Jjmp;
- b->s1 = ret;
- }
- if (b->nins == 0)
- if (b->jmp.type == Jjmp) {
- uffind(&b->s1, uf);
- if (b->s1 != b)
- uf[b->id] = b->s1;
- }
- }
- for (p=&fn->start; (b=*p); p=&b->link) {
- if (b->s1)
- uffind(&b->s1, uf);
- if (b->s2)
- uffind(&b->s2, uf);
- if (b->s1 && b->s1 == b->s2) {
- b->jmp.type = Jjmp;
- b->s2 = 0;
- }
- }
- *p = ret;
- free(uf);
- }
- static int
- reachrec(Blk *b, Blk *to)
- {
- if (b == to)
- return 1;
- if (!b || b->visit)
- return 0;
- b->visit = 1;
- if (reachrec(b->s1, to))
- return 1;
- if (reachrec(b->s2, to))
- return 1;
- return 0;
- }
- /* Blk.visit needs to be clear at entry */
- int
- reaches(Fn *fn, Blk *b, Blk *to)
- {
- int r;
- assert(to);
- r = reachrec(b, to);
- for (b=fn->start; b; b=b->link)
- b->visit = 0;
- return r;
- }
- /* can b reach 'to' not through excl
- * Blk.visit needs to be clear at entry */
- int
- reachesnotvia(Fn *fn, Blk *b, Blk *to, Blk *excl)
- {
- excl->visit = 1;
- return reaches(fn, b, to);
- }
|