From ae0862c1ec6850035bbb89aa6274392de1020039 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9my=20Oudompheng?= Date: Sun, 9 Sep 2012 20:30:08 +0200 Subject: [PATCH] cmd/8g: import componentgen from 6g. This makes the compilers code more similar and improves code generation a lot. The number of LEAL instructions generated for cmd/go drops by 60%. % GOARCH=386 go build -gcflags -S -a cmd/go | grep LEAL | wc -l Before: 89774 After: 47548 benchmark old ns/op new ns/op delta BenchmarkAppendFloatDecimal 540 444 -17.78% BenchmarkAppendFloat 1160 1035 -10.78% BenchmarkAppendFloatExp 1060 922 -13.02% BenchmarkAppendFloatNegExp 1053 920 -12.63% BenchmarkAppendFloatBig 1773 1558 -12.13% BenchmarkFormatInt 13065 12481 -4.47% BenchmarkAppendInt 10981 9900 -9.84% BenchmarkFormatUint 3804 3650 -4.05% BenchmarkAppendUint 3506 3303 -5.79% BenchmarkUnquoteEasy 714 683 -4.34% BenchmarkUnquoteHard 5117 2915 -43.03% Update #1914. R=nigeltao, rsc, golang-dev CC=golang-dev, remy https://golang.org/cl/6489067 --- src/cmd/8g/cgen.c | 166 +++++++++++++++++++++++++++++++++++++++++++++- src/cmd/8g/gg.h | 1 + src/cmd/8g/ggen.c | 4 ++ 3 files changed, 170 insertions(+), 1 deletion(-) diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c index 1ae49acaa0..3ef75712c0 100644 --- a/src/cmd/8g/cgen.c +++ b/src/cmd/8g/cgen.c @@ -777,7 +777,7 @@ igen(Node *n, Node *a, Node *res) break; *a = *n; return; - + case OCALLFUNC: fp = structfirst(&flist, getoutarg(n->left->type)); cgen_call(n, 0); @@ -1197,6 +1197,11 @@ sgen(Node *n, Node *res, int64 w) return; } + if (w == 8 || w == 12) { + if(componentgen(n, res)) + return; + } + // offset on the stack osrc = stkof(n); odst = stkof(res); @@ -1280,3 +1285,162 @@ sgen(Node *n, Node *res, int64 w) } } +static int +cadable(Node *n) +{ + if(!n->addable) { + // dont know how it happens, + // but it does + return 0; + } + + switch(n->op) { + case ONAME: + return 1; + } + return 0; +} + +/* + * copy a structure component by component + * return 1 if can do, 0 if cant. + * nr is N for copy zero + */ +int +componentgen(Node *nr, Node *nl) +{ + Node nodl, nodr; + int freel, freer; + + freel = 0; + freer = 0; + + switch(nl->type->etype) { + default: + goto no; + + case TARRAY: + if(!isslice(nl->type)) + goto no; + case TSTRING: + case TINTER: + break; + } + + nodl = *nl; + if(!cadable(nl)) { + if(nr == N || !cadable(nr)) + goto no; + igen(nl, &nodl, N); + freel = 1; + } + + if(nr != N) { + nodr = *nr; + if(!cadable(nr)) { + igen(nr, &nodr, N); + freer = 1; + } + } + + switch(nl->type->etype) { + case TARRAY: + if(!isslice(nl->type)) + goto no; + + nodl.xoffset += Array_array; + nodl.type = ptrto(nl->type->type); + + if(nr != N) { + nodr.xoffset += Array_array; + nodr.type = nodl.type; + } else + nodconst(&nodr, nodl.type, 0); + gmove(&nodr, &nodl); + + nodl.xoffset += Array_nel-Array_array; + nodl.type = types[TUINT32]; + + if(nr != N) { + nodr.xoffset += Array_nel-Array_array; + nodr.type = nodl.type; + } else + nodconst(&nodr, nodl.type, 0); + gmove(&nodr, &nodl); + + nodl.xoffset += Array_cap-Array_nel; + nodl.type = types[TUINT32]; + + if(nr != N) { + nodr.xoffset += Array_cap-Array_nel; + nodr.type = nodl.type; + } else + nodconst(&nodr, nodl.type, 0); + gmove(&nodr, &nodl); + + goto yes; + + case TSTRING: + nodl.xoffset += Array_array; + nodl.type = ptrto(types[TUINT8]); + + if(nr != N) { + nodr.xoffset += Array_array; + nodr.type = nodl.type; + } else + nodconst(&nodr, nodl.type, 0); + gmove(&nodr, &nodl); + + nodl.xoffset += Array_nel-Array_array; + nodl.type = types[TUINT32]; + + if(nr != N) { + nodr.xoffset += Array_nel-Array_array; + nodr.type = nodl.type; + } else + nodconst(&nodr, nodl.type, 0); + gmove(&nodr, &nodl); + + goto yes; + + case TINTER: + nodl.xoffset += Array_array; + nodl.type = ptrto(types[TUINT8]); + + if(nr != N) { + nodr.xoffset += Array_array; + nodr.type = nodl.type; + } else + nodconst(&nodr, nodl.type, 0); + gmove(&nodr, &nodl); + + nodl.xoffset += Array_nel-Array_array; + nodl.type = ptrto(types[TUINT8]); + + if(nr != N) { + nodr.xoffset += Array_nel-Array_array; + nodr.type = nodl.type; + } else + nodconst(&nodr, nodl.type, 0); + gmove(&nodr, &nodl); + + goto yes; + + case TSTRUCT: + goto no; + } + +no: + if(freer) + regfree(&nodr); + if(freel) + regfree(&nodl); + return 0; + +yes: + if(freer) + regfree(&nodr); + if(freel) + regfree(&nodl); + return 1; +} diff --git a/src/cmd/8g/gg.h b/src/cmd/8g/gg.h index 12632f651c..a30c95d715 100644 --- a/src/cmd/8g/gg.h +++ b/src/cmd/8g/gg.h @@ -107,6 +107,7 @@ void cgen_aret(Node*, Node*); Node* ncon(uint32); void mgen(Node*, Node*, Node*); void mfree(Node*); +int componentgen(Node*, Node*); /* * cgen64.c diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c index 749f913ef5..a31f660740 100644 --- a/src/cmd/8g/ggen.c +++ b/src/cmd/8g/ggen.c @@ -59,6 +59,10 @@ clearfat(Node *nl) dump("\nclearfat", nl); w = nl->type->width; + if(w == 8 || w == 12) + if(componentgen(N, nl)) + return; + c = w % 4; // bytes q = w / 4; // quads -- 2.48.1