Commit acbe6c94 authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/6g: avoid taking the address of slices unnecessarily.

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
parent 212ce41d
...@@ -502,7 +502,7 @@ void ...@@ -502,7 +502,7 @@ void
agen(Node *n, Node *res) agen(Node *n, Node *res)
{ {
Node *nl, *nr; Node *nl, *nr;
Node n1, n2, n3, tmp, n4, n5; Node n1, n2, n3, tmp, tmp2, n4, n5, nlen;
Prog *p1; Prog *p1;
uint32 w; uint32 w;
uint64 v; uint64 v;
...@@ -565,6 +565,7 @@ agen(Node *n, Node *res) ...@@ -565,6 +565,7 @@ agen(Node *n, Node *res)
case OINDEX: case OINDEX:
w = n->type->width; w = n->type->width;
// Generate the non-addressable child first.
if(nr->addable) if(nr->addable)
goto irad; goto irad;
if(nl->addable) { if(nl->addable) {
...@@ -574,18 +575,41 @@ agen(Node *n, Node *res) ...@@ -574,18 +575,41 @@ agen(Node *n, Node *res)
} }
if(!isconst(nl, CTSTR)) { if(!isconst(nl, CTSTR)) {
regalloc(&n3, types[tptr], res); 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; goto index;
} }
tempname(&tmp, nr->type); tempname(&tmp, nr->type);
cgen(nr, &tmp); cgen(nr, &tmp);
nr = &tmp; nr = &tmp;
irad: irad:
if(!isconst(nl, CTSTR)) { if(!isconst(nl, CTSTR)) {
regalloc(&n3, types[tptr], res); 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)) { if(!isconst(nr, CTINT)) {
regalloc(&n1, nr->type, N); regalloc(&n1, nr->type, N);
...@@ -596,6 +620,7 @@ agen(Node *n, Node *res) ...@@ -596,6 +620,7 @@ agen(Node *n, Node *res)
index: index:
// &a is in &n3 (allocated in res) // &a is in &n3 (allocated in res)
// i is in &n1 (if not constant) // i is in &n1 (if not constant)
// len(a) is in nlen (if needed)
// w is width // w is width
// explicit check for nil if array is large enough // explicit check for nil if array is large enough
...@@ -617,22 +642,13 @@ agen(Node *n, Node *res) ...@@ -617,22 +642,13 @@ agen(Node *n, Node *res)
v = mpgetfix(nr->val.u.xval); v = mpgetfix(nr->val.u.xval);
if(isslice(nl->type) || nl->type->etype == TSTRING) { if(isslice(nl->type) || nl->type->etype == TSTRING) {
if(!debug['B'] && !n->bounded) { if(!debug['B'] && !n->bounded) {
n1 = n3;
n1.op = OINDREG;
n1.type = types[tptr];
n1.xoffset = Array_nel;
nodconst(&n2, types[TUINT32], v); 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); p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
ginscall(panicindex, -1); ginscall(panicindex, -1);
patch(p1, pc); patch(p1, pc);
} }
regfree(&nlen);
n1 = n3;
n1.op = OINDREG;
n1.type = types[tptr];
n1.xoffset = Array_array;
gmove(&n1, &n3);
} }
if (v*w != 0) if (v*w != 0)
...@@ -658,24 +674,19 @@ agen(Node *n, Node *res) ...@@ -658,24 +674,19 @@ agen(Node *n, Node *res)
if(is64(nr->type)) if(is64(nr->type))
t = types[TUINT64]; t = types[TUINT64];
if(isconst(nl, CTSTR)) { 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) { } 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)) { if(is64(nr->type)) {
regalloc(&n5, t, N); regalloc(&n5, t, N);
gmove(&n1, &n5); gmove(&nlen, &n5);
n1 = n5; regfree(&nlen);
nlen = n5;
} }
} else { } 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); p1 = gbranch(optoas(OLT, t), T, +1);
if(n5.op != OXXX)
regfree(&n5);
ginscall(panicindex, -1); ginscall(panicindex, -1);
patch(p1, pc); patch(p1, pc);
} }
...@@ -689,14 +700,6 @@ agen(Node *n, Node *res) ...@@ -689,14 +700,6 @@ agen(Node *n, Node *res)
goto indexdone; 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) { if(w == 0) {
// nothing to do // nothing to do
} else if(w == 1 || w == 2 || w == 4 || w == 8) { } else if(w == 1 || w == 2 || w == 4 || w == 8) {
...@@ -713,6 +716,8 @@ agen(Node *n, Node *res) ...@@ -713,6 +716,8 @@ agen(Node *n, Node *res)
gmove(&n3, res); gmove(&n3, res);
regfree(&n2); regfree(&n2);
regfree(&n3); regfree(&n3);
if(!isconst(nl, CTSTR) && !isfixedarray(nl->type))
regfree(&nlen);
break; break;
case ONAME: case ONAME:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment