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
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index 1ae49ac..3ef7571 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -777,7 +777,7 @@
break;
*a = *n;
return;
-
+
case OCALLFUNC:
fp = structfirst(&flist, getoutarg(n->left->type));
cgen_call(n, 0);
@@ -1197,6 +1197,11 @@
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 @@
}
}
+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 12632f6..a30c95d 100644
--- a/src/cmd/8g/gg.h
+++ b/src/cmd/8g/gg.h
@@ -107,6 +107,7 @@
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 749f913..a31f660 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -59,6 +59,10 @@
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