1
0
mirror of https://github.com/golang/go synced 2024-11-20 06:44:40 -07:00

cmd/5g: enable xtramodes optimisation

xtramodes' C_PBIT optimisation transforms:

MOVW          0(R3),R1
ADD           $4,R3,R3

into:

MOVW.P        4(R3),R1

and the AADD optimisation tranforms:

ADD          R0,R1
MOVBU        0(R1),R0

into:

MOVBU        R0<<0(R1),R0

5g does not appear to generate sequences that
can be transformed by xtramodes' AMOVW.

R=remyoudompheng, rsc
CC=golang-dev
https://golang.org/cl/6817085
This commit is contained in:
Dave Cheney 2012-11-11 07:51:20 +11:00
parent e9a3087e29
commit 3f26c5e124

View File

@ -49,7 +49,6 @@ peep(void)
int t; int t;
p1 = nil; p1 = nil;
USED(p1); // ... in unreachable code...
/* /*
* complete R structure * complete R structure
*/ */
@ -120,7 +119,7 @@ loop1:
} }
break; break;
#ifdef NOTDEF #ifdef NOTDEF
if(p->scond == C_SCOND_NONE) if(p->scond == C_SCOND_NONE)
if(regtyp(&p->to)) if(regtyp(&p->to))
if(isdconst(&p->from)) { if(isdconst(&p->from)) {
@ -175,22 +174,21 @@ loop1:
break; break;
} }
} }
#ifdef NOTDEF
// for(r=firstr; r!=R; r=r->link) { for(r=firstr; r!=R; r=r->link) {
// p = r->prog; p = r->prog;
// switch(p->as) { switch(p->as) {
// case AMOVW: case AMOVW:
// case AMOVB: case AMOVB:
// case AMOVBU: case AMOVBU:
// if(p->from.type == D_OREG && p->from.offset == 0) if(p->from.type == D_OREG && p->from.offset == 0)
// xtramodes(r, &p->from); xtramodes(r, &p->from);
// else else
// if(p->to.type == D_OREG && p->to.offset == 0) if(p->to.type == D_OREG && p->to.offset == 0)
// xtramodes(r, &p->to); xtramodes(r, &p->to);
// else else
// continue; continue;
// break; break;
// case ACMP: // case ACMP:
// /* // /*
// * elide CMP $0,x if calculation of x can set condition codes // * elide CMP $0,x if calculation of x can set condition codes
@ -258,13 +256,17 @@ loop1:
// r2->prog->as = t; // r2->prog->as = t;
// excise(r); // excise(r);
// continue; // continue;
// } }
// } }
predicate(); // predicate();
#endif
} }
/*
* uniqp returns a "unique" predecessor to instruction r.
* If the instruction is the first one or has multiple
* predecessors due to jump, R is returned.
*/
Reg* Reg*
uniqp(Reg *r) uniqp(Reg *r)
{ {
@ -737,6 +739,11 @@ shiftprop(Reg *r)
return 1; return 1;
} }
/*
* findpre returns the last instruction mentioning v
* before r. It must be a set, and there must be
* a unique path from that instruction to r.
*/
Reg* Reg*
findpre(Reg *r, Adr *v) findpre(Reg *r, Adr *v)
{ {
@ -757,6 +764,10 @@ findpre(Reg *r, Adr *v)
return R; return R;
} }
/*
* findinc finds ADD instructions with a constant
* argument which falls within the immed_12 range.
*/
Reg* Reg*
findinc(Reg *r, Reg *r2, Adr *v) findinc(Reg *r, Reg *r2, Adr *v)
{ {
@ -847,6 +858,19 @@ finduse(Reg *r, Adr *v)
return findu1(r, v); return findu1(r, v);
} }
/*
* xtramodes enables the ARM post increment and
* shift offset addressing modes to transform
* MOVW 0(R3),R1
* ADD $4,R3,R3
* into
* MOVW.P 4(R3),R1
* and
* ADD R0,R1
* MOVBU 0(R1),R0
* into
* MOVBU R0<<0(R1),R0
*/
int int
xtramodes(Reg *r, Adr *a) xtramodes(Reg *r, Adr *a)
{ {
@ -855,8 +879,6 @@ xtramodes(Reg *r, Adr *a)
Adr v; Adr v;
p = r->prog; p = r->prog;
if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG) /* byte load */
return 0;
v = *a; v = *a;
v.type = D_REG; v.type = D_REG;
r1 = findpre(r, &v); r1 = findpre(r, &v);
@ -865,6 +887,9 @@ xtramodes(Reg *r, Adr *a)
if(p1->to.type == D_REG && p1->to.reg == v.reg) if(p1->to.type == D_REG && p1->to.reg == v.reg)
switch(p1->as) { switch(p1->as) {
case AADD: case AADD:
if(p1->scond & C_SBIT)
// avoid altering ADD.S/ADC sequences.
break;
if(p1->from.type == D_REG || if(p1->from.type == D_REG ||
(p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 && (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
(p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) || (p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||