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

cmd/6g, cmd/8g: add OINDREG, ODOT, ODOTPTR cases to igen.

Apart from reducing the number of LEAL/LEAQ instructions by about
30%, it gives 8g easier registerization in several cases,
for example in strconv. Performance with 6g is not affected.

Before (386):
src/pkg/strconv/decimal.go:22   TEXT  (*decimal).String+0(SB),$240-12
src/pkg/strconv/extfloat.go:540 TEXT  (*extFloat).ShortestDecimal+0(SB),$584-20

After (386):
src/pkg/strconv/decimal.go:22   TEXT  (*decimal).String+0(SB),$196-12
src/pkg/strconv/extfloat.go:540 TEXT  (*extFloat).ShortestDecimal+0(SB),$420-20

Benchmarks with GOARCH=386 (on a Core 2).

benchmark                 old ns/op    new ns/op    delta
BenchmarkBinaryTree17    7110191000   7079644000   -0.43%
BenchmarkFannkuch11      7769274000   7766514000   -0.04%
BenchmarkGobDecode         33454820     34755400   +3.89%
BenchmarkGobEncode         11675710     11007050   -5.73%
BenchmarkGzip            2013519000   1593855000  -20.84%
BenchmarkGunzip           253368200    242667600   -4.22%
BenchmarkJSONEncode       152443900    120763400  -20.78%
BenchmarkJSONDecode       304112800    247461800  -18.63%
BenchmarkMandelbrot200     29245520     29240490   -0.02%
BenchmarkParse              8484105      8088660   -4.66%
BenchmarkRevcomp         2695688000   2841263000   +5.40%
BenchmarkTemplate         363759800    277271200  -23.78%

benchmark                       old ns/op    new ns/op    delta
BenchmarkAtof64Decimal                127          129   +1.57%
BenchmarkAtof64Float                  166          164   -1.20%
BenchmarkAtof64FloatExp               308          300   -2.60%
BenchmarkAtof64Big                    584          571   -2.23%
BenchmarkAppendFloatDecimal           440          430   -2.27%
BenchmarkAppendFloat                  995          776  -22.01%
BenchmarkAppendFloatExp               897          746  -16.83%
BenchmarkAppendFloatNegExp            900          752  -16.44%
BenchmarkAppendFloatBig              1528         1228  -19.63%
BenchmarkAppendFloat32Integer         443          453   +2.26%
BenchmarkAppendFloat32ExactFraction   812          661  -18.60%
BenchmarkAppendFloat32Point          1002          773  -22.85%
BenchmarkAppendFloat32Exp             858          725  -15.50%
BenchmarkAppendFloat32NegExp          848          728  -14.15%
BenchmarkAppendFloat64Fixed1          447          431   -3.58%
BenchmarkAppendFloat64Fixed2          480          462   -3.75%
BenchmarkAppendFloat64Fixed3          461          457   -0.87%
BenchmarkAppendFloat64Fixed4          509          484   -4.91%

Update #1914.

R=rsc, nigeltao
CC=golang-dev, remy
https://golang.org/cl/6494107
This commit is contained in:
Rémy Oudompheng 2012-09-24 23:07:44 +02:00
parent 65c7dc4ace
commit f4e76d5e02
4 changed files with 76 additions and 11 deletions

View File

