]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/6g: avoid taking the address of slices unnecessarily.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Fri, 7 Sep 2012 04:54:42 +0000 (06:54 +0200)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Fri, 7 Sep 2012 04:54:42 +0000 (06:54 +0200)
The main case where it happens is when evaluating &s[i] without
bounds checking, which usually happens during range loops (i=0).

This allows registerization of the corresponding variables,
saving 16 bytes of stack frame for each such range loop and a
LEAQ instruction.

R=golang-dev, rsc, dave
CC=golang-dev, remy
https://golang.org/cl/6497073

src/cmd/6g/cgen.c

index c2760375ffcd3c35f4e7eb91ad7c4052a37afe3d..4905a011c71498c101661e02c09e625bebda2ccc 100644 (file)
@@ -502,7 +502,7 @@ void
 agen(Node *n, Node *res)
 {
        Node *nl, *nr;
-       Node n1, n2, n3, tmp, n4, n5;
+       Node n1, n2, n3, tmp, tmp2, n4, n5, nlen;
        Prog *p1;
        uint32 w;
        uint64 v;
@@ -565,6 +565,7 @@ agen(Node *n, Node *res)
 
        case OINDEX:
                w = n->type->width;
+               // Generate the non-addressable child first.
                if(nr->addable)
                        goto irad;
                if(nl->addable) {
@@ -574,18 +575,41 @@ agen(Node *n, Node *res)
                        }
                        if(!isconst(nl, CTSTR)) {
                                regalloc(&n3, types[tptr], res);
-                               agen(nl, &n3);
+                               if(isfixedarray(nl->type))
+                                       agen(nl, &n3);
+                               else {
+                                       igen(nl, &nlen, res);
+                                       nlen.type = types[tptr];
+                                       nlen.xoffset += Array_array;
+                                       gmove(&nlen, &n3);
+                                       nlen.type = types[TUINT32];
+                                       nlen.xoffset += Array_nel-Array_array;
+                               }
                        }
                        goto index;
                }
                tempname(&tmp, nr->type);
                cgen(nr, &tmp);
                nr = &tmp;
-
        irad:
                if(!isconst(nl, CTSTR)) {
                        regalloc(&n3, types[tptr], res);
-                       agen(nl, &n3);
+                       if(isfixedarray(nl->type))
+                               agen(nl, &n3);
+                       else {
+                               if(!nl->addable) {
+                                       // igen will need an addressable node.
+                                       tempname(&tmp2, nl->type);
+                                       cgen(nl, &tmp2);
+                                       nl = &tmp2;
+                               }
+                               igen(nl, &nlen, res);
+                               nlen.type = types[tptr];
+                               nlen.xoffset += Array_array;
+                               gmove(&nlen, &n3);
+                               nlen.type = types[TUINT32];
+                               nlen.xoffset += Array_nel-Array_array;
+                       }
                }
                if(!isconst(nr, CTINT)) {
                        regalloc(&n1, nr->type, N);
@@ -596,6 +620,7 @@ agen(Node *n, Node *res)
        index:
                // &a 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
@@ -617,22 +642,13 @@ agen(Node *n, Node *res)
                        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;
                                        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);
+                               regfree(&nlen);
                        }
 
                        if (v*w != 0)
@@ -658,24 +674,19 @@ agen(Node *n, Node *res)
                        if(is64(nr->type))
                                t = types[TUINT64];
                        if(isconst(nl, CTSTR)) {
-                               nodconst(&n1, t, nl->val.u.sval->len);
+                               nodconst(&nlen, t, nl->val.u.sval->len);
                        } else if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                               n1 = n3;
-                               n1.op = OINDREG;
-                               n1.type = types[TUINT32];
-                               n1.xoffset = Array_nel;
                                if(is64(nr->type)) {
                                        regalloc(&n5, t, N);
-                                       gmove(&n1, &n5);
-                                       n1 = n5;
+                                       gmove(&nlen, &n5);
+                                       regfree(&nlen);
+                                       nlen = n5;
                                }
                        } else {
-                               nodconst(&n1, t, nl->type->bound);
+                               nodconst(&nlen, t, nl->type->bound);
                        }
-                       gins(optoas(OCMP, t), &n2, &n1);
+                       gins(optoas(OCMP, t), &n2, &nlen);
                        p1 = gbranch(optoas(OLT, t), T, +1);
-                       if(n5.op != OXXX)
-                               regfree(&n5);
                        ginscall(panicindex, -1);
                        patch(p1, pc);
                }
@@ -689,14 +700,6 @@ agen(Node *n, Node *res)
                        goto indexdone;
                }
 
-               if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                       n1 = n3;
-                       n1.op = OINDREG;
-                       n1.type = types[tptr];
-                       n1.xoffset = Array_array;
-                       gmove(&n1, &n3);
-               }
-
                if(w == 0) {
                        // nothing to do
                } else if(w == 1 || w == 2 || w == 4 || w == 8) {
@@ -713,6 +716,8 @@ agen(Node *n, Node *res)
                gmove(&n3, res);
                regfree(&n2);
                regfree(&n3);
+               if(!isconst(nl, CTSTR) && !isfixedarray(nl->type))
+                       regfree(&nlen);
                break;
 
        case ONAME: