1
0
mirror of https://github.com/golang/go synced 2024-10-03 12:21:22 -06:00

initial cut at arm optimizer

R=rsc
CC=golang-dev
https://golang.org/cl/3921041
This commit is contained in:
Ken Thompson 2011-01-07 18:04:48 -08:00
parent 80055c658b
commit 90ca4d75a4
3 changed files with 159 additions and 65 deletions

View File

@ -24,6 +24,7 @@ OFILES=\
cgen64.$O\ cgen64.$O\
cplx.$O\ cplx.$O\
reg.$O\ reg.$O\
peep.$O\
LIB=\ LIB=\
../gc/gc.a\ ../gc/gc.a\

View File

@ -154,10 +154,16 @@ Dconv(Fmt *fp)
break; break;
case D_BRANCH: case D_BRANCH:
if(a->sym != S) if(a->branch == P || a->branch->loc == 0) {
sprint(str, "%s+%d(APC)", a->sym->name, a->offset); if(a->sym != S)
else sprint(str, "%s+%d(APC)", a->sym->name, a->offset);
sprint(str, "%d(APC)", a->offset); else
sprint(str, "%d(APC)", a->offset);
} else
if(a->sym != S)
sprint(str, "%s+%d(APC)", a->sym->name, a->branch->loc);
else
sprint(str, "%d(APC)", a->branch->loc);
break; break;
case D_FCONST: case D_FCONST:

View File