@ -798,7 +798,7 @@ igen(Node *n, Node *a, Node *res)
Type *fp;
Iter flist;
Node n1, n2;
switch(n->op) {
case ONAME:
if((n->class&PHEAP) || n->class == PPARAMREF)
@ -806,6 +806,39 @@ igen(Node *n, Node *a, Node *res)
*a = *n;
return;
case OINDREG:
// Increase the refcount of the register so that igen's caller
// has to call regfree.
if(n->val.u.reg != D_SP)
reg[n->val.u.reg]++;
*a = *n;
return;
case ODOT:
igen(n->left, a, res);
a->xoffset += n->xoffset;
a->type = n->type;
return;
case ODOTPTR:
regalloc(a, types[tptr], res);
cgen(n->left, a);
if(n->xoffset != 0) {
// explicit check for nil if struct is large enough
// that we might derive too big a pointer.
if(n->left->type->type->width >= unmappedzero) {
n1 = *a;
n1.op = OINDREG;
n1.type = types[TUINT8];
n1.xoffset = 0;
gins(ATESTB, nodintconst(0), &n1);
}
}
a->op = OINDREG;
a->xoffset += n->xoffset;
a->type = n->type;
return;
case OCALLFUNC:
fp = structfirst(&flist, getoutarg(n->left->type));
cgen_call(n, 0);

View File

@ -342,9 +342,8 @@ cgen(Node *n, Node *res)
}
if(isslice(nl->type)) {
igen(nl, &n1, res);
n1.op = OINDREG;
n1.type = types[TUINT32];
n1.xoffset = Array_cap;
n1.xoffset += Array_cap;
gmove(&n1, res);
regfree(&n1);
break;
@ -781,10 +780,10 @@ agen(Node *n, Node *res)
void
igen(Node *n, Node *a, Node *res)
{
Node n1;
Type *fp;
Iter flist;
Node n1;
switch(n->op) {
case ONAME:
if((n->class&PHEAP) || n->class == PPARAMREF)
@ -792,6 +791,39 @@ igen(Node *n, Node *a, Node *res)
*a = *n;
return;
case OINDREG:
// Increase the refcount of the register so that igen's caller
// has to call regfree.
if(n->val.u.reg != D_SP)
reg[n->val.u.reg]++;
*a = *n;
return;
case ODOT:
igen(n->left, a, res);
a->xoffset += n->xoffset;
a->type = n->type;
return;
case ODOTPTR:
regalloc(a, types[tptr], res);
cgen(n->left, a);
if(n->xoffset != 0) {
// explicit check for nil if struct is large enough
// that we might derive too big a pointer.
if(n->left->type->type->width >= unmappedzero) {
n1 = *a;
n1.op = OINDREG;
n1.type = types[TUINT8];
n1.xoffset = 0;
gins(ATESTB, nodintconst(0), &n1);
}
}
a->op = OINDREG;
a->xoffset += n->xoffset;
a->type = n->type;
return;
case OCALLFUNC:
fp = structfirst(&flist, getoutarg(n->left->type));
cgen_call(n, 0);

View File

@ -766,7 +766,7 @@ ginit(void)
for(i=0; i<nelem(reg); i++)
reg[i] = 1;
for(i=D_AL; i<=D_DI; i++)
for(i=D_AX; i<=D_DI; i++)
reg[i] = 0;
for(i=0; i<nelem(resvd); i++)
reg[resvd[i]]++;
@ -782,7 +782,7 @@ gclean(void)
for(i=0; i<nelem(resvd); i++)
reg[resvd[i]]--;
for(i=D_AL; i<=D_DI; i++)
for(i=D_AX; i<=D_DI; i++)
if(reg[i])
yyerror("reg %R left allocated at %ux", i, regpc[i]);
}
@ -792,7 +792,7 @@ anyregalloc(void)
{
int i, j;
for(i=D_AL; i<=D_DI; i++) {
for(i=D_AX; i<=D_DI; i++) {
if(reg[i] == 0)
goto ok;
for(j=0; j<nelem(resvd); j++)

View File

@ -170,11 +170,11 @@ struct Type
vlong argwid;
// most nodes
Type* type;
vlong width; // offset in TFIELD, width in all others
Type* type; // actual type for TFIELD, element type for TARRAY, TCHAN, TMAP, TPTRxx
vlong width; // offset in TFIELD, width in all others
// TFIELD
Type* down; // also used in TMAP
Type* down; // next struct field, also key type in TMAP
Strlit* note; // literal string annotation
// TARRAY