mirror of
https://github.com/golang/go
synced 2024-11-25 17:07:57 -07:00
cmd/8g: do not take the address of string/slice for &s[i]
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
This commit is contained in:
parent
041fc8bf96
commit
2de064b63c
@ -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)) {
|
||||
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,103 +581,111 @@ 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);
|
||||
}
|
||||
|
||||
if (v*w != 0) {
|
||||
nodconst(&n2, types[tptr], v*w);
|
||||
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
||||
}
|
||||
gmove(&n3, res);
|
||||
// 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(&n1, types[tptr], v*w);
|
||||
gins(optoas(OADD, types[tptr]), &n1, &n2);
|
||||
}
|
||||
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);
|
||||
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user