|
@@ -1,1117 +0,0 @@
|
|
|
-#include "gc.h"
|
|
|
-#include "bound.h"
|
|
|
-
|
|
|
-static BB* bbfree;
|
|
|
-static BBset* bbsfree;
|
|
|
-static int bballoc;
|
|
|
-static int bbsalloc;
|
|
|
-static BB bbz;
|
|
|
-static BBset bbsz;
|
|
|
-static BB* firstbb;
|
|
|
-static BB* lastbb;
|
|
|
-static BB* wounded;
|
|
|
-static BB* bbaux;
|
|
|
-static BBset* recalc;
|
|
|
-static BBset* bbhash[BBHASH];
|
|
|
-static BB** ordered;
|
|
|
-static int bcount;
|
|
|
-static BBset** heap;
|
|
|
-static int heapn;
|
|
|
-static int bsize;
|
|
|
-static char bbbuff[BBBSIZE];
|
|
|
-static int bchange;
|
|
|
-
|
|
|
-#define bdebug (debug['v'])
|
|
|
-#define dbg 0
|
|
|
-#define bcheck 0
|
|
|
-
|
|
|
-static long
|
|
|
-Rn(Reg *r)
|
|
|
-{
|
|
|
- if(r == R)
|
|
|
- return -1;
|
|
|
- return r->rpo;
|
|
|
-}
|
|
|
-
|
|
|
-static BB*
|
|
|
-bba(void)
|
|
|
-{
|
|
|
- BB *b;
|
|
|
-
|
|
|
- bballoc++;
|
|
|
- b = bbfree;
|
|
|
- if(b == nil) {
|
|
|
- b = alloc(sizeof(*b));
|
|
|
- } else
|
|
|
- bbfree = b->link;
|
|
|
-
|
|
|
- *b = bbz;
|
|
|
- return b;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-bfree(BB *b)
|
|
|
-{
|
|
|
- bballoc--;
|
|
|
- b->link = bbfree;
|
|
|
- bbfree = b;
|
|
|
-}
|
|
|
-
|
|
|
-static BBset*
|
|
|
-bbsa(void)
|
|
|
-{
|
|
|
- BBset *b;
|
|
|
-
|
|
|
- bballoc++;
|
|
|
- b = bbsfree;
|
|
|
- if(b == nil) {
|
|
|
- b = alloc(sizeof(*b));
|
|
|
- } else
|
|
|
- bbsfree = b->link;
|
|
|
-
|
|
|
- *b = bbsz;
|
|
|
- return b;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-bsfree(BBset *b)
|
|
|
-{
|
|
|
- bballoc--;
|
|
|
- b->link = bbsfree;
|
|
|
- bbsfree = b;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-dumpheap(void)
|
|
|
-{
|
|
|
- int i;
|
|
|
-
|
|
|
- for(i = 1; i <= heapn; i++)
|
|
|
- print(" %d", heap[i]->damage);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-checkheap(void)
|
|
|
-{
|
|
|
- int N, N2, n, c;
|
|
|
-
|
|
|
- N = heapn;
|
|
|
- N2 = N >> 1;
|
|
|
- for(n = 1; n <= N2; n++) {
|
|
|
- c = n << 1;
|
|
|
- if((heap[c]->damage > heap[n]->damage)
|
|
|
- || ((c < N) && (heap[c + 1]->damage > heap[n]->damage))) {
|
|
|
- print("bad heap (%d:%d) %d [", n, heap[n]->damage, heapn);
|
|
|
- dumpheap();
|
|
|
- print(" ]\n");
|
|
|
- abort();
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-downheap(int n)
|
|
|
-{
|
|
|
- int N, N2, d, c;
|
|
|
- BBset *s, *t, *u;
|
|
|
-
|
|
|
- s = heap[n];
|
|
|
- d = s->damage;
|
|
|
-//print("down %d %d", n, d);
|
|
|
- N = heapn;
|
|
|
- N2 = N >> 1;
|
|
|
- while(n <= N2) {
|
|
|
- c = n << 1;
|
|
|
- t = heap[c];
|
|
|
- if(c < N) {
|
|
|
- u = heap[c + 1];
|
|
|
- if(t->damage < u->damage) {
|
|
|
- t = u;
|
|
|
- c++;
|
|
|
- }
|
|
|
- }
|
|
|
-//print(" [%d %d]", c, t->damage);
|
|
|
- if(t->damage < d)
|
|
|
- break;
|
|
|
- heap[n] = t;
|
|
|
- t->index = n;
|
|
|
- n = c;
|
|
|
- }
|
|
|
- heap[n] = s;
|
|
|
- s->index = n;
|
|
|
-//print("\n");
|
|
|
-//checkheap();
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-upheap(int n)
|
|
|
-{
|
|
|
- int f, d;
|
|
|
- BBset *s, *t;
|
|
|
-
|
|
|
- s = heap[n];
|
|
|
- d = s->damage;
|
|
|
-//print("up %d %d", n, d);
|
|
|
- while(n > 1) {
|
|
|
- f = n >> 1;
|
|
|
- t = heap[f];
|
|
|
-//print(" [%d %d]", f, t->damage);
|
|
|
- if(t->damage >= d)
|
|
|
- break;
|
|
|
- heap[n] = t;
|
|
|
- t->index = n;
|
|
|
- n = f;
|
|
|
- }
|
|
|
- heap[n] = s;
|
|
|
- s->index = n;
|
|
|
-//print("\n");
|
|
|
-//checkheap();
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-heapremove(BBset *s)
|
|
|
-{
|
|
|
- int x;
|
|
|
- BBset *t;
|
|
|
-
|
|
|
- x = s->index;
|
|
|
- s->index = 0;
|
|
|
- if(x == 0)
|
|
|
- return;
|
|
|
- if(x == heapn) {
|
|
|
- heapn--;
|
|
|
- return;
|
|
|
- }
|
|
|
- t = heap[heapn--];
|
|
|
- heap[x] = t;
|
|
|
- t->index = x;
|
|
|
- if(s->damage < t->damage)
|
|
|
- upheap(x);
|
|
|
- else
|
|
|
- downheap(x);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-heapadd(BBset *s)
|
|
|
-{
|
|
|
- int n;
|
|
|
-
|
|
|
- n = heapn + 1;
|
|
|
- heap[n] = s;
|
|
|
- s->index = n;
|
|
|
- heapn = n;
|
|
|
- upheap(n);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-bbsrecalc(BBset *s)
|
|
|
-{
|
|
|
- if(s->recalc)
|
|
|
- return;
|
|
|
- s->recalc = 1;
|
|
|
- s->link = recalc;
|
|
|
- recalc = s;
|
|
|
- heapremove(s);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-bbadd(BB *b, Hval h)
|
|
|
-{
|
|
|
- int k;
|
|
|
- BBset *s;
|
|
|
-
|
|
|
- k = h[0] & BBMASK;
|
|
|
- for(s = bbhash[k]; s != nil; s = s->next) {
|
|
|
- if(BBEQ(s->hash, h)) {
|
|
|
- b->set = s;
|
|
|
- b->link = s->ents;
|
|
|
- s->ents = b;
|
|
|
- bbsrecalc(s);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- s = bbsa();
|
|
|
- s->next = bbhash[k];
|
|
|
- bbhash[k] = s;
|
|
|
- b->set = s;
|
|
|
- b->link = nil;
|
|
|
- s->ents = b;
|
|
|
- BBCP(s->hash, h);
|
|
|
- bbsrecalc(s);
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-hashbb(BB *b, Hval h)
|
|
|
-{
|
|
|
- Reg *r;
|
|
|
- Prog *p;
|
|
|
- char *s;
|
|
|
- int c, f, i, n;
|
|
|
-
|
|
|
- r = b->first;
|
|
|
- s = bbbuff;
|
|
|
- i = 0;
|
|
|
- n = BBBSIZE;
|
|
|
- for(;;) {
|
|
|
- p = r->prog;
|
|
|
- if(p->as != ANOP) {
|
|
|
- if(p->to.type == D_BRANCH)
|
|
|
- p->to.offset = r->s2->rpo;
|
|
|
- c = snprint(s, n, "%P", p);
|
|
|
- s += c;
|
|
|
- n -= c;
|
|
|
- i++;
|
|
|
- }
|
|
|
- if(r == b->last)
|
|
|
- break;
|
|
|
- r = r->link;
|
|
|
- }
|
|
|
- if(n == 0)
|
|
|
- return Bbig;
|
|
|
- b->len = i;
|
|
|
- BBMKHASH(bbbuff, BBBSIZE - n, h);
|
|
|
- f = b->flags;
|
|
|
- if(i == 1 && r->prog->as == AJMP && b->first->p1 == R)
|
|
|
- f = Bjo;
|
|
|
- else if(b->first->p1 != R)
|
|
|
- f |= Bpre;
|
|
|
- if(bdebug)
|
|
|
- print("A %x %s %ux %ux\n", f, bbbuff, h[0], h[1]);
|
|
|
- return f;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-enterbb(BB *b)
|
|
|
-{
|
|
|
- Hval h;
|
|
|
-
|
|
|
- b->flags = hashbb(b, h);
|
|
|
- if(b->flags != Bbig)
|
|
|
- bbadd(b, h);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-preproc(BB *b, int x)
|
|
|
-{
|
|
|
- BB *n;
|
|
|
- Reg *r;
|
|
|
-
|
|
|
- ordered[x] = b;
|
|
|
- if(b->last->rpo - b->first->rpo > BBBIG) {
|
|
|
- b->flags = Bbig;
|
|
|
- return;
|
|
|
- }
|
|
|
- if(b->first->p2 == nil) {
|
|
|
- b->flags = Bdel;
|
|
|
- return;
|
|
|
- }
|
|
|
- switch(b->last->prog->as) {
|
|
|
- case ARET:
|
|
|
- case AJMP:
|
|
|
- case AIRETL:
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- b->flags = Bdel;
|
|
|
- n = bba();
|
|
|
- n->first = b->first;
|
|
|
- for(r = b->last->link; r != R; r = r->link) {
|
|
|
- switch(r->prog->as) {
|
|
|
- case ARET:
|
|
|
- case AJMP:
|
|
|
- case AIRETL:
|
|
|
- n->last = r;
|
|
|
- n->flags = Bpin;
|
|
|
- enterbb(n);
|
|
|
- if(n->flags & Bpin) {
|
|
|
- n->aux = bbaux;
|
|
|
- bbaux = n;
|
|
|
- }
|
|
|
- else
|
|
|
- bfree(n);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- bfree(n);
|
|
|
- return;
|
|
|
- }
|
|
|
- enterbb(b);
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-p2len(Reg *r)
|
|
|
-{
|
|
|
- int c;
|
|
|
-
|
|
|
- c = 0;
|
|
|
- for(r = r->p2; r != nil; r = r->p2link)
|
|
|
- c++;
|
|
|
- return c;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-calcdamage(BBset *s)
|
|
|
-{
|
|
|
- BB *f;
|
|
|
- int d, t;
|
|
|
-
|
|
|
- s->recalc = 0;
|
|
|
- f = s->ents;
|
|
|
- if(f == nil)
|
|
|
- return;
|
|
|
- if(f->flags & Bjo) {
|
|
|
- if(bdebug)
|
|
|
- print("add %ld jo\n", f->first->rpo);
|
|
|
- s->damage = COSTJO;
|
|
|
- heapadd(s);
|
|
|
- return;
|
|
|
- }
|
|
|
- if(f->link == nil) {
|
|
|
- if(bdebug)
|
|
|
- print("solo %x %x\n", s->hash[0], s->hash[1]);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- d = 0;
|
|
|
- t = 0;
|
|
|
- while(f != nil) {
|
|
|
- if((f->flags & (Bpre|Bpin)) == 0 && f->last->link != R) {
|
|
|
- t = 1;
|
|
|
- d += (f->last->rpo - f->first->rpo) >> 1;
|
|
|
- }
|
|
|
- d += p2len(f->first);
|
|
|
- f = f->link;
|
|
|
- }
|
|
|
-
|
|
|
- if(t == 0) {
|
|
|
- if(bdebug)
|
|
|
- print("all pre %ld\n", s->ents->first->rpo);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if(bdebug)
|
|
|
- print("add %ld %d\n", s->ents->first->rpo, d);
|
|
|
- if(d > COSTHI)
|
|
|
- d = COSTHI;
|
|
|
- s->damage = d;
|
|
|
- heapadd(s);
|
|
|
-}
|
|
|
-
|
|
|
-static Reg*
|
|
|
-findjump(BB *b)
|
|
|
-{
|
|
|
- Reg *r, *l;
|
|
|
-
|
|
|
- r = b->first;
|
|
|
- l = b->last;
|
|
|
-
|
|
|
- for(;;) {
|
|
|
- if(r->prog->as == AJMP)
|
|
|
- break;
|
|
|
- if(r == l) {
|
|
|
- diag(Z, "findjump botch");
|
|
|
- break;
|
|
|
- }
|
|
|
- r = r->link;
|
|
|
- }
|
|
|
- return r;
|
|
|
-}
|
|
|
-
|
|
|
-static BB*
|
|
|
-findset(int r)
|
|
|
-{
|
|
|
- BB *s, **p;
|
|
|
- int n, n2;
|
|
|
-
|
|
|
- if(r < ordered[0]->first->rpo)
|
|
|
- return nil;
|
|
|
- n = bcount;
|
|
|
- p = ordered;
|
|
|
- while(n > 0) {
|
|
|
- n2 = n >> 1;
|
|
|
- s = p[n2];
|
|
|
- if(r < s->first->rpo) {
|
|
|
- n = n2;
|
|
|
- continue;
|
|
|
- }
|
|
|
- if(r > s->last->rpo) {
|
|
|
- n2++;
|
|
|
- p += n2;
|
|
|
- n -= n2;
|
|
|
- continue;
|
|
|
- }
|
|
|
- return s;
|
|
|
- }
|
|
|
- diag(Z, "findset botch");
|
|
|
- return nil;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-wound(Reg *r)
|
|
|
-{
|
|
|
- BB *b, *p, **n;
|
|
|
- BBset *s;
|
|
|
-
|
|
|
- b = findset(r->rpo);
|
|
|
- if(b == nil)
|
|
|
- return;
|
|
|
- s = b->set;
|
|
|
- if(s == nil)
|
|
|
- return;
|
|
|
- for(n = &s->ents; (p = *n) != nil; n = &(*n)->link) {
|
|
|
- if(p == b) {
|
|
|
- *n = b->link;
|
|
|
- b->link = wounded;
|
|
|
- wounded = b;
|
|
|
- bbsrecalc(s);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-printbl(Reg *l)
|
|
|
-{
|
|
|
- if(l == nil) {
|
|
|
- print("Z");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- print("%ld", l->rpo);
|
|
|
- while((l = l->p2link) != nil)
|
|
|
- print(" %ld", l->rpo);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-appset(Reg *e, Reg *s)
|
|
|
-{
|
|
|
- for(;;) {
|
|
|
- if(s->p2link == R) {
|
|
|
- s->p2link = e;
|
|
|
- return;
|
|
|
- }
|
|
|
- s = s->p2link;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static Reg*
|
|
|
-delset(Reg *e, Reg *s)
|
|
|
-{
|
|
|
- Reg *c, *l;
|
|
|
-
|
|
|
- c = s;
|
|
|
- l = nil;
|
|
|
- for(;;) {
|
|
|
- if(e == c) {
|
|
|
- if(l == nil)
|
|
|
- return s->p2link;
|
|
|
- l->p2link = c->p2link;
|
|
|
- return s;
|
|
|
- }
|
|
|
- l = c;
|
|
|
- c = c->p2link;
|
|
|
- if(c == nil)
|
|
|
- return s;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-redest(Reg *s, Reg *d)
|
|
|
-{
|
|
|
- while(s != R) {
|
|
|
- s->s2 = d;
|
|
|
- s = s->p2link;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-changedest(Reg *s, Reg *d, int x)
|
|
|
-{
|
|
|
- Reg *l;
|
|
|
-
|
|
|
- if(bdebug) {
|
|
|
- print("change %ld [", s->rpo);
|
|
|
- printbl(s->p2);
|
|
|
- print("] -> %ld [", d->rpo);
|
|
|
- printbl(d->p2);
|
|
|
- print("]\n");
|
|
|
- }
|
|
|
-
|
|
|
- if(s->p2 == nil) {
|
|
|
-// print("deadjmp\n");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- l = s->p2;
|
|
|
- for(;;) {
|
|
|
- if(bdebug)
|
|
|
- print("s2 %ld = %ld\n", l->rpo, d->rpo);
|
|
|
- l->s2 = d;
|
|
|
- wound(l);
|
|
|
- if(l->p2link == nil)
|
|
|
- break;
|
|
|
- l = l->p2link;
|
|
|
- }
|
|
|
-
|
|
|
- if(x) {
|
|
|
- l->p2link = delset(s, d->p2);
|
|
|
- d->p2 = s->p2;
|
|
|
- }
|
|
|
- else {
|
|
|
- l->p2link = d->p2;
|
|
|
- d->p2 = s->p2;
|
|
|
- s->p2 = nil;
|
|
|
- }
|
|
|
-
|
|
|
- if(bdebug) {
|
|
|
- print("result [");
|
|
|
- printbl(d->p2);
|
|
|
- print("]\n");
|
|
|
- }
|
|
|
-
|
|
|
- bchange = 1;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-bexcise(BB *b)
|
|
|
-{
|
|
|
- Reg *r, *l;
|
|
|
-
|
|
|
- l = b->last;
|
|
|
- r = b->first;
|
|
|
- if(bdebug)
|
|
|
- print("excise %ld to %ld\n", r->rpo, l->rpo);
|
|
|
- for(;;) {
|
|
|
- r->prog->as = ANOP;
|
|
|
- r->prog->to.type = D_NONE;
|
|
|
- r->p2 = R;
|
|
|
- if(r->s2 != R) {
|
|
|
- r->s2->p2 = delset(r, r->s2->p2);
|
|
|
- r->s2 = R;
|
|
|
- }
|
|
|
- if(r == l)
|
|
|
- break;
|
|
|
- r = r->link;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-backtrack(Reg *s, Reg *d)
|
|
|
-{
|
|
|
- int i;
|
|
|
- char l[BINST], r[BINST];
|
|
|
-
|
|
|
-//print("backtrack %ld %ld\n", Rn(s), Rn(d));
|
|
|
- i = 0;
|
|
|
- while(s != nil && d != nil) {
|
|
|
- if(snprint(l, BINST, "%P", s->prog) == BINST)
|
|
|
- break;
|
|
|
- if(snprint(r, BINST, "%P", d->prog) == BINST)
|
|
|
- break;
|
|
|
-//print("%s\t%s\n", l, r);
|
|
|
- if(strcmp(l, r) != 0)
|
|
|
- break;
|
|
|
- i++;
|
|
|
- s = s->p2link;
|
|
|
- d = d->p2link;
|
|
|
- }
|
|
|
- return i;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-checktails(void)
|
|
|
-{
|
|
|
- int c;
|
|
|
- Reg *r;
|
|
|
-
|
|
|
- c = 0;
|
|
|
- for(r = firstr; r->link != R; r = r->link) {
|
|
|
- if(r->prog->as == AJMP && r->s2 != nil)
|
|
|
- c += backtrack(r->p1, r->s2->p1);
|
|
|
- }
|
|
|
-
|
|
|
- if(c > 0)
|
|
|
- print("tails %s %d\n", firstr->prog->from.sym->name, c);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-process(BBset *s)
|
|
|
-{
|
|
|
- Reg *h;
|
|
|
- BB *f, *o, *p, *t;
|
|
|
-
|
|
|
- if(bdebug)
|
|
|
- print("process %d %x %x\n", s->damage, s->hash[0], s->hash[1]);
|
|
|
- f = s->ents;
|
|
|
- if(f->flags & Bjo) {
|
|
|
- s->ents = nil;
|
|
|
- h = findjump(f)->s2;
|
|
|
- o = nil;
|
|
|
- while(f != nil) {
|
|
|
- t = f->link;
|
|
|
- if((f->flags & Bjo) != 0 && f->first->s2 != f->first) {
|
|
|
- changedest(f->first, h, 1);
|
|
|
- bexcise(f);
|
|
|
- }
|
|
|
- else {
|
|
|
- f->link = o;
|
|
|
- o = f;
|
|
|
- }
|
|
|
- f = t;
|
|
|
- }
|
|
|
- s->ents = o;
|
|
|
- }
|
|
|
- else {
|
|
|
- o = nil;
|
|
|
- p = nil;
|
|
|
- while(f != nil) {
|
|
|
- t = f->link;
|
|
|
- if((f->flags & (Bpre|Bpin)) != 0 || (f->last->link == R)) {
|
|
|
- f->link = p;
|
|
|
- p = f;
|
|
|
- }
|
|
|
- else {
|
|
|
- f->link = o;
|
|
|
- o = f;
|
|
|
- }
|
|
|
- f = t;
|
|
|
- }
|
|
|
- if(o == nil) {
|
|
|
- diag(Z, "all Bpre");
|
|
|
- return;
|
|
|
- }
|
|
|
- if(p == nil) {
|
|
|
- p = o;
|
|
|
- o = p->link;
|
|
|
- p->link = nil;
|
|
|
- s->ents = p;
|
|
|
- }
|
|
|
- else
|
|
|
- s->ents = p;
|
|
|
-
|
|
|
- h = p->first;
|
|
|
- // oblit o list repl with jmp to h
|
|
|
- while(o != nil) {
|
|
|
- changedest(o->first, h, 1);
|
|
|
- bexcise(o);
|
|
|
- o = o->link;
|
|
|
- }
|
|
|
-
|
|
|
- bbsrecalc(s);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-iterate(void)
|
|
|
-{
|
|
|
- BBset *s;
|
|
|
- BB *b, *t;
|
|
|
-
|
|
|
- heapn = 0;
|
|
|
-
|
|
|
- for(;;) {
|
|
|
- for(b = wounded; b != nil; b = t) {
|
|
|
- t = b->link;
|
|
|
- enterbb(b);
|
|
|
- }
|
|
|
- wounded = nil;
|
|
|
-
|
|
|
- for(s = recalc; s != nil; s = s->link)
|
|
|
- calcdamage(s);
|
|
|
- recalc = nil;
|
|
|
-
|
|
|
- if(heapn == 0)
|
|
|
- return;
|
|
|
-
|
|
|
- s = heap[1];
|
|
|
- heapremove(s);
|
|
|
- process(s);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-cleanup(void)
|
|
|
-{
|
|
|
- int i;
|
|
|
- BB *l, *n;
|
|
|
- BBset *b, *t;
|
|
|
-
|
|
|
- for(i = 0; i < BBHASH; i++) {
|
|
|
- b = bbhash[i];
|
|
|
- bbhash[i] = nil;
|
|
|
- while(b != nil) {
|
|
|
- t = b->next;
|
|
|
- bsfree(b);
|
|
|
- b = t;
|
|
|
- }
|
|
|
- }
|
|
|
- for(i = 0; i < bcount; i++)
|
|
|
- bfree(ordered[i]);
|
|
|
- for(l = bbaux; l != nil; l = n) {
|
|
|
- n = l->aux;
|
|
|
- bfree(l);
|
|
|
- }
|
|
|
- bbaux = nil;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-prreg(Reg *r)
|
|
|
-{
|
|
|
- Prog *p;
|
|
|
-
|
|
|
- p = r->prog;
|
|
|
- if(p->to.type == D_BRANCH)
|
|
|
- p->to.offset = r->s2->rpo;
|
|
|
- print("%ld:%P\tr %lX ", r->rpo, r->prog, r->regu);
|
|
|
- print("p1 %ld p2 %ld p2l %ld s1 %ld s2 %ld link %ld",
|
|
|
- Rn(r->p1), Rn(r->p2), Rn(r->p2link),
|
|
|
- Rn(r->s1), Rn(r->s2), Rn(r->link));
|
|
|
- if(!r->active)
|
|
|
- print(" d");
|
|
|
-// print(" %p %p\n", r->prog, r->prog->link);
|
|
|
- print("\n");
|
|
|
-}
|
|
|
-
|
|
|
-static void prfunc(char*);
|
|
|
-
|
|
|
-static void
|
|
|
-checkr(int d)
|
|
|
-{
|
|
|
- Prog *p;
|
|
|
- Reg *r, *t;
|
|
|
-
|
|
|
- for(r = firstr; r->link != R; r = r->link) {
|
|
|
- for(p = r->prog->link; p != P && p != r->link->prog; p = p->link)
|
|
|
- ;
|
|
|
- if(p == P) {
|
|
|
- print("%ld: bad prog link\n", r->rpo);
|
|
|
- if(d)
|
|
|
- prfunc(nil);
|
|
|
- abort();
|
|
|
- }
|
|
|
- if(r->s1 != R && (r->s1 != r->link || r->link->p1 != r)) {
|
|
|
- print("%ld: bad s1 p1\n", r->rpo);
|
|
|
- if(d)
|
|
|
- prfunc(nil);
|
|
|
- abort();
|
|
|
- }
|
|
|
- if(r->s2 != R && r->s2->p2 == nil) {
|
|
|
- print("%ld: no p2 for s2\n", r->rpo);
|
|
|
- if(d)
|
|
|
- prfunc(nil);
|
|
|
- abort();
|
|
|
- }
|
|
|
- if(r->p2 != R) {
|
|
|
- t = r->p2->s2;
|
|
|
- while(t != r) {
|
|
|
- t = t->p2link;
|
|
|
- if(t == R) {
|
|
|
- print("%ld: bad s2 for p2\n", r->rpo);
|
|
|
- if(d)
|
|
|
- prfunc(nil);
|
|
|
- abort();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-prfunc(char *s)
|
|
|
-{
|
|
|
- Reg *r;
|
|
|
-
|
|
|
- if(s != nil)
|
|
|
- print("%s structure %s\n", s, firstr->prog->from.sym->name);
|
|
|
- for(r = firstr; r != R; r = r->link)
|
|
|
- prreg(r);
|
|
|
- if(s != nil) {
|
|
|
- print("end\n");
|
|
|
- checkr(0);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/* find p in r's list and replace with l */
|
|
|
-static void
|
|
|
-adjprog(Reg *r, Prog *p, Prog *l)
|
|
|
-{
|
|
|
- Prog *t, **n;
|
|
|
-
|
|
|
- for(n = &r->prog->link; (t = *n) != nil; n = &t->link) {
|
|
|
- if(t == p) {
|
|
|
- *n = l;
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- print("adjprog botch\n");
|
|
|
- abort();
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-jumptojump(void)
|
|
|
-{
|
|
|
- Reg *r;
|
|
|
-
|
|
|
- for(r = firstr; r != R; r = r->link) {
|
|
|
- if(r->prog->as == AJMP && r->p2 != R && r->s2 != r) {
|
|
|
- if(bdebug)
|
|
|
- print("jump as dest %ld -> %ld\n", r->rpo, r->s2->rpo);
|
|
|
- changedest(r, r->s2, 0);
|
|
|
- bchange++;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/* drag a tail to replace a jump. seems to be a bad idea. */
|
|
|
-static void
|
|
|
-rearrange(void)
|
|
|
-{
|
|
|
- int i;
|
|
|
- Reg *j, *t;
|
|
|
- BB *b, *p, *s;
|
|
|
-
|
|
|
- for(i = 0; i < bcount; i++) {
|
|
|
- b = ordered[i];
|
|
|
- if(b->flags & Bdel)
|
|
|
- continue;
|
|
|
- j = b->last;
|
|
|
- if(j->prog->as == AJMP && j->s2->p1 == R) {
|
|
|
- t = j->s2;
|
|
|
- if(t == b->first)
|
|
|
- continue;
|
|
|
- s = findset(t->rpo);
|
|
|
- if(s == nil) {
|
|
|
- diag(Z, "no self");
|
|
|
- continue;
|
|
|
- }
|
|
|
- if(s == ordered[0])
|
|
|
- continue;
|
|
|
- if(s->flags & Bdel)
|
|
|
- continue;
|
|
|
- if(s->last->link == R)
|
|
|
- continue;
|
|
|
- if(bdebug)
|
|
|
- print("drag %ld to %ld\n", t->rpo, j->rpo);
|
|
|
- p = findset(t->rpo - 1);
|
|
|
- if(p == nil) {
|
|
|
- diag(Z, "no predec");
|
|
|
- continue;
|
|
|
- }
|
|
|
- if(p->last->link != t) {
|
|
|
- diag(Z, "bad predec %ld %ld", p->last->rpo, t->rpo);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- /* poison everything in sight */
|
|
|
- b->flags |= Bdel;
|
|
|
- s->flags |= Bdel;
|
|
|
- findset(j->link->rpo)->flags |= Bdel;
|
|
|
- findset(s->last->link->rpo)->flags |= Bdel;
|
|
|
-
|
|
|
- /* remove */
|
|
|
- adjprog(p->last, t->prog, s->last->link->prog);
|
|
|
- p->last->link = s->last->link;
|
|
|
-
|
|
|
- /* fix tail */
|
|
|
- adjprog(s->last, s->last->link->prog, j->link->prog);
|
|
|
- s->last->link = j->link;
|
|
|
-
|
|
|
- /* fix head */
|
|
|
- adjprog(j, j->link->prog, t->prog);
|
|
|
- j->link = t;
|
|
|
-
|
|
|
- /* nop the jump */
|
|
|
- j->prog->as = ANOP;
|
|
|
- j->prog->to.type = D_NONE;
|
|
|
- j->s2 = nil;
|
|
|
- j->link->p2 = delset(j, j->link->p2);
|
|
|
- j->s1 = t;
|
|
|
- t->p1 = j;
|
|
|
- if(bcheck)
|
|
|
- checkr(1);
|
|
|
- bchange++;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-jumptodot(void)
|
|
|
-{
|
|
|
- Reg *r;
|
|
|
-
|
|
|
- for(r = firstr; r != R; r = r->link) {
|
|
|
- if(r->prog->as == AJMP && r->s2 == r->link) {
|
|
|
- if(debug['v'])
|
|
|
- print("jump to next %ld\n", r->rpo);
|
|
|
- r->prog->as = ANOP;
|
|
|
- r->prog->to.type = D_NONE;
|
|
|
- r->s2 = nil;
|
|
|
- r->link->p2 = delset(r, r->link->p2);
|
|
|
- findset(r->rpo)->flags |= Bdel;
|
|
|
- findset(r->link->rpo)->flags |= Bdel;
|
|
|
- bchange++;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-comtarg(void)
|
|
|
-{
|
|
|
- int n;
|
|
|
- BB *b, *c;
|
|
|
- Reg *r, *l, *p, *t;
|
|
|
-
|
|
|
-loop:
|
|
|
- bchange = 0;
|
|
|
-
|
|
|
- /* excise NOPS because they just get in the way */
|
|
|
- /* some have p2 because they are excised labelled moves */
|
|
|
-
|
|
|
- if(debug['v']) {
|
|
|
- n = 0;
|
|
|
- for(r = firstr; r != R; r = r->link)
|
|
|
- r->rpo = n++;
|
|
|
- prfunc("prenop");
|
|
|
- }
|
|
|
-
|
|
|
- r = firstr;
|
|
|
- l = r->link;
|
|
|
- while(l != R) {
|
|
|
- if(l->prog->as == ANOP) {
|
|
|
- t = l->p1;
|
|
|
- p = l->p2;
|
|
|
-if(dbg) print("nop %ld [", l->rpo);
|
|
|
-if(dbg) printbl(p);
|
|
|
- for(;;) {
|
|
|
- adjprog(r, l->prog, l->prog->link);
|
|
|
- r->link = l->link;
|
|
|
- l->link = freer;
|
|
|
- freer = l;
|
|
|
- l = r->link;
|
|
|
- if(l->prog->as != ANOP)
|
|
|
- break;
|
|
|
-if(dbg) print("] %ld [", l->rpo);
|
|
|
-if(dbg) printbl(l->p2);
|
|
|
- if(p == R)
|
|
|
- p = l->p2;
|
|
|
- else if(l->p2 != nil)
|
|
|
- appset(l->p2, p);
|
|
|
- }
|
|
|
-if(dbg) print("] %ld [", l->rpo);
|
|
|
-if(dbg) printbl(l->p2);
|
|
|
- if(p != R) {
|
|
|
- redest(p, l);
|
|
|
- if(l->p2 != R)
|
|
|
- appset(p, l->p2);
|
|
|
- else
|
|
|
- l->p2 = p;
|
|
|
- }
|
|
|
-if(dbg) print("] -> [");
|
|
|
-if(dbg) printbl(l->p2);
|
|
|
-if(dbg) print("]\n");
|
|
|
- if(r->s1 != R)
|
|
|
- r->s1 = l;
|
|
|
- l->p1 = t;
|
|
|
- }
|
|
|
- r = l;
|
|
|
- l = r->link;
|
|
|
- }
|
|
|
-
|
|
|
- n = 0;
|
|
|
- for(r = firstr; r != R; r = r->link)
|
|
|
- r->rpo = n++;
|
|
|
-
|
|
|
- if(debug['v'])
|
|
|
- prfunc("input");
|
|
|
-
|
|
|
- firstbb = nil;
|
|
|
- lastbb = nil;
|
|
|
-
|
|
|
- if(debug['v'])
|
|
|
- print("bbstart\n");
|
|
|
-
|
|
|
- n = 0;
|
|
|
- r = firstr;
|
|
|
- do {
|
|
|
- b = bba();
|
|
|
- b->first = r;
|
|
|
- for(;;) {
|
|
|
- l = r;
|
|
|
- r = r->link;
|
|
|
- switch(l->prog->as) {
|
|
|
- case ARET:
|
|
|
- case AJMP:
|
|
|
- case AIRETL:
|
|
|
- goto out;
|
|
|
- }
|
|
|
- if(r->p2 != R)
|
|
|
- break;
|
|
|
- }
|
|
|
- out:
|
|
|
- b->last = l;
|
|
|
- if(lastbb == nil)
|
|
|
- firstbb = b;
|
|
|
- else
|
|
|
- lastbb->link = b;
|
|
|
- lastbb = b;
|
|
|
- if(bdebug)
|
|
|
- print("BB %ld %ld\n", b->first->rpo, b->last->rpo);
|
|
|
- n++;
|
|
|
- } while(r != R);
|
|
|
-
|
|
|
- if(debug['v'])
|
|
|
- print("end\n");
|
|
|
-
|
|
|
- if(n > bsize) {
|
|
|
- bsize = n * 3 / 2;
|
|
|
- if(bsize < BBINIT)
|
|
|
- bsize = BBINIT;
|
|
|
- ordered = alloc(bsize * sizeof(*ordered));
|
|
|
- heap = alloc((bsize + 1) * sizeof(*ordered));
|
|
|
- }
|
|
|
-
|
|
|
- if(debug['v'])
|
|
|
- print("preprocstart\n");
|
|
|
-
|
|
|
- n = 0;
|
|
|
- for(b = firstbb; b != nil; b = c) {
|
|
|
- c = b->link;
|
|
|
- preproc(b, n++);
|
|
|
- }
|
|
|
-
|
|
|
- if(debug['v'])
|
|
|
- print("end\n");
|
|
|
-
|
|
|
- bcount = n;
|
|
|
-
|
|
|
- jumptojump();
|
|
|
-
|
|
|
- if(debug['v'])
|
|
|
- print("iteratestart\n");
|
|
|
-
|
|
|
- iterate();
|
|
|
-//checktails();
|
|
|
-
|
|
|
- if(debug['v'])
|
|
|
- print("end\n");
|
|
|
-
|
|
|
- if(debug['v'])
|
|
|
- print("extrastart\n");
|
|
|
-
|
|
|
- jumptodot();
|
|
|
-// rearrange();
|
|
|
-
|
|
|
- if(debug['v'])
|
|
|
- print("end\n");
|
|
|
-
|
|
|
- cleanup();
|
|
|
- if(bballoc || bbsalloc)
|
|
|
- diag(Z, "bballoc %d %d", bballoc, bbsalloc);
|
|
|
-
|
|
|
- if(debug['v'])
|
|
|
- prfunc("output");
|
|
|
-
|
|
|
- if(1 && bchange)
|
|
|
- goto loop;
|
|
|
-}
|