From 2de064b63c6d0eb5cba5bd877da81c8100aaeb2a Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9my=20Oudompheng?= Date: Tue, 2 Oct 2012 08:19:27 +0200 Subject: [PATCH] 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 --- src/cmd/8g/cgen.c | 153 +++++++++++++++++++++++----------------------- src/cmd/8g/gg.h | 1 - 2 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c index 3fd0cd753e..708bc53189 100644 --- a/src/cmd/8g/cgen.c +++ b/src/cmd/8g/cgen.c @@ -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)) { - cgen(n, res); + 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,109 +581,117 @@ 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); } + // 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(&n2, types[tptr], v*w); - gins(optoas(OADD, types[tptr]), &n2, &n3); + nodconst(&n1, types[tptr], v*w); + gins(optoas(OADD, types[tptr]), &n1, &n2); } - gmove(&n3, res); - regfree(&n3); + 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); patch(p1, pc); } - + if(isconst(nl, CTSTR)) { regalloc(&n3, types[tptr], res); p1 = gins(ALEAL, N, &n3); @@ -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; diff --git a/src/cmd/8g/gg.h b/src/cmd/8g/gg.h index e905303a5d..09718855bd 100644 --- a/src/cmd/8g/gg.h +++ b/src/cmd/8g/gg.h @@ -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); -- 2.48.1