@ -34,9 +34,9 @@
#define P2R(p) (Reg*)(p->reg) #define P2R(p) (Reg*)(p->reg)
void addsplits(void); void addsplits(void);
int onlyone; int noreturn(Prog *p);
static int first = 1; static int first = 0;
Reg* Reg*
rega(void) rega(void)
@ -137,13 +137,24 @@ regopt(Prog *firstp)
uint32 vreg; uint32 vreg;
Bits bit; Bits bit;
return; if(first == 0) {
if(first) {
fmtinstall('Q', Qconv); fmtinstall('Q', Qconv);
// exregoffset = D_R13; // R14,R15 are external // exregoffset = D_R13; // R14,R15 are external
first = 0;
} }
first++;
//if(!debug['K'])
// return;
//if(first != 19) {
// return;
//}
//print("optimizing %S\n", curfn->nname->sym);
//debug['R'] = 2;
//debug['P'] = 2;
// count instructions // count instructions
nr = 0; nr = 0;
@ -152,7 +163,7 @@ return;
// if too big dont bother // if too big dont bother
if(nr >= 10000) { if(nr >= 10000) {
print("********** %S is too big (%d)\n", curfn->nname->sym, nr); // print("********** %S is too big (%d)\n", curfn->nname->sym, nr);
return; return;
} }
@ -178,7 +189,7 @@ return;
* allocate pcs * allocate pcs
* find use and set of variables * find use and set of variables
*/ */
print("pass 1\n"); if(0) print("pass 1\n");
nr = 0; nr = 0;
for(p=firstp; p != P; p = p->link) { for(p=firstp; p != P; p = p->link) {
switch(p->as) { switch(p->as) {
@ -265,20 +276,15 @@ print("pass 1\n");
} }
} }
} }
if(firstr == R) { if(firstr == R)
return; return;
}
onlyone++;
if(onlyone != 1)
return;
/* /*
* pass 2 * pass 2
* turn branch references to pointers * turn branch references to pointers
* build back pointers * build back pointers
*/ */
print("pass 2\n"); if(0) print("pass 2\n");
for(r=firstr; r!=R; r=r->link) { for(r=firstr; r!=R; r=r->link) {
p = r->prog; p = r->prog;
if(p->to.type == D_BRANCH) { if(p->to.type == D_BRANCH) {
@ -305,7 +311,7 @@ print("pass 2\n");
* pass 2.5 * pass 2.5
* find looping structure * find looping structure
*/ */
print("pass 2.5\n"); if(0) print("pass 2.5\n");
for(r = firstr; r != R; r = r->link) for(r = firstr; r != R; r = r->link)
r->active = 0; r->active = 0;
change = 0; change = 0;
@ -317,7 +323,7 @@ print("pass 2.5\n");
* back until flow graph is complete * back until flow graph is complete
*/ */
loop1: loop1:
print("loop 1\n"); if(0) print("loop 1\n");
change = 0; change = 0;
for(r = firstr; r != R; r = r->link) for(r = firstr; r != R; r = r->link)
r->active = 0; r->active = 0;
@ -325,7 +331,7 @@ print("loop 1\n");
if(r->prog->as == ARET) if(r->prog->as == ARET)
prop(r, zbits, zbits); prop(r, zbits, zbits);
loop11: loop11:
print("loop 11\n"); if(0) print("loop 11\n");
/* pick up unreachable code */ /* pick up unreachable code */
i = 0; i = 0;
for(r = firstr; r != R; r = r1) { for(r = firstr; r != R; r = r1) {
@ -347,7 +353,7 @@ print("loop 11\n");
* forward until graph is complete * forward until graph is complete
*/ */
loop2: loop2:
print("loop 2\n"); if(0) print("loop 2\n");
change = 0; change = 0;
for(r = firstr; r != R; r = r->link) for(r = firstr; r != R; r = r->link)
r->active = 0; r->active = 0;
@ -357,7 +363,7 @@ print("loop 2\n");
addsplits(); addsplits();
if(debug['R'] && debug['v']) { if(debug['R'] > 1) {
print("\nprop structure:\n"); print("\nprop structure:\n");
for(r = firstr; r != R; r = r->link) { for(r = firstr; r != R; r = r->link) {
print("%d:%P", r->loop, r->prog); print("%d:%P", r->loop, r->prog);
@ -394,7 +400,7 @@ print("loop 2\n");
* isolate regions * isolate regions
* calculate costs (paint1) * calculate costs (paint1)
*/ */
print("pass 5\n"); if(0) print("pass 5\n");
r = firstr; r = firstr;
if(r) { if(r) {
for(z=0; z<BITS; z++) for(z=0; z<BITS; z++)
@ -429,7 +435,7 @@ print("pass 5\n");
rgp->enter = r; rgp->enter = r;
rgp->varno = i; rgp->varno = i;
change = 0; change = 0;
if(debug['R'] && debug['v']) if(debug['R'] > 1)
print("\n"); print("\n");
paint1(r, i); paint1(r, i);
bit.b[i/32] &= ~(1L<<(i%32)); bit.b[i/32] &= ~(1L<<(i%32));
@ -442,7 +448,7 @@ print("pass 5\n");
rgp->cost = change; rgp->cost = change;
nregion++; nregion++;
if(nregion >= NRGN) { if(nregion >= NRGN) {
if(debug['R'] && debug['v']) if(debug['R'] > 1)
print("too many regions\n"); print("too many regions\n");
goto brk; goto brk;
} }
@ -457,7 +463,6 @@ brk:
* determine used registers (paint2) * determine used registers (paint2)
* replace code (paint3) * replace code (paint3)
*/ */
print("pass 6 -- %d regions\n", nregion);
rgp = region; rgp = region;
for(i=0; i<nregion; i++) { for(i=0; i<nregion; i++) {
bit = blsh(rgp->varno); bit = blsh(rgp->varno);
@ -485,9 +490,9 @@ print("pass 6 -- %d regions\n", nregion);
* pass 7 * pass 7
* peep-hole on basic block * peep-hole on basic block
*/ */
print("pass 7\n"); if(0) print("pass 7\n");
if(!debug['R'] || debug['P']) { if(!debug['R'] || debug['P']) {
// peep(); peep();
} }
/* /*
@ -495,9 +500,12 @@ print("pass 7\n");
* eliminate nops * eliminate nops
* free aux structures * free aux structures
*/ */
for(p = firstr->prog; p != P; p = p->link){ for(p = firstp; p != P; p = p->link) {
while(p->link && p->link->as == ANOP) while(p->link != P && p->link->as == ANOP)
p->link = p->link->link; p->link = p->link->link;
if(p->to.type == D_BRANCH)
while(p->to.branch != P && p->to.branch->as == ANOP)
p->to.branch = p->to.branch->link;
} }
if(r1 != R) { if(r1 != R) {
r1->link = freer; r1->link = freer;
@ -562,15 +570,31 @@ addmove(Reg *r, int bn, int rn, int f)
if(a->etype == TARRAY || a->sym == S) if(a->etype == TARRAY || a->sym == S)
a->type = D_CONST; a->type = D_CONST;
p1->as = AMOVW; switch(v->etype) {
if(v->etype == TINT8 || v->etype == TUINT8) default:
print("What is this %E\n", v->etype);
case TINT32:
case TUINT32:
case TPTR32:
case TBOOL:
p1->as = AMOVW;
break;
case TINT8:
case TUINT8:
p1->as = AMOVB; p1->as = AMOVB;
if(v->etype == TINT16 || v->etype == TUINT16) break;
case TINT16:
case TUINT16:
p1->as = AMOVH; p1->as = AMOVH;
if(v->etype == TFLOAT) break;
case TFLOAT32:
p1->as = AMOVF; p1->as = AMOVF;
if(v->etype == TFLOAT64) break;
case TFLOAT64:
p1->as = AMOVD; p1->as = AMOVD;
break;
}
p1->from.type = D_REG; p1->from.type = D_REG;
p1->from.reg = rn; p1->from.reg = rn;
@ -619,32 +643,72 @@ mkvar(Reg *r, Adr *a, int docon)
Bits bit; Bits bit;
Sym *s; Sym *s;
// mark registers used
t = a->type; t = a->type;
if(t == D_REG && a->reg != NREG) n = D_NONE;
r->regu |= RtoB(a->reg);
if(t == D_FREG && a->reg != NREG) switch(t) {
r->regu |= FtoB(a->reg); default:
s = a->sym; print("type %d %d %D\n", t, a->name, a);
o = a->offset; goto none;
et = a->etype;
if(s == S) { case D_NONE:
if(t != D_CONST || !docon || a->reg != NREG) case D_CONST:
goto none; case D_FCONST:
et = TINT32; case D_BRANCH:
goto none;
case D_REGREG:
if(a->offset != NREG)
r->regu |= RtoB(a->offset);
// fallthrough
case D_REG:
case D_SHIFT:
case D_OREG:
if(a->reg != NREG)
r->regu |= RtoB(a->reg);
break;
case D_FREG:
if(a->reg != NREG)
r->regu |= FtoB(a->reg);
break;
} }
if(t == D_CONST) {
// if(s == S && sval(o)) switch(a->name) {
// goto none; default:
goto none;
case D_EXTERN:
case D_STATIC:
case D_AUTO:
case D_PARAM:
n = a->name;
break;
} }
flag = 0; flag = 0;
// if(a->pun)
// flag = 1;
s = a->sym;
if(s == S)
goto none;
if(s->name[0] == '.')
goto none;
et = a->etype;
o = a->offset;
w = a->width;
for(i=0; i<nvar; i++) { for(i=0; i<nvar; i++) {
v = var+i; v = var+i;
if(v->sym == s && v->name == n) { if(v->sym == s && v->name == n) {
if(v->offset == o) if(v->offset == o)
if(v->etype == et) if(v->etype == et)
if(v->width == w) if(v->width == w)
return blsh(i); if(!flag)
return blsh(i);
// if they overlaps, disable both // if they overlaps, disable both
if(overlap(v->offset, v->width, o, w)) { if(overlap(v->offset, v->width, o, w)) {
@ -654,12 +718,11 @@ mkvar(Reg *r, Adr *a, int docon)
} }
} }
// if(a->pun)
// flag = 1;
switch(et) { switch(et) {
case 0: case 0:
case TFUNC: case TFUNC:
case TARRAY:
case TSTRING:
goto none; goto none;
} }
@ -681,7 +744,7 @@ mkvar(Reg *r, Adr *a, int docon)
v->addr = flag; // funny punning v->addr = flag; // funny punning
if(debug['R']) if(debug['R'])
print("bit=%2d et=%2d %D\n", i, et, a); print("bit=%2d et=%E pun=%d %D\n", i, et, flag, a);
out: out:
bit = blsh(i); bit = blsh(i);
@ -692,9 +755,6 @@ out:
for(z=0; z<BITS; z++) for(z=0; z<BITS; z++)
params.b[z] |= bit.b[z]; params.b[z] |= bit.b[z];
// if(v->etype != et || !typechlpfd[et]) /* funny punning */
// for(z=0; z<BITS; z++)
// addrs.b[z] |= bit.b[z];
// if(t == D_CONST) { // if(t == D_CONST) {
// if(s == S) { // if(s == S) {
// for(z=0; z<BITS; z++) // for(z=0; z<BITS; z++)
@ -738,6 +798,8 @@ prop(Reg *r, Bits ref, Bits cal)
} }
switch(r1->prog->as) { switch(r1->prog->as) {
case ABL: case ABL:
if(noreturn(r1->prog))
break;
for(z=0; z<BITS; z++) { for(z=0; z<BITS; z++) {
cal.b[z] |= ref.b[z] | externs.b[z]; cal.b[z] |= ref.b[z] | externs.b[z];
ref.b[z] = 0; ref.b[z] = 0;
@ -753,9 +815,10 @@ prop(Reg *r, Bits ref, Bits cal)
case ARET: case ARET:
for(z=0; z<BITS; z++) { for(z=0; z<BITS; z++) {
cal.b[z] = externs.b[z]; cal.b[z] = externs.b[z] | ovar.b[z];
ref.b[z] = 0; ref.b[z] = 0;
} }
break;
} }
for(z=0; z<BITS; z++) { for(z=0; z<BITS; z++) {
ref.b[z] = (ref.b[z] & ~r1->set.b[z]) | ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
@ -1008,7 +1071,7 @@ paint1(Reg *r, int bn)
if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) { if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) {
change -= CLOAD * r->loop; change -= CLOAD * r->loop;
if(debug['R'] && debug['v']) if(debug['R'] > 1)
print("%d%P\td %Q $%d\n", r->loop, print("%d%P\td %Q $%d\n", r->loop,
r->prog, blsh(bn), change); r->prog, blsh(bn), change);
} }
@ -1018,21 +1081,21 @@ paint1(Reg *r, int bn)
if(r->use1.b[z] & bb) { if(r->use1.b[z] & bb) {
change += CREF * r->loop; change += CREF * r->loop;
if(debug['R'] && debug['v']) if(debug['R'] > 1)
print("%d%P\tu1 %Q $%d\n", r->loop, print("%d%P\tu1 %Q $%d\n", r->loop,
p, blsh(bn), change); p, blsh(bn), change);
} }
if((r->use2.b[z]|r->set.b[z]) & bb) { if((r->use2.b[z]|r->set.b[z]) & bb) {
change += CREF * r->loop; change += CREF * r->loop;
if(debug['R'] && debug['v']) if(debug['R'] > 1)
print("%d%P\tu2 %Q $%d\n", r->loop, print("%d%P\tu2 %Q $%d\n", r->loop,
p, blsh(bn), change); p, blsh(bn), change);
} }
if(STORE(r) & r->regdiff.b[z] & bb) { if(STORE(r) & r->regdiff.b[z] & bb) {
change -= CLOAD * r->loop; change -= CLOAD * r->loop;
if(debug['R'] && debug['v']) if(debug['R'] > 1)
print("%d%P\tst %Q $%d\n", r->loop, print("%d%P\tst %Q $%d\n", r->loop,
p, blsh(bn), change); p, blsh(bn), change);
} }
@ -1244,3 +1307,27 @@ BtoF(int32 b)
return 0; return 0;
return bitno(b) - 16; return bitno(b) - 16;
} }
static Sym* symlist[10];
int
noreturn(Prog *p)
{
Sym *s;
int i;
if(symlist[0] == S) {
symlist[0] = pkglookup("panicindex", runtimepkg);
symlist[1] = pkglookup("panicslice", runtimepkg);
symlist[2] = pkglookup("throwinit", runtimepkg);
symlist[3] = pkglookup("panic", runtimepkg);
}
s = p->to.sym;
if(s == S)
return 0;
for(i=0; symlist[i]!=S; i++)
if(s == symlist[i])
return 1;
return 0;
}