mirror of
https://github.com/golang/go
synced 2024-11-20 08:34:41 -07:00
initial cut at arm optimizer
R=rsc CC=golang-dev https://golang.org/cl/3921041
This commit is contained in:
parent
80055c658b
commit
90ca4d75a4
@ -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\
|
||||||
|
@ -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:
|
||||||
|
209
src/cmd/5g/reg.c
209
src/cmd/5g/reg.c
@ -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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user