]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/8g: do not take the address of string/slice for &s[i]
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Tue, 2 Oct 2012 06:19:27 +0000 (08:19 +0200)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Tue, 2 Oct 2012 06:19:27 +0000 (08:19 +0200)
A similar change was made in 6g recently.

LEALs in cmd/go: 31440 before, 27867 after.

benchmark                 old ns/op    new ns/op    delta
BenchmarkBinaryTree17    7065794000   6723617000   -4.84%
BenchmarkFannkuch11      7767395000   7477945000   -3.73%
BenchmarkGobDecode         34708140     34857820   +0.43%
BenchmarkGobEncode         10998780     10960060   -0.35%
BenchmarkGzip            1603630000   1471052000   -8.27%
BenchmarkGunzip           242573900    240650400   -0.79%
BenchmarkJSONEncode       120842200    117966100   -2.38%
BenchmarkJSONDecode       247254900    249103100   +0.75%
BenchmarkMandelbrot200     29237330     29241790   +0.02%
BenchmarkParse              8111320      8096865   -0.18%
BenchmarkRevcomp         2595780000   2694153000   +3.79%
BenchmarkTemplate         276679600    264497000   -4.40%

benchmark                              old ns/op    new ns/op    delta
BenchmarkAppendFloatDecimal                  429          416   -3.03%
BenchmarkAppendFloat                         780          740   -5.13%
BenchmarkAppendFloatExp                      746          700   -6.17%
BenchmarkAppendFloatNegExp                   752          694   -7.71%
BenchmarkAppendFloatBig                     1228         1108   -9.77%
BenchmarkAppendFloat32Integer                457          416   -8.97%
BenchmarkAppendFloat32ExactFraction          662          631   -4.68%
BenchmarkAppendFloat32Point                  771          735   -4.67%
BenchmarkAppendFloat32Exp                    722          672   -6.93%
BenchmarkAppendFloat32NegExp                 724          659   -8.98%
BenchmarkAppendFloat64Fixed1                 429          400   -6.76%
BenchmarkAppendFloat64Fixed2                 463          442   -4.54%

Update #1914.

R=golang-dev, daniel.morsing, rsc
CC=golang-dev
https://golang.org/cl/6574043

src/cmd/8g/cgen.c
src/cmd/8g/gg.h

index 3fd0cd753e18c3e9f3b3ce21aa9da22facc6dfa4..708bc531897ff33f4f8a2d57f2fe73e87988bf84 100644 (file)
@@ -456,23 +456,30 @@ flt2:     // binary
 }
 
 /*
- * generate array index into res.
- * n might be any size; res is 32-bit.
+ * generate an addressable node in res, containing the value of n.
+ * n is an array index, and might be any size; res width is <= 32-bit.
  * returns Prog* to patch to panic call.
  */
 Prog*
