From f4e76d5e0222c40e9b98ba19e6628e49f14ecc12 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9my=20Oudompheng?= Date: Mon, 24 Sep 2012 23:07:44 +0200 Subject: [PATCH] cmd/6g, cmd/8g: add OINDREG, ODOT, ODOTPTR cases to igen. Apart from reducing the number of LEAL/LEAQ instructions by about 30%, it gives 8g easier registerization in several cases, for example in strconv. Performance with 6g is not affected. Before (386): src/pkg/strconv/decimal.go:22 TEXT (*decimal).String+0(SB),$240-12 src/pkg/strconv/extfloat.go:540 TEXT (*extFloat).ShortestDecimal+0(SB),$584-20 After (386): src/pkg/strconv/decimal.go:22 TEXT (*decimal).String+0(SB),$196-12 src/pkg/strconv/extfloat.go:540 TEXT (*extFloat).ShortestDecimal+0(SB),$420-20 Benchmarks with GOARCH=386 (on a Core 2). benchmark old ns/op new ns/op delta BenchmarkBinaryTree17 7110191000 7079644000 -0.43% BenchmarkFannkuch11 7769274000 7766514000 -0.04% BenchmarkGobDecode 33454820 34755400 +3.89% BenchmarkGobEncode 11675710 11007050 -5.73% BenchmarkGzip 2013519000 1593855000 -20.84% BenchmarkGunzip 253368200 242667600 -4.22% BenchmarkJSONEncode 152443900 120763400 -20.78% BenchmarkJSONDecode 304112800 247461800 -18.63% BenchmarkMandelbrot200 29245520 29240490 -0.02% BenchmarkParse 8484105 8088660 -4.66% BenchmarkRevcomp 2695688000 2841263000 +5.40% BenchmarkTemplate 363759800 277271200 -23.78% benchmark old ns/op new ns/op delta BenchmarkAtof64Decimal 127 129 +1.57% BenchmarkAtof64Float 166 164 -1.20% BenchmarkAtof64FloatExp 308 300 -2.60% BenchmarkAtof64Big 584 571 -2.23% BenchmarkAppendFloatDecimal 440 430 -2.27% BenchmarkAppendFloat 995 776 -22.01% BenchmarkAppendFloatExp 897 746 -16.83% BenchmarkAppendFloatNegExp 900 752 -16.44% BenchmarkAppendFloatBig 1528 1228 -19.63% BenchmarkAppendFloat32Integer 443 453 +2.26% BenchmarkAppendFloat32ExactFraction 812 661 -18.60% BenchmarkAppendFloat32Point 1002 773 -22.85% BenchmarkAppendFloat32Exp 858 725 -15.50% BenchmarkAppendFloat32NegExp 848 728 -14.15% BenchmarkAppendFloat64Fixed1 447 431 -3.58% BenchmarkAppendFloat64Fixed2 480 462 -3.75% BenchmarkAppendFloat64Fixed3 461 457 -0.87% BenchmarkAppendFloat64Fixed4 509 484 -4.91% Update #1914. R=rsc, nigeltao CC=golang-dev, remy https://golang.org/cl/6494107 --- src/cmd/6g/cgen.c | 35 ++++++++++++++++++++++++++++++++++- src/cmd/8g/cgen.c | 40 ++++++++++++++++++++++++++++++++++++---- src/cmd/8g/gsubr.c | 6 +++--- src/cmd/gc/go.h | 6 +++--- 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index ce3a3eba9a..27ab1052c3 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -798,7 +798,7 @@ igen(Node *n, Node *a, Node *res) Type *fp; Iter flist; Node n1, n2; - + switch(n->op) { case ONAME: if((n->class&PHEAP) || n->class == PPARAMREF) @@ -806,6 +806,39 @@ igen(Node *n, Node *a, Node *res) *a = *n; return; + case OINDREG: + // Increase the refcount of the register so that igen's caller + // has to call regfree. + if(n->val.u.reg != D_SP) + reg[n->val.u.reg]++; + *a = *n; + return; + + case ODOT: + igen(n->left, a, res); + a->xoffset += n->xoffset; + a->type = n->type; + return; + + case ODOTPTR: + regalloc(a, types[tptr], res); + cgen(n->left, a); + if(n->xoffset != 0) { + // explicit check for nil if struct is large enough + // that we might derive too big a pointer. + if(n->left->type->type->width >= unmappedzero) { + n1 = *a; + n1.op = OINDREG; + n1.type = types[TUINT8]; + n1.xoffset = 0; + gins(ATESTB, nodintconst(0), &n1); + } + } + a->op = OINDREG; + a->xoffset += n->xoffset; + a->type = n->type; + return; + case OCALLFUNC: fp = structfirst(&flist, getoutarg(n->left->type)); cgen_call(n, 0); diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c index ed188fed62..6684bf94d5 100644 --- a/src/cmd/8g/cgen.c +++ b/src/cmd/8g/cgen.c @@ -342,9 +342,8 @@ cgen(Node *n, Node *res) } if(isslice(nl->type)) { igen(nl, &n1, res); - n1.op = OINDREG; n1.type = types[TUINT32]; - n1.xoffset = Array_cap; + n1.xoffset += Array_cap; gmove(&n1, res); regfree(&n1); break; @@ -781,10 +780,10 @@ agen(Node *n, Node *res) void igen(Node *n, Node *a, Node *res) { - Node n1; Type *fp; Iter flist; - + Node n1; + switch(n->op) { case ONAME: if((n->class&PHEAP) || n->class == PPARAMREF) @@ -792,6 +791,39 @@ igen(Node *n, Node *a, Node *res) *a = *n; return; + case OINDREG: + // Increase the refcount of the register so that igen's caller + // has to call regfree. + if(n->val.u.reg != D_SP) + reg[n->val.u.reg]++; + *a = *n; + return; + + case ODOT: + igen(n->left, a, res); + a->xoffset += n->xoffset; + a->type = n->type; + return; + + case ODOTPTR: + regalloc(a, types[tptr], res); + cgen(n->left, a); + if(n->xoffset != 0) { + // explicit check for nil if struct is large enough + // that we might derive too big a pointer. + if(n->left->type->type->width >= unmappedzero) { + n1 = *a; + n1.op = OINDREG; + n1.type = types[TUINT8]; + n1.xoffset = 0; + gins(ATESTB, nodintconst(0), &n1); + } + } + a->op = OINDREG; + a->xoffset += n->xoffset; + a->type = n->type; + return; + case OCALLFUNC: fp = structfirst(&flist, getoutarg(n->left->type)); cgen_call(n, 0); diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c index dcbd6dbcfa..a94086e7c1 100644 --- a/src/cmd/8g/gsubr.c +++ b/src/cmd/8g/gsubr.c @@ -766,7 +766,7 @@ ginit(void) for(i=0; i