mirror of
https://github.com/golang/go
synced 2024-11-20 06:04:52 -07:00
arm optimizer bug fixes
R=rsc CC=golang-dev https://golang.org/cl/3913043
This commit is contained in:
parent
212e074be2
commit
ab4d8bf16c
@ -37,6 +37,7 @@ int shiftprop(Reg *r);
|
||||
void constprop(Adr *c1, Adr *v1, Reg *r);
|
||||
void predicate(void);
|
||||
int copyau1(Prog *p, Adr *v);
|
||||
int isdconst(Addr *a);
|
||||
|
||||
void
|
||||
peep(void)
|
||||
@ -81,30 +82,42 @@ loop1:
|
||||
t = 0;
|
||||
for(r=firstr; r!=R; r=r->link) {
|
||||
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
|
||||
*/
|
||||
if(shiftprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(p->as == AMOVW || p->as == AMOVF || p->as == AMOVD)
|
||||
if(regtyp(&p->to)) {
|
||||
if(p->from.type == D_CONST)
|
||||
break;
|
||||
|
||||
case AMOVW:
|
||||
case AMOVF:
|
||||
case AMOVD:
|
||||
if(!regtyp(&p->to))
|
||||
break;
|
||||
if(isdconst(&p->from)) {
|
||||
constprop(&p->from, &p->to, r->s1);
|
||||
else
|
||||
if(regtyp(&p->from))
|
||||
if(p->from.type == p->to.type) {
|
||||
if(copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
} else
|
||||
if(subprop(r) && copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!regtyp(&p->from))
|
||||
break;
|
||||
if(p->from.type != p->to.type)
|
||||
break;
|
||||
if(copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
break;
|
||||
}
|
||||
if(subprop(r) && copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,7 +135,7 @@ loop1:
|
||||
/*
|
||||
* 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->from.type = D_REG;
|
||||
if(p->reg != NREG)
|
||||
@ -170,7 +183,7 @@ loop1:
|
||||
/*
|
||||
* 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;
|
||||
r2 = r->s1;
|
||||
if(r2 == R)
|
||||
@ -668,12 +681,14 @@ shiftprop(Reg *r)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* make the substitution */
|
||||
p2->from.type = D_SHIFT;
|
||||
p2->from.reg = NREG;
|
||||
o = p->reg;
|
||||
if(o == NREG)
|
||||
o = p->to.reg;
|
||||
|
||||
switch(p->from.type){
|
||||
case D_CONST:
|
||||
o |= (p->from.offset&0x1f)<<7;
|
||||
@ -735,7 +750,7 @@ findinc(Reg *r, Reg *r2, Adr *v)
|
||||
case 4: /* set and used */
|
||||
p = r1->prog;
|
||||
if(p->as == AADD)
|
||||
if(p->from.type == D_CONST)
|
||||
if(isdconst(&p->from))
|
||||
if(p->from.offset > -4096 && p->from.offset < 4096)
|
||||
return r1;
|
||||
default:
|
||||
@ -990,7 +1005,6 @@ copyu(Prog *p, Adr *v, Adr *s)
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
|
||||
case AADD: /* read, read, write */
|
||||
case ASUB:
|
||||
case ARSB:
|
||||
@ -1192,6 +1206,10 @@ copyau(Adr *a, Adr *v)
|
||||
if(copyas(a, v))
|
||||
return 1;
|
||||
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(v->reg == a->reg)
|
||||
return 1;
|
||||
@ -1320,19 +1338,22 @@ isbranch(Prog *p)
|
||||
int
|
||||
predicable(Prog *p)
|
||||
{
|
||||
if (isbranch(p)
|
||||
|| p->as == ANOP
|
||||
|| p->as == AXXX
|
||||
|| p->as == ADATA
|
||||
|| p->as == AGLOBL
|
||||
|| p->as == AGOK
|
||||
|| p->as == AHISTORY
|
||||
|| p->as == ANAME
|
||||
|| p->as == ASIGNAME
|
||||
|| p->as == ATEXT
|
||||
|| p->as == AWORD
|
||||
|| p->as == ABCASE
|
||||
|| p->as == ACASE)
|
||||
switch(p->as) {
|
||||
case ANOP:
|
||||
case AXXX:
|
||||
case ADATA:
|
||||
case AGLOBL:
|
||||
case AGOK:
|
||||
case AHISTORY:
|
||||
case ANAME:
|
||||
case ASIGNAME:
|
||||
case ATEXT:
|
||||
case AWORD:
|
||||
case ABCASE:
|
||||
case ACASE:
|
||||
return 0;
|
||||
}
|
||||
if(isbranch(p))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@ -1347,18 +1368,23 @@ predicable(Prog *p)
|
||||
int
|
||||
modifiescpsr(Prog *p)
|
||||
{
|
||||
return (p->scond&C_SBIT)
|
||||
|| p->as == ATST
|
||||
|| p->as == ATEQ
|
||||
|| p->as == ACMN
|
||||
|| p->as == ACMP
|
||||
|| p->as == AMULU
|
||||
|| p->as == ADIVU
|
||||
|| p->as == AMUL
|
||||
|| p->as == ADIV
|
||||
|| p->as == AMOD
|
||||
|| p->as == AMODU
|
||||
|| p->as == ABL;
|
||||
switch(p->as) {
|
||||
case ATST:
|
||||
case ATEQ:
|
||||
case ACMN:
|
||||
case ACMP:
|
||||
case AMULU:
|
||||
case ADIVU:
|
||||
case AMUL:
|
||||
case ADIV:
|
||||
case AMOD:
|
||||
case AMODU:
|
||||
case ABL:
|
||||
return 1;
|
||||
}
|
||||
if(p->scond & C_SBIT)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1401,10 +1427,10 @@ joinsplit(Reg *r, Joininfo *j)
|
||||
return Toolong;
|
||||
}
|
||||
|
||||
Reg *
|
||||
Reg*
|
||||
successor(Reg *r)
|
||||
{
|
||||
if (r->s1)
|
||||
if(r->s1)
|
||||
return r->s1;
|
||||
else
|
||||
return r->s2;
|
||||
@ -1418,23 +1444,24 @@ applypred(Reg *rstart, Joininfo *j, int cond, int branch)
|
||||
|
||||
if(j->len == 0)
|
||||
return;
|
||||
if (cond == Truecond)
|
||||
if(cond == Truecond)
|
||||
pred = predinfo[rstart->prog->as - ABEQ].scond;
|
||||
else
|
||||
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 != j->last || branch == Delbranch)
|
||||
excise(r);
|
||||
else {
|
||||
if (cond == Truecond)
|
||||
r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
|
||||
else
|
||||
r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
|
||||
if (cond == Truecond)
|
||||
r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
|
||||
else
|
||||
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;
|
||||
if (r->s1 != r->link) {
|
||||
r->s1 = r->link;
|
||||
@ -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)
|
||||
p->scond = zprog.scond;
|
||||
p->from = zprog.from;
|
||||
p->to = zprog.to;
|
||||
p->reg = zprog.reg; /**/
|
||||
p->reg = zprog.reg;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -139,22 +139,16 @@ regopt(Prog *firstp)
|
||||
|
||||
if(first == 0) {
|
||||
fmtinstall('Q', Qconv);
|
||||
// exregoffset = D_R13; // R14,R15 are external
|
||||
}
|
||||
first++;
|
||||
|
||||
//if(!debug['K'])
|
||||
// return;
|
||||
|
||||
//if(first != 19) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
//print("optimizing %S\n", curfn->nname->sym);
|
||||
|
||||
//debug['R'] = 2;
|
||||
//debug['P'] = 2;
|
||||
|
||||
if(debug['K']) {
|
||||
if(first != 20)
|
||||
return;
|
||||
// debug['R'] = 2;
|
||||
// debug['P'] = 2;
|
||||
print("optimizing %S\n", curfn->nname->sym);
|
||||
}
|
||||
|
||||
// count instructions
|
||||
nr = 0;
|
||||
@ -189,7 +183,6 @@ regopt(Prog *firstp)
|
||||
* allocate pcs
|
||||
* find use and set of variables
|
||||
*/
|
||||
if(0) print("pass 1\n");
|
||||
nr = 0;
|
||||
for(p=firstp; p != P; p = p->link) {
|
||||
switch(p->as) {
|
||||
@ -284,7 +277,6 @@ if(0) print("pass 1\n");
|
||||
* turn branch references to pointers
|
||||
* build back pointers
|
||||
*/
|
||||
if(0) print("pass 2\n");
|
||||
for(r=firstr; r!=R; r=r->link) {
|
||||
p = r->prog;
|
||||
if(p->to.type == D_BRANCH) {
|
||||
@ -311,7 +303,6 @@ if(0) print("pass 2\n");
|
||||
* pass 2.5
|
||||
* find looping structure
|
||||
*/
|
||||
if(0) print("pass 2.5\n");
|
||||
for(r = firstr; r != R; r = r->link)
|
||||
r->active = 0;
|
||||
change = 0;
|
||||
@ -323,7 +314,6 @@ if(0) print("pass 2.5\n");
|
||||
* back until flow graph is complete
|
||||
*/
|
||||
loop1:
|
||||
if(0) print("loop 1\n");
|
||||
change = 0;
|
||||
for(r = firstr; r != R; r = r->link)
|
||||
r->active = 0;
|
||||
@ -331,7 +321,6 @@ if(0) print("loop 1\n");
|
||||
if(r->prog->as == ARET)
|
||||
prop(r, zbits, zbits);
|
||||
loop11:
|
||||
if(0) print("loop 11\n");
|
||||
/* pick up unreachable code */
|
||||
i = 0;
|
||||
for(r = firstr; r != R; r = r1) {
|
||||
@ -353,7 +342,6 @@ if(0) print("loop 11\n");
|
||||
* forward until graph is complete
|
||||
*/
|
||||
loop2:
|
||||
if(0) print("loop 2\n");
|
||||
change = 0;
|
||||
for(r = firstr; r != R; r = r->link)
|
||||
r->active = 0;
|
||||
@ -400,7 +388,6 @@ if(0) print("loop 2\n");
|
||||
* isolate regions
|
||||
* calculate costs (paint1)
|
||||
*/
|
||||
if(0) print("pass 5\n");
|
||||
r = firstr;
|
||||
if(r) {
|
||||
for(z=0; z<BITS; z++)
|
||||
@ -490,7 +477,6 @@ brk:
|
||||
* pass 7
|
||||
* peep-hole on basic block
|
||||
*/
|
||||
if(0) print("pass 7\n");
|
||||
if(!debug['R'] || debug['P']) {
|
||||
peep();
|
||||
}
|
||||
@ -652,8 +638,12 @@ mkvar(Reg *r, Adr *a, int docon)
|
||||
print("type %d %d %D\n", t, a->name, a);
|
||||
goto none;
|
||||
|
||||
case D_NONE:
|
||||
case D_CONST:
|
||||
if(a->reg != NREG)
|
||||
r->regu |= RtoB(a->reg);
|
||||
// fallthrough
|
||||
|
||||
case D_NONE:
|
||||
case D_FCONST:
|
||||
case D_BRANCH:
|
||||
goto none;
|
||||
@ -1028,9 +1018,6 @@ allreg(uint32 b, Rgn *r)
|
||||
}
|
||||
break;
|
||||
|
||||
case TINT64:
|
||||
case TUINT64:
|
||||
case TPTR64:
|
||||
case TFLOAT32:
|
||||
case TFLOAT64:
|
||||
case TFLOAT:
|
||||
@ -1040,6 +1027,14 @@ allreg(uint32 b, Rgn *r)
|
||||
return FtoB(i);
|
||||
}
|
||||
break;
|
||||
|
||||
case TINT64:
|
||||
case TUINT64:
|
||||
case TPTR64:
|
||||
case TINTER:
|
||||
case TSTRUCT:
|
||||
case TARRAY:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user