| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- #include "all.h"
- static int
- iscon(Ref r, int64_t bits, Fn *fn)
- {
- return rtype(r) == RCon
- && fn->con[r.val].type == CBits
- && fn->con[r.val].bits.i == bits;
- }
- static int
- iscopy(Ins *i, Ref r, Fn *fn)
- {
- static bits extcpy[] = {
- [WFull] = 0,
- [Wsb] = BIT(Wsb) | BIT(Wsh) | BIT(Wsw),
- [Wub] = BIT(Wub) | BIT(Wuh) | BIT(Wuw),
- [Wsh] = BIT(Wsh) | BIT(Wsw),
- [Wuh] = BIT(Wuh) | BIT(Wuw),
- [Wsw] = BIT(Wsw),
- [Wuw] = BIT(Wuw),
- };
- Op *op;
- bits b;
- Tmp *t;
- if (i->op == Ocopy)
- return 1;
- op = &optab[i->op];
- if (op->hasid && KBASE(i->cls) == 0)
- return iscon(i->arg[1], op->idval, fn);
- if (!isext(i->op) || rtype(r) != RTmp)
- return 0;
- if (i->op == Oextsw || i->op == Oextuw)
- if (i->cls == Kw)
- return 1;
- t = &fn->tmp[r.val];
- assert(KBASE(t->cls) == 0);
- if (i->cls == Kl && t->cls == Kw)
- return 0;
- b = extcpy[t->width];
- return (BIT(Wsb + (i->op-Oextsb)) & b) != 0;
- }
- static Ref
- copyof(Ref r, Ref *cpy)
- {
- if (rtype(r) == RTmp && !req(cpy[r.val], R))
- return cpy[r.val];
- return r;
- }
- /* detects a cluster of phis/copies redundant with 'r';
- * the algorithm is inspired by Section 3.2 of "Simple
- * and Efficient SSA Construction" by Braun M. et al.
- */
- static void
- phisimpl(Phi *p, Ref r, Ref *cpy, Use ***pstk, BSet *ts, BSet *as, Fn *fn)
- {
- Use **stk, *u, *u1;
- uint nstk, a;
- int t;
- Ref r1;
- Phi *p0;
- bszero(ts);
- bszero(as);
- p0 = &(Phi){.narg = 0};
- stk = *pstk;
- nstk = 1;
- stk[0] = &(Use){.type = UPhi, .u.phi = p};
- while (nstk) {
- u = stk[--nstk];
- if (u->type == UIns && iscopy(u->u.ins, r, fn)) {
- p = p0;
- t = u->u.ins->to.val;
- }
- else if (u->type == UPhi) {
- p = u->u.phi;
- t = p->to.val;
- }
- else
- continue;
- if (bshas(ts, t))
- continue;
- bsset(ts, t);
- for (a=0; a<p->narg; a++) {
- r1 = copyof(p->arg[a], cpy);
- if (req(r1, r))
- continue;
- if (rtype(r1) != RTmp)
- return;
- bsset(as, r1.val);
- }
- u = fn->tmp[t].use;
- u1 = &u[fn->tmp[t].nuse];
- vgrow(pstk, nstk+(u1-u));
- stk = *pstk;
- for (; u<u1; u++)
- stk[nstk++] = u;
- }
- bsdiff(as, ts);
- if (!bscount(as))
- for (t=0; bsiter(ts, &t); t++)
- cpy[t] = r;
- }
- static void
- subst(Ref *pr, Ref *cpy)
- {
- assert(rtype(*pr) != RTmp || !req(cpy[pr->val], R));
- *pr = copyof(*pr, cpy);
- }
- /* requires use and dom, breaks use */
- void
- copy(Fn *fn)
- {
- BSet ts[1], as[1];
- Use **stk;
- Phi *p, **pp;
- Ins *i;
- Blk *b;
- uint n, a, eq;
- Ref *cpy, r, r1;
- int t;
- bsinit(ts, fn->ntmp);
- bsinit(as, fn->ntmp);
- cpy = emalloc(fn->ntmp * sizeof cpy[0]);
- stk = vnew(10, sizeof stk[0], PHeap);
- /* 1. build the copy-of map */
- for (n=0; n<fn->nblk; n++) {
- b = fn->rpo[n];
- for (p=b->phi; p; p=p->link) {
- assert(rtype(p->to) == RTmp);
- if (!req(cpy[p->to.val], R))
- continue;
- eq = 0;
- r = R;
- for (a=0; a<p->narg; a++)
- if (p->blk[a]->id < n) {
- r1 = copyof(p->arg[a], cpy);
- if (req(r, R) || req(r, UNDEF))
- r = r1;
- if (req(r1, r) || req(r1, UNDEF))
- eq++;
- }
- assert(!req(r, R));
- if (rtype(r) == RTmp
- && !dom(fn->rpo[fn->tmp[r.val].bid], b))
- cpy[p->to.val] = p->to;
- else if (eq == p->narg)
- cpy[p->to.val] = r;
- else {
- cpy[p->to.val] = p->to;
- phisimpl(p, r, cpy, &stk, ts, as, fn);
- }
- }
- for (i=b->ins; i<&b->ins[b->nins]; i++) {
- assert(rtype(i->to) <= RTmp);
- if (!req(cpy[i->to.val], R))
- continue;
- r = copyof(i->arg[0], cpy);
- if (iscopy(i, r, fn))
- cpy[i->to.val] = r;
- else
- cpy[i->to.val] = i->to;
- }
- }
- /* 2. remove redundant phis/copies
- * and rewrite their uses */
- for (b=fn->start; b; b=b->link) {
- for (pp=&b->phi; (p=*pp);) {
- r = cpy[p->to.val];
- if (!req(r, p->to)) {
- *pp = p->link;
- continue;
- }
- for (a=0; a<p->narg; a++)
- subst(&p->arg[a], cpy);
- pp=&p->link;
- }
- for (i=b->ins; i<&b->ins[b->nins]; i++) {
- r = cpy[i->to.val];
- if (!req(r, i->to)) {
- *i = (Ins){.op = Onop};
- continue;
- }
- subst(&i->arg[0], cpy);
- subst(&i->arg[1], cpy);
- }
- subst(&b->jmp.arg, cpy);
- }
- if (debug['C']) {
- fprintf(stderr, "\n> Copy information:");
- for (t=Tmp0; t<fn->ntmp; t++) {
- if (req(cpy[t], R)) {
- fprintf(stderr, "\n%10s not seen!",
- fn->tmp[t].name);
- }
- else if (!req(cpy[t], TMP(t))) {
- fprintf(stderr, "\n%10s copy of ",
- fn->tmp[t].name);
- printref(cpy[t], fn, stderr);
- }
- }
- fprintf(stderr, "\n\n> After copy elimination:\n");
- printfn(fn, stderr);
- }
- vfree(stk);
- free(cpy);
- }
|