-cgenindex(Node *n, Node *res)
+igenindex(Node *n, Node *res)
 {
        Node tmp, lo, hi, zero;
 
        if(!is64(n->type)) {
-               cgen(n, res);
+               if(n->addable) {
+                       // nothing to do.
+                       *res = *n;
+               } else {
+                       tempname(res, types[TUINT32]);
+                       cgen(n, res);
+               }
                return nil;
        }
 
        tempname(&tmp, types[TINT64]);
        cgen(n, &tmp);
        split64(&tmp, &lo, &hi);
+       tempname(res, types[TUINT32]);
        gmove(&lo, res);
        if(debug['B']) {
                splitclean();
@@ -492,7 +499,7 @@ void
 agen(Node *n, Node *res)
 {
        Node *nl, *nr;
-       Node n1, n2, n3, n4, tmp;
+       Node n1, n2, n3, n4, tmp, nlen;
        Type *t;
        uint32 w;
        uint64 v;
@@ -574,109 +581,117 @@ agen(Node *n, Node *res)
                p2 = nil;  // to be patched to panicindex.
                w = n->type->width;
                if(nr->addable) {
-                       if(!isconst(nr, CTINT))
-                               tempname(&tmp, types[TINT32]);
+                       // Generate &nl first, and move nr into register.
                        if(!isconst(nl, CTSTR))
-                               agenr(nl, &n3, res);
+                               igen(nl, &n3, res);
                        if(!isconst(nr, CTINT)) {
-                               p2 = cgenindex(nr, &tmp);
+                               p2 = igenindex(nr, &tmp);
                                regalloc(&n1, tmp.type, N);
                                gmove(&tmp, &n1);
                        }
                } else if(nl->addable) {
+                       // Generate nr first, and move &nl into register.
                        if(!isconst(nr, CTINT)) {
-                               tempname(&tmp, types[TINT32]);
-                               p2 = cgenindex(nr, &tmp);
+                               p2 = igenindex(nr, &tmp);
                                regalloc(&n1, tmp.type, N);
                                gmove(&tmp, &n1);
                        }
-                       if(!isconst(nl, CTSTR)) {
-                               regalloc(&n3, types[tptr], res);
-                               agen(nl, &n3);
-                       }
+                       if(!isconst(nl, CTSTR))
+                               igen(nl, &n3, res);
                } else {
-                       tempname(&tmp, types[TINT32]);
-                       p2 = cgenindex(nr, &tmp);
+                       p2 = igenindex(nr, &tmp);
                        nr = &tmp;
                        if(!isconst(nl, CTSTR))
-                               agenr(nl, &n3, res);
+                               igen(nl, &n3, res);
                        regalloc(&n1, tmp.type, N);
                        gins(optoas(OAS, tmp.type), &tmp, &n1);
                }
 
-               // &a is in &n3 (allocated in res)
-               // i is in &n1 (if not constant)
+               // For fixed array we really want the pointer in n3.
+               if(isfixedarray(nl->type)) {
+                       regalloc(&n2, types[tptr], &n3);
+                       agen(&n3, &n2);
+                       regfree(&n3);
+                       n3 = n2;
+               }
+
+               // &a[0] is in n3 (allocated in res)
+               // i is in n1 (if not constant)
+               // len(a) is in nlen (if needed)
                // w is width
 
                // explicit check for nil if array is large enough
                // that we might derive too big a pointer.
                if(isfixedarray(nl->type) && nl->type->width >= unmappedzero) {
-                       regalloc(&n4, types[tptr], &n3);
-                       gmove(&n3, &n4);
+                       n4 = n3;
                        n4.op = OINDREG;
                        n4.type = types[TUINT8];
                        n4.xoffset = 0;
                        gins(ATESTB, nodintconst(0), &n4);
-                       regfree(&n4);
                }
 
                // constant index
                if(isconst(nr, CTINT)) {
                        if(isconst(nl, CTSTR))
-                               fatal("constant string constant index");
+                               fatal("constant string constant index");  // front end should handle
                        v = mpgetfix(nr->val.u.xval);
                        if(isslice(nl->type) || nl->type->etype == TSTRING) {
                                if(!debug['B'] && !n->bounded) {
-                                       n1 = n3;
-                                       n1.op = OINDREG;
-                                       n1.type = types[tptr];
-                                       n1.xoffset = Array_nel;
+                                       nlen = n3;
+                                       nlen.type = types[TUINT32];
+                                       nlen.xoffset += Array_nel;
                                        nodconst(&n2, types[TUINT32], v);
-                                       gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
+                                       gins(optoas(OCMP, types[TUINT32]), &nlen, &n2);
                                        p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
                                        ginscall(panicindex, -1);
                                        patch(p1, pc);
                                }
-
-                               n1 = n3;
-                               n1.op = OINDREG;
-                               n1.type = types[tptr];
-                               n1.xoffset = Array_array;
-                               gmove(&n1, &n3);
                        }
 
+                       // Load base pointer in n2 = n3.
+                       regalloc(&n2, types[tptr], &n3);
+                       n3.type = types[tptr];
+                       n3.xoffset += Array_array;
+                       gmove(&n3, &n2);
+                       regfree(&n3);
                        if (v*w != 0) {
-                               nodconst(&n2, types[tptr], v*w);
-                               gins(optoas(OADD, types[tptr]), &n2, &n3);
+                               nodconst(&n1, types[tptr], v*w);
+                               gins(optoas(OADD, types[tptr]), &n1, &n2);
                        }
-                       gmove(&n3, res);
-                       regfree(&n3);
+                       gmove(&n2, res);
+                       regfree(&n2);
                        break;
                }
 
-               regalloc(&n2, types[TINT32], &n1);                      // i
+               // i is in register n1, extend to 32 bits.
+               t = types[TUINT32];
+               if(issigned[n1.type->etype])
+                       t = types[TINT32];
+
+               regalloc(&n2, t, &n1);                  // i
                gmove(&n1, &n2);
                regfree(&n1);
 
                if(!debug['B'] && !n->bounded) {
                        // check bounds
-                       if(isconst(nl, CTSTR))
-                               nodconst(&n1, types[TUINT32], nl->val.u.sval->len);
-                       else if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                               n1 = n3;
-                               n1.op = OINDREG;
-                               n1.type = types[tptr];
-                               n1.xoffset = Array_nel;
-                       } else
-                               nodconst(&n1, types[TUINT32], nl->type->bound);
-                       gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
-                       p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
+                       t = types[TUINT32];
+                       if(isconst(nl, CTSTR)) {
+                               nodconst(&nlen, t, nl->val.u.sval->len);
+                       } else if(isslice(nl->type) || nl->type->etype == TSTRING) {
+                               nlen = n3;
+                               nlen.type = t;
+                               nlen.xoffset += Array_nel;
+                       } else {
+                               nodconst(&nlen, t, nl->type->bound);
+                       }
+                       gins(optoas(OCMP, t), &n2, &nlen);
+                       p1 = gbranch(optoas(OLT, t), T, +1);
                        if(p2)
                                patch(p2, pc);
                        ginscall(panicindex, -1);
                        patch(p1, pc);
                }
-               
+
                if(isconst(nl, CTSTR)) {
                        regalloc(&n3, types[tptr], res);
                        p1 = gins(ALEAL, N, &n3);
@@ -686,24 +701,27 @@ agen(Node *n, Node *res)
                        goto indexdone;
                }
 
+               // Load base pointer in n3.
+               regalloc(&tmp, types[tptr], &n3);
                if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                       n1 = n3;
-                       n1.op = OINDREG;
-                       n1.type = types[tptr];
-                       n1.xoffset = Array_array;
-                       gmove(&n1, &n3);
+                       n3.type = types[tptr];
+                       n3.xoffset += Array_array;
+                       gmove(&n3, &tmp);
                }
+               regfree(&n3);
+               n3 = tmp;
 
                if(w == 0) {
                        // nothing to do
                } else if(w == 1 || w == 2 || w == 4 || w == 8) {
+                       // LEAL (n3)(n2*w), n3
                        p1 = gins(ALEAL, &n2, &n3);
                        p1->from.scale = w;
                        p1->from.index = p1->from.type;
                        p1->from.type = p1->to.type + D_INDIR;
                } else {
-                       nodconst(&n1, types[TUINT32], w);
-                       gins(optoas(OMUL, types[TUINT32]), &n1, &n2);
+                       nodconst(&tmp, types[TUINT32], w);
+                       gins(optoas(OMUL, types[TUINT32]), &tmp, &n2);
                        gins(optoas(OADD, types[tptr]), &n2, &n3);
                }
 
@@ -861,23 +879,6 @@ igen(Node *n, Node *a, Node *res)
        a->type = n->type;
 }
 
-/*
- * generate:
- *     newreg = &n;
- *
- * caller must regfree(a).
- */
-void
-agenr(Node *n, Node *a, Node *res)
-{
-       Node n1;
-
-       tempname(&n1, types[tptr]);
-       agen(n, &n1);
-       regalloc(a, types[tptr], res);
-       gmove(&n1, a);
-}
-
 /*
  * branch gen
  *     if(n == true) goto to;
index e905303a5d114ec84b1c360a7e974e921c883dd2..09718855bd898cd5ae61e8e448b5c0d811dd63ca 100644 (file)
@@ -95,7 +95,6 @@ void  ginscall(Node*, int);
  * cgen.c
  */
 void   agen(Node*, Node*);
-void   agenr(Node *n, Node *a, Node *res);
 void   igen(Node*, Node*, Node*);
 vlong  fieldoffset(Type*, Node*);
 void   sgen(Node*, Node*, int64);