]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/6g, cmd/8g: add OINDREG, ODOT, ODOTPTR cases to igen.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 24 Sep 2012 21:07:44 +0000 (23:07 +0200)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 24 Sep 2012 21:07:44 +0000 (23:07 +0200)
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

src/cmd/6g/cgen.c
src/cmd/8g/cgen.c
src/cmd/8g/gsubr.c
src/cmd/gc/go.h

index ce3a3eba9ab74dabd0691f85520490db68f87ef5..27ab1052c3cd429b04501c0a783d0880d96c232e 100644 (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);
index ed188fed627728d2cc445ff69a61a4e66f1d3c24..6684bf94d5a5b334437dd5162510c42c0e5744cd 100644 (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);
index dcbd6dbcfaedc6d2d224f7ee10bb548515a7a6b2..a94086e7c167e50514a9b1a5c498389f462d725a 100644 (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++)
index 89b91f666594cba26af97537c2aa2c398ae78762..326ede3063a00603846139c68fb2a7926fe13627 100644 (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