mirror of
https://github.com/golang/go
synced 2024-11-22 08:34:40 -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.
|
* generate an addressable node in res, containing the value of n.
|
||||||
* n might be any size; res is 32-bit.
|
* n is an array index, and might be any size; res width is <= 32-bit.
|
||||||
* returns Prog* to patch to panic call.
|
* returns Prog* to patch to panic call.
|
||||||
*/
|
*/
|
||||||
Prog*
|
Prog*
|
||||||
cgenindex(Node *n, Node *res)
|
igenindex(Node *n, Node *res)
|
||||||
{
|
{
|
||||||
Node tmp, lo, hi, zero;
|
Node tmp, lo, hi, zero;
|
||||||
|
|
||||||
if(!is64(n->type)) {
|
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;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
tempname(&tmp, types[TINT64]);
|
tempname(&tmp, types[TINT64]);
|
||||||
cgen(n, &tmp);
|
cgen(n, &tmp);
|
||||||
split64(&tmp, &lo, &hi);
|
split64(&tmp, &lo, &hi);
|
||||||
|
tempname(res, types[TUINT32]);
|
||||||
gmove(&lo, res);
|
gmove(&lo, res);
|
||||||
if(debug['B']) {
|
if(debug['B']) {
|
||||||
splitclean();
|
splitclean();
|
||||||
@ -492,7 +499,7 @@ void
|
|||||||
agen(Node *n, Node *res)
|
agen(Node *n, Node *res)
|
||||||
{
|
{
|
||||||
Node *nl, *nr;
|
Node *nl, *nr;
|
||||||
Node n1, n2, n3, n4, tmp;
|
Node n1, n2, n3, n4, tmp, nlen;
|
||||||
Type *t;
|
Type *t;
|
||||||
uint32 w;
|
uint32 w;
|
||||||
uint64 v;
|
uint64 v;
|
||||||
@ -574,109 +581,117 @@ agen(Node *n, Node *res)
|
|||||||
p2 = nil; // to be patched to panicindex.
|
p2 = nil; // to be patched to panicindex.
|
||||||
w = n->type->width;
|
w = n->type->width;
|
||||||
if(nr->addable) {
|
if(nr->addable) {
|
||||||
if(!isconst(nr, CTINT))
|
// Generate &nl first, and move nr into register.
|
||||||
tempname(&tmp, types[TINT32]);
|
|
||||||
if(!isconst(nl, CTSTR))
|
if(!isconst(nl, CTSTR))
|
||||||
agenr(nl, &n3, res);
|
igen(nl, &n3, res);
|
||||||
if(!isconst(nr, CTINT)) {
|
if(!isconst(nr, CTINT)) {
|
||||||
p2 = cgenindex(nr, &tmp);
|
p2 = igenindex(nr, &tmp);
|
||||||
regalloc(&n1, tmp.type, N);
|
regalloc(&n1, tmp.type, N);
|
||||||
gmove(&tmp, &n1);
|
gmove(&tmp, &n1);
|
||||||
}
|
}
|
||||||
} else if(nl->addable) {
|
} else if(nl->addable) {
|
||||||
|
// Generate nr first, and move &nl into register.
|
||||||
if(!isconst(nr, CTINT)) {
|
if(!isconst(nr, CTINT)) {
|
||||||
tempname(&tmp, types[TINT32]);
|
p2 = igenindex(nr, &tmp);
|
||||||
p2 = cgenindex(nr, &tmp);
|
|
||||||
regalloc(&n1, tmp.type, N);
|
regalloc(&n1, tmp.type, N);
|
||||||
gmove(&tmp, &n1);
|
gmove(&tmp, &n1);
|
||||||
}
|
}
|
||||||
if(!isconst(nl, CTSTR)) {
|
if(!isconst(nl, CTSTR))
|
||||||
regalloc(&n3, types[tptr], res);
|
igen(nl, &n3, res);
|
||||||
agen(nl, &n3);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
tempname(&tmp, types[TINT32]);
|
p2 = igenindex(nr, &tmp);
|
||||||
p2 = cgenindex(nr, &tmp);
|
|
||||||
nr = &tmp;
|
nr = &tmp;
|
||||||
if(!isconst(nl, CTSTR))
|
if(!isconst(nl, CTSTR))
|
||||||
agenr(nl, &n3, res);
|
igen(nl, &n3, res);
|
||||||
regalloc(&n1, tmp.type, N);
|
regalloc(&n1, tmp.type, N);
|
||||||
gins(optoas(OAS, tmp.type), &tmp, &n1);
|
gins(optoas(OAS, tmp.type), &tmp, &n1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// &a is in &n3 (allocated in res)
|
// For fixed array we really want the pointer in n3.
|
||||||
// i is in &n1 (if not constant)
|
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
|
// w is width
|
||||||
|
|
||||||
// explicit check for nil if array is large enough
|
// explicit check for nil if array is large enough
|
||||||
// that we might derive too big a pointer.
|
// that we might derive too big a pointer.
|
||||||
if(isfixedarray(nl->type) && nl->type->width >= unmappedzero) {
|
if(isfixedarray(nl->type) && nl->type->width >= unmappedzero) {
|
||||||
regalloc(&n4, types[tptr], &n3);
|
n4 = n3;
|
||||||
gmove(&n3, &n4);
|
|
||||||
n4.op = OINDREG;
|
n4.op = OINDREG;
|
||||||
n4.type = types[TUINT8];
|
n4.type = types[TUINT8];
|
||||||
n4.xoffset = 0;
|
n4.xoffset = 0;
|
||||||
gins(ATESTB, nodintconst(0), &n4);
|
gins(ATESTB, nodintconst(0), &n4);
|
||||||
regfree(&n4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constant index
|
// constant index
|
||||||
if(isconst(nr, CTINT)) {
|
if(isconst(nr, CTINT)) {
|
||||||
if(isconst(nl, CTSTR))
|
if(isconst(nl, CTSTR))
|
||||||
fatal("constant string constant index");
|
fatal("constant string constant index"); // front end should handle
|
||||||
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;
|
nlen = n3;
|
||||||
n1.op = OINDREG;
|
nlen.type = types[TUINT32];
|
||||||
n1.type = types[tptr];
|
nlen.xoffset += Array_nel;
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
n1 = n3;
|
|
||||||
n1.op = OINDREG;
|
|
||||||
n1.type = types[tptr];
|
|
||||||
n1.xoffset = Array_array;
|
|
||||||
gmove(&n1, &n3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v*w != 0) {
|
// Load base pointer in n2 = n3.
|
||||||
nodconst(&n2, types[tptr], v*w);
|
regalloc(&n2, types[tptr], &n3);
|
||||||
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
n3.type = types[tptr];
|
||||||
}
|
n3.xoffset += Array_array;
|
||||||
gmove(&n3, res);
|
gmove(&n3, &n2);
|
||||||
regfree(&n3);
|
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;
|
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);
|
gmove(&n1, &n2);
|
||||||
regfree(&n1);
|
regfree(&n1);
|
||||||
|
|
||||||
if(!debug['B'] && !n->bounded) {
|
if(!debug['B'] && !n->bounded) {
|
||||||
// check bounds
|
// check bounds
|
||||||
if(isconst(nl, CTSTR))
|
t = types[TUINT32];
|
||||||
nodconst(&n1, types[TUINT32], nl->val.u.sval->len);
|
if(isconst(nl, CTSTR)) {
|
||||||
else if(isslice(nl->type) || nl->type->etype == TSTRING) {
|
nodconst(&nlen, t, nl->val.u.sval->len);
|
||||||
n1 = n3;
|
} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
|
||||||
n1.op = OINDREG;
|
nlen = n3;
|
||||||
n1.type = types[tptr];
|
nlen.type = t;
|
||||||
n1.xoffset = Array_nel;
|
nlen.xoffset += Array_nel;
|
||||||
} else
|
} else {
|
||||||
nodconst(&n1, types[TUINT32], nl->type->bound);
|
nodconst(&nlen, t, nl->type->bound);
|
||||||
gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
|
}
|
||||||
p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
|
gins(optoas(OCMP, t), &n2, &nlen);
|
||||||
|
p1 = gbranch(optoas(OLT, t), T, +1);
|
||||||
if(p2)
|
if(p2)
|
||||||
patch(p2, pc);
|
patch(p2, pc);
|
||||||
ginscall(panicindex, -1);
|
ginscall(panicindex, -1);
|
||||||
patch(p1, pc);
|
patch(p1, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isconst(nl, CTSTR)) {
|
if(isconst(nl, CTSTR)) {
|
||||||
regalloc(&n3, types[tptr], res);
|
regalloc(&n3, types[tptr], res);
|
||||||
p1 = gins(ALEAL, N, &n3);
|
p1 = gins(ALEAL, N, &n3);
|
||||||
@ -686,24 +701,27 @@ agen(Node *n, Node *res)
|
|||||||
goto indexdone;
|
goto indexdone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load base pointer in n3.
|
||||||
|
regalloc(&tmp, types[tptr], &n3);
|
||||||
if(isslice(nl->type) || nl->type->etype == TSTRING) {
|
if(isslice(nl->type) || nl->type->etype == TSTRING) {
|
||||||
n1 = n3;
|
n3.type = types[tptr];
|
||||||
n1.op = OINDREG;
|
n3.xoffset += Array_array;
|
||||||
n1.type = types[tptr];
|
gmove(&n3, &tmp);
|
||||||
n1.xoffset = Array_array;
|
|
||||||
gmove(&n1, &n3);
|
|
||||||
}
|
}
|
||||||
|
regfree(&n3);
|
||||||
|
n3 = tmp;
|
||||||
|
|
||||||
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) {
|
||||||
|
// LEAL (n3)(n2*w), n3
|
||||||
p1 = gins(ALEAL, &n2, &n3);
|
p1 = gins(ALEAL, &n2, &n3);
|
||||||
p1->from.scale = w;
|
p1->from.scale = w;
|
||||||
p1->from.index = p1->from.type;
|
p1->from.index = p1->from.type;
|
||||||
p1->from.type = p1->to.type + D_INDIR;
|
p1->from.type = p1->to.type + D_INDIR;
|
||||||
} else {
|
} else {
|
||||||
nodconst(&n1, types[TUINT32], w);
|
nodconst(&tmp, types[TUINT32], w);
|
||||||
gins(optoas(OMUL, types[TUINT32]), &n1, &n2);
|
gins(optoas(OMUL, types[TUINT32]), &tmp, &n2);
|
||||||
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
gins(optoas(OADD, types[tptr]), &n2, &n3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,23 +879,6 @@ igen(Node *n, Node *a, Node *res)
|
|||||||
a->type = n->type;
|
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
|
* branch gen
|
||||||
* if(n == true) goto to;
|
* if(n == true) goto to;
|
||||||
|
@ -95,7 +95,6 @@ void ginscall(Node*, int);
|
|||||||
* cgen.c
|
* cgen.c
|
||||||
*/
|
*/
|
||||||
void agen(Node*, Node*);
|
void agen(Node*, Node*);
|
||||||
void agenr(Node *n, Node *a, Node *res);
|
|
||||||
void igen(Node*, Node*, Node*);
|
void igen(Node*, Node*, Node*);
|
||||||
vlong fieldoffset(Type*, Node*);
|
vlong fieldoffset(Type*, Node*);
|
||||||
void sgen(Node*, Node*, int64);
|
void sgen(Node*, Node*, int64);
|
||||||
|
Loading…
Reference in New Issue
Block a user