| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- #include "all.h"
- void
- getalias(Alias *a, Ref r, Fn *fn)
- {
- Con *c;
- switch (rtype(r)) {
- default:
- die("unreachable");
- case RTmp:
- *a = fn->tmp[r.val].alias;
- if (astack(a->type))
- a->type = a->slot->type;
- assert(a->type != ABot);
- break;
- case RCon:
- c = &fn->con[r.val];
- if (c->type == CAddr) {
- a->type = ASym;
- a->u.sym = c->sym;
- } else
- a->type = ACon;
- a->offset = c->bits.i;
- a->slot = 0;
- break;
- }
- }
- int
- alias(Ref p, int op, int sp, Ref q, int sq, int *delta, Fn *fn)
- {
- Alias ap, aq;
- int ovlap;
- getalias(&ap, p, fn);
- getalias(&aq, q, fn);
- ap.offset += op;
- /* when delta is meaningful (ovlap == 1),
- * we do not overflow int because sp and
- * sq are bounded by 2^28 */
- *delta = ap.offset - aq.offset;
- ovlap = ap.offset < aq.offset + sq && aq.offset < ap.offset + sp;
- if (astack(ap.type) && astack(aq.type)) {
- /* if both are offsets of the same
- * stack slot, they alias iif they
- * overlap */
- if (ap.base == aq.base && ovlap)
- return MustAlias;
- return NoAlias;
- }
- if (ap.type == ASym && aq.type == ASym) {
- /* they conservatively alias if the
- * symbols are different, or they
- * alias for sure if they overlap */
- if (!symeq(ap.u.sym, aq.u.sym))
- return MayAlias;
- if (ovlap)
- return MustAlias;
- return NoAlias;
- }
- if ((ap.type == ACon && aq.type == ACon)
- || (ap.type == aq.type && ap.base == aq.base)) {
- assert(ap.type == ACon || ap.type == AUnk);
- /* if they have the same base, we
- * can rely on the offsets only */
- if (ovlap)
- return MustAlias;
- return NoAlias;
- }
- /* if one of the two is unknown
- * there may be aliasing unless
- * the other is provably local */
- if (ap.type == AUnk && aq.type != ALoc)
- return MayAlias;
- if (aq.type == AUnk && ap.type != ALoc)
- return MayAlias;
- return NoAlias;
- }
- int
- escapes(Ref r, Fn *fn)
- {
- Alias *a;
- if (rtype(r) != RTmp)
- return 1;
- a = &fn->tmp[r.val].alias;
- return !astack(a->type) || a->slot->type == AEsc;
- }
- static void
- esc(Ref r, Fn *fn)
- {
- Alias *a;
- assert(rtype(r) <= RType);
- if (rtype(r) == RTmp) {
- a = &fn->tmp[r.val].alias;
- if (astack(a->type))
- a->slot->type = AEsc;
- }
- }
- static void
- store(Ref r, int sz, Fn *fn)
- {
- Alias *a;
- int64_t off;
- bits m;
- if (rtype(r) == RTmp) {
- a = &fn->tmp[r.val].alias;
- if (a->slot) {
- assert(astack(a->type));
- off = a->offset;
- if (sz >= NBit
- || (off < 0 || off >= NBit))
- m = -1;
- else
- m = (BIT(sz) - 1) << off;
- a->slot->u.loc.m |= m;
- }
- }
- }
- void
- fillalias(Fn *fn)
- {
- uint n;
- int t, sz;
- int64_t x;
- Blk *b;
- Phi *p;
- Ins *i;
- Con *c;
- Alias *a, a0, a1;
- for (t=0; t<fn->ntmp; t++)
- fn->tmp[t].alias.type = ABot;
- for (n=0; n<fn->nblk; ++n) {
- b = fn->rpo[n];
- for (p=b->phi; p; p=p->link) {
- assert(rtype(p->to) == RTmp);
- a = &fn->tmp[p->to.val].alias;
- assert(a->type == ABot);
- a->type = AUnk;
- a->base = p->to.val;
- a->offset = 0;
- a->slot = 0;
- }
- for (i=b->ins; i<&b->ins[b->nins]; ++i) {
- a = 0;
- if (!req(i->to, R)) {
- assert(rtype(i->to) == RTmp);
- a = &fn->tmp[i->to.val].alias;
- assert(a->type == ABot);
- if (Oalloc <= i->op && i->op <= Oalloc1) {
- a->type = ALoc;
- a->slot = a;
- a->u.loc.sz = -1;
- if (rtype(i->arg[0]) == RCon) {
- c = &fn->con[i->arg[0].val];
- x = c->bits.i;
- if (c->type == CBits)
- if (0 <= x && x <= NBit)
- a->u.loc.sz = x;
- }
- } else {
- a->type = AUnk;
- a->slot = 0;
- }
- a->base = i->to.val;
- a->offset = 0;
- }
- if (i->op == Ocopy) {
- assert(a);
- getalias(a, i->arg[0], fn);
- }
- if (i->op == Oadd) {
- getalias(&a0, i->arg[0], fn);
- getalias(&a1, i->arg[1], fn);
- if (a0.type == ACon) {
- *a = a1;
- a->offset += a0.offset;
- }
- else if (a1.type == ACon) {
- *a = a0;
- a->offset += a1.offset;
- }
- }
- if (req(i->to, R) || a->type == AUnk)
- if (i->op != Oblit0) {
- if (!isload(i->op))
- esc(i->arg[0], fn);
- if (!isstore(i->op))
- if (i->op != Oargc)
- esc(i->arg[1], fn);
- }
- if (i->op == Oblit0) {
- ++i;
- assert(i->op == Oblit1);
- assert(rtype(i->arg[0]) == RInt);
- sz = abs(rsval(i->arg[0]));
- store((i-1)->arg[1], sz, fn);
- }
- if (isstore(i->op))
- store(i->arg[1], storesz(i), fn);
- }
- if (b->jmp.type != Jretc)
- esc(b->jmp.arg, fn);
- }
- for (b=fn->start; b; b=b->link)
- for (p=b->phi; p; p=p->link)
- for (n=0; n<p->narg; n++)
- esc(p->arg[n], fn);
- }
|