Commit ab4d8bf1 authored by Ken Thompson's avatar Ken Thompson

arm optimizer bug fixes

R=rsc
CC=golang-dev
https://golang.org/cl/3913043
parent 212e074b
...@@ -37,6 +37,7 @@ int shiftprop(Reg *r); ...@@ -37,6 +37,7 @@ int shiftprop(Reg *r);
void constprop(Adr *c1, Adr *v1, Reg *r); void constprop(Adr *c1, Adr *v1, Reg *r);
void predicate(void); void predicate(void);
int copyau1(Prog *p, Adr *v); int copyau1(Prog *p, Adr *v);
int isdconst(Addr *a);
void void
peep(void) peep(void)
...@@ -81,30 +82,42 @@ loop1: ...@@ -81,30 +82,42 @@ loop1:
t = 0; t = 0;
for(r=firstr; r!=R; r=r->link) { for(r=firstr; r!=R; r=r->link) {
p = r->prog; p = r->prog;
if(p->as == ASLL || p->as == ASRL || p->as == ASRA) { switch(p->as) {
case ASLL:
case ASRL:
case ASRA:
/* /*
* elide shift into D_SHIFT operand of subsequent instruction * elide shift into D_SHIFT operand of subsequent instruction
*/ */
if(shiftprop(r)) { if(shiftprop(r)) {
excise(r); excise(r);
t++; t++;
break;
} }
} break;
if(p->as == AMOVW || p->as == AMOVF || p->as == AMOVD)
if(regtyp(&p->to)) { case AMOVW:
if(p->from.type == D_CONST) case AMOVF:
case AMOVD:
if(!regtyp(&p->to))
break;
if(isdconst(&p->from)) {
constprop(&p->from, &p->to, r->s1); constprop(&p->from, &p->to, r->s1);
else break;
if(regtyp(&p->from)) }
if(p->from.type == p->to.type) { if(!regtyp(&p->from))
break;
if(p->from.type != p->to.type)
break;
if(copyprop(r)) { if(copyprop(r)) {
excise(r); excise(r);
t++; t++;
} else break;
}
if(subprop(r) && copyprop(r)) { if(subprop(r) && copyprop(r)) {
excise(r); excise(r);
t++; t++;
} break;
} }
} }
} }
...@@ -122,7 +135,7 @@ loop1: ...@@ -122,7 +135,7 @@ loop1:
/* /*
* EOR -1,x,y => MVN x,y * EOR -1,x,y => MVN x,y
*/ */
if(p->from.type == D_CONST && p->from.offset == -1) { if(isdconst(&p->from) && p->from.offset == -1) {
p->as = AMVN; p->as = AMVN;
p->from.type = D_REG; p->from.type = D_REG;
if(p->reg != NREG) if(p->reg != NREG)
...@@ -170,7 +183,7 @@ loop1: ...@@ -170,7 +183,7 @@ loop1:
/* /*
* elide CMP $0,x if calculation of x can set condition codes * elide CMP $0,x if calculation of x can set condition codes
*/ */
if(p->from.type != D_CONST || p->from.offset != 0) if(isdconst(&p->from) || p->from.offset != 0)
continue; continue;
r2 = r->s1; r2 = r->s1;
if(r2 == R) if(r2 == R)
...@@ -668,12 +681,14 @@ shiftprop(Reg *r) ...@@ -668,12 +681,14 @@ shiftprop(Reg *r)
} }
break; break;
} }
/* make the substitution */ /* make the substitution */
p2->from.type = D_SHIFT; p2->from.type = D_SHIFT;
p2->from.reg = NREG; p2->from.reg = NREG;
o = p->reg; o = p->reg;
if(o == NREG) if(o == NREG)
o = p->to.reg; o = p->to.reg;
switch(p->from.type){ switch(p->from.type){
case D_CONST: case D_CONST:
o |= (p->from.offset&0x1f)<<7; o |= (p->from.offset&0x1f)<<7;
...@@ -735,7 +750,7 @@ findinc(Reg *r, Reg *r2, Adr *v) ...@@ -735,7 +750,7 @@ findinc(Reg *r, Reg *r2, Adr *v)
case 4: /* set and used */ case 4: /* set and used */
p = r1->prog; p = r1->prog;
if(p->as == AADD) if(p->as == AADD)
if(p->from.type == D_CONST) if(isdconst(&p->from))
if(p->from.offset > -4096 && p->from.offset < 4096) if(p->from.offset > -4096 && p->from.offset < 4096)
return r1; return r1;
default: default:
...@@ -990,7 +1005,6 @@ copyu(Prog *p, Adr *v, Adr *s) ...@@ -990,7 +1005,6 @@ copyu(Prog *p, Adr *v, Adr *s)
return 1; return 1;
return 0; return 0;
case AADD: /* read, read, write */ case AADD: /* read, read, write */
case ASUB: case ASUB:
case ARSB: case ARSB:
...@@ -1192,6 +1206,10 @@ copyau(Adr *a, Adr *v) ...@@ -1192,6 +1206,10 @@ copyau(Adr *a, Adr *v)
if(copyas(a, v)) if(copyas(a, v))
return 1; return 1;
if(v->type == D_REG) { if(v->type == D_REG) {
if(a->type == D_CONST && a->reg != NREG) {
if(v->reg == a->reg)
return 1;
} else
if(a->type == D_OREG) { if(a->type == D_OREG) {
if(v->reg == a->reg) if(v->reg == a->reg)
return 1; return 1;
...@@ -1320,19 +1338,22 @@ isbranch(Prog *p) ...@@ -1320,19 +1338,22 @@ isbranch(Prog *p)
int int
predicable(Prog *p) predicable(Prog *p)
{ {
if (isbranch(p) switch(p->as) {
|| p->as == ANOP case ANOP:
|| p->as == AXXX case AXXX:
|| p->as == ADATA case ADATA:
|| p->as == AGLOBL case AGLOBL:
|| p->as == AGOK case AGOK:
|| p->as == AHISTORY case AHISTORY:
|| p->as == ANAME case ANAME:
|| p->as == ASIGNAME case ASIGNAME:
|| p->as == ATEXT case ATEXT:
|| p->as == AWORD case AWORD:
|| p->as == ABCASE case ABCASE:
|| p->as == ACASE) case ACASE:
return 0;
}
if(isbranch(p))
return 0; return 0;
return 1; return 1;
} }
...@@ -1347,18 +1368,23 @@ predicable(Prog *p) ...@@ -1347,18 +1368,23 @@ predicable(Prog *p)
int int
modifiescpsr(Prog *p) modifiescpsr(Prog *p)
{ {
return (p->scond&C_SBIT) switch(p->as) {
|| p->as == ATST case ATST:
|| p->as == ATEQ case ATEQ:
|| p->as == ACMN case ACMN:
|| p->as == ACMP case ACMP:
|| p->as == AMULU case AMULU:
|| p->as == ADIVU case ADIVU:
|| p->as == AMUL case AMUL:
|| p->as == ADIV case ADIV:
|| p->as == AMOD case AMOD:
|| p->as == AMODU case AMODU:
|| p->as == ABL; case ABL:
return 1;
}
if(p->scond & C_SBIT)
return 1;
return 0;
} }
/* /*
...@@ -1401,10 +1427,10 @@ joinsplit(Reg *r, Joininfo *j) ...@@ -1401,10 +1427,10 @@ joinsplit(Reg *r, Joininfo *j)
return Toolong; return Toolong;
} }
Reg * Reg*
successor(Reg *r) successor(Reg *r)
{ {
if (r->s1) if(r->s1)
return r->s1; return r->s1;
else else
return r->s2; return r->s2;
...@@ -1418,12 +1444,12 @@ applypred(Reg *rstart, Joininfo *j, int cond, int branch) ...@@ -1418,12 +1444,12 @@ applypred(Reg *rstart, Joininfo *j, int cond, int branch)
if(j->len == 0) if(j->len == 0)
return; return;
if (cond == Truecond) if(cond == Truecond)
pred = predinfo[rstart->prog->as - ABEQ].scond; pred = predinfo[rstart->prog->as - ABEQ].scond;
else else
pred = predinfo[rstart->prog->as - ABEQ].notscond; pred = predinfo[rstart->prog->as - ABEQ].notscond;
for (r = j->start; ; r = successor(r)) { for(r = j->start;; r = successor(r)) {
if (r->prog->as == AB) { if (r->prog->as == AB) {
if (r != j->last || branch == Delbranch) if (r != j->last || branch == Delbranch)
excise(r); excise(r);
...@@ -1434,7 +1460,8 @@ applypred(Reg *rstart, Joininfo *j, int cond, int branch) ...@@ -1434,7 +1460,8 @@ applypred(Reg *rstart, Joininfo *j, int cond, int branch)
r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode; r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
} }
} }
else if (predicable(r->prog)) else
if (predicable(r->prog))
r->prog->scond = (r->prog->scond&~C_SCOND)|pred; r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
if (r->s1 != r->link) { if (r->s1 != r->link) {
r->s1 = r->link; r->s1 = r->link;
...@@ -1474,3 +1501,11 @@ predicate(void) ...@@ -1474,3 +1501,11 @@ predicate(void)
} }
} }
} }
int
isdconst(Addr *a)
{
if(a->type == D_CONST && a->reg == NREG)
return 1;
return 0;
}
...@@ -102,7 +102,7 @@ excise(Reg *r) ...@@ -102,7 +102,7 @@ excise(Reg *r)
p->scond = zprog.scond; p->scond = zprog.scond;
p->from = zprog.from; p->from = zprog.from;
p->to = zprog.to; p->to = zprog.to;
p->reg = zprog.reg; /**/ p->reg = zprog.reg;
} }
static void static void
...@@ -139,22 +139,16 @@ regopt(Prog *firstp) ...@@ -139,22 +139,16 @@ regopt(Prog *firstp)
if(first == 0) { if(first == 0) {
fmtinstall('Q', Qconv); fmtinstall('Q', Qconv);
// exregoffset = D_R13; // R14,R15 are external
} }
first++; first++;
//if(!debug['K']) if(debug['K']) {
// return; if(first != 20)
return;
//if(first != 19) { // debug['R'] = 2;
// return; // debug['P'] = 2;
//} print("optimizing %S\n", curfn->nname->sym);
}
//print("optimizing %S\n", curfn->nname->sym);
//debug['R'] = 2;
//debug['P'] = 2;
// count instructions // count instructions
nr = 0; nr = 0;
...@@ -189,7 +183,6 @@ regopt(Prog *firstp) ...@@ -189,7 +183,6 @@ regopt(Prog *firstp)
* allocate pcs * allocate pcs
* find use and set of variables * find use and set of variables
*/ */
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) {
...@@ -284,7 +277,6 @@ if(0) print("pass 1\n"); ...@@ -284,7 +277,6 @@ if(0) print("pass 1\n");
* turn branch references to pointers * turn branch references to pointers
* build back pointers * build back pointers
*/ */
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) {
...@@ -311,7 +303,6 @@ if(0) print("pass 2\n"); ...@@ -311,7 +303,6 @@ if(0) print("pass 2\n");
* pass 2.5 * pass 2.5
* find looping structure * find looping structure
*/ */
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;
...@@ -323,7 +314,6 @@ if(0) print("pass 2.5\n"); ...@@ -323,7 +314,6 @@ if(0) print("pass 2.5\n");
* back until flow graph is complete * back until flow graph is complete
*/ */
loop1: loop1:
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;
...@@ -331,7 +321,6 @@ if(0) print("loop 1\n"); ...@@ -331,7 +321,6 @@ if(0) print("loop 1\n");
if(r->prog->as == ARET) if(r->prog->as == ARET)
prop(r, zbits, zbits); prop(r, zbits, zbits);
loop11: loop11:
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) {
...@@ -353,7 +342,6 @@ if(0) print("loop 11\n"); ...@@ -353,7 +342,6 @@ if(0) print("loop 11\n");
* forward until graph is complete * forward until graph is complete
*/ */
loop2: loop2:
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;
...@@ -400,7 +388,6 @@ if(0) print("loop 2\n"); ...@@ -400,7 +388,6 @@ if(0) print("loop 2\n");
* isolate regions * isolate regions
* calculate costs (paint1) * calculate costs (paint1)
*/ */
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++)
...@@ -490,7 +477,6 @@ brk: ...@@ -490,7 +477,6 @@ brk:
* pass 7 * pass 7
* peep-hole on basic block * peep-hole on basic block
*/ */
if(0) print("pass 7\n");
if(!debug['R'] || debug['P']) { if(!debug['R'] || debug['P']) {
peep(); peep();
} }
...@@ -652,8 +638,12 @@ mkvar(Reg *r, Adr *a, int docon) ...@@ -652,8 +638,12 @@ mkvar(Reg *r, Adr *a, int docon)
print("type %d %d %D\n", t, a->name, a); print("type %d %d %D\n", t, a->name, a);
goto none; goto none;
case D_NONE:
case D_CONST: case D_CONST:
if(a->reg != NREG)
r->regu |= RtoB(a->reg);
// fallthrough
case D_NONE:
case D_FCONST: case D_FCONST:
case D_BRANCH: case D_BRANCH:
goto none; goto none;
...@@ -1028,9 +1018,6 @@ allreg(uint32 b, Rgn *r) ...@@ -1028,9 +1018,6 @@ allreg(uint32 b, Rgn *r)
} }
break; break;
case TINT64:
case TUINT64:
case TPTR64:
case TFLOAT32: case TFLOAT32:
case TFLOAT64: case TFLOAT64:
case TFLOAT: case TFLOAT:
...@@ -1040,6 +1027,14 @@ allreg(uint32 b, Rgn *r) ...@@ -1040,6 +1027,14 @@ allreg(uint32 b, Rgn *r)
return FtoB(i); return FtoB(i);
} }
break; break;
case TINT64:
case TUINT64:
case TPTR64:
case TINTER:
case TSTRUCT:
case TARRAY:
break;
} }
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment