mirror of
https://github.com/golang/go
synced 2024-11-24 21:10:04 -07:00
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
This commit is contained in:
parent
212ce41d00
commit
acbe6c94d7
@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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:
|
||||||
|
Loading…
Reference in New Issue
Block a user