1
0
mirror of https://github.com/golang/go synced 2024-11-21 23:14:40 -07:00

code optimization on slices

R=rsc
CC=golang-dev
https://golang.org/cl/1942043
This commit is contained in:
Ken Thompson 2010-08-13 19:39:36 -07:00
parent 0d40e40f5e
commit 5b0c317c9c
3 changed files with 134 additions and 26 deletions

View File

@ -1008,6 +1008,43 @@ sgen(Node *n, Node *ns, int32 w)
fatal("sgen UINF");
}
if(isslice(n->type))
if(isslice(ns->type))
if(n->addable)
if(ns->addable)
if(n->op != OINDREG)
if(ns->op != OINDREG)
if(n->op != OREGISTER)
if(ns->op != OREGISTER) {
// slices are done component by component
// to keep from confusing optimization
nodl = *ns;
nodl.xoffset += Array_array;
nodl.type = types[TUINT64];
nodr = *n;
nodr.xoffset += Array_array;
nodr.type = types[TUINT64];
gmove(&nodr, &nodl);
nodl = *ns;
nodl.xoffset += Array_nel;
nodl.type = types[TUINT32];
nodr = *n;
nodr.xoffset += Array_nel;
nodr.type = types[TUINT32];
gmove(&nodr, &nodl);
nodl = *ns;
nodl.xoffset += Array_cap;
nodl.type = types[TUINT32];
nodr = *n;
nodr.xoffset += Array_cap;
nodr.type = types[TUINT32];
gmove(&nodr, &nodl);
return;
}
if(w < 0)
fatal("sgen copy %d", w);

View File

@ -1041,6 +1041,34 @@ clearfat(Node *nl)
if(debug['g'])
dump("\nclearfat", nl);
if(isslice(nl->type))
if(nl->addable)
if(nl->op != OINDREG)
if(nl->op != OREGISTER) {
// slices are done component by component
// to keep from confusing optimization
n1 = *nl;
n1.xoffset += Array_array;
n1.type = types[TUINT64];
nodconst(&ax, types[TUINT64], 0);
gmove(&ax, &n1);
n1 = *nl;
n1.xoffset += Array_nel;
n1.type = types[TUINT32];
nodconst(&ax, types[TUINT32], 0);
gmove(&ax, &n1);
n1 = *nl;
n1.xoffset += Array_cap;
n1.type = types[TUINT32];
nodconst(&ax, types[TUINT32], 0);
gmove(&ax, &n1);
return;
}
w = nl->type->width;
c = w % 8; // bytes
q = w / 8; // quads

View File

@ -1683,12 +1683,28 @@ optoas(int op, Type *t)
enum
{
ODynam = 1<<0,
ODynam = 1<<0,
OAddable = 1<<1,
};
static Node clean[20];
static int cleani = 0;
int
xgen(Node *n, Node *a, int o)
{
regalloc(a, types[tptr], N);
if(o & ODynam)
if(n->addable)
if(n->op != OINDREG)
if(n->op != OREGISTER)
return 1;
agen(n, a);
return 0;
}
void
sudoclean(void)
{
@ -1820,7 +1836,7 @@ oindex:
if(l->type->etype != TARRAY)
fatal("not ary");
if(l->type->bound < 0)
o += ODynam;
o |= ODynam;
w = n->type->width;
if(isconst(r, CTINT))
@ -1844,8 +1860,8 @@ oindex:
// load the array (reg)
if(l->ullman > r->ullman) {
regalloc(reg, types[tptr], N);
agen(l, reg);
if(xgen(l, reg, o))
o |= OAddable;
}
// load the index (reg1)
@ -1860,17 +1876,17 @@ oindex:
// load the array (reg)
if(l->ullman <= r->ullman) {
regalloc(reg, types[tptr], N);
agen(l, reg);
if(xgen(l, reg, o))
o |= OAddable;
}
if(!(o & ODynam) && l->type->width >= unmappedzero && l->op == OIND) {
// cannot rely on page protections to
// catch array ptr == 0, so dereference.
n2 = *reg;
n2.xoffset = 0;
n2.op = OINDREG;
n2.type = types[TUINT8];
n2.xoffset = 0;
gins(ATESTB, nodintconst(0), &n2);
}
@ -1880,15 +1896,27 @@ oindex:
n4.op = OXXX;
t = types[TUINT32];
if(o & ODynam) {
n2 = *reg;
n2.op = OINDREG;
n2.type = types[TUINT32];
n2.xoffset = Array_nel;
if(is64(r->type)) {
t = types[TUINT64];
regalloc(&n4, t, N);
gmove(&n2, &n4);
n2 = n4;
if(o & OAddable) {
n2 = *l;
n2.xoffset += Array_nel;
n2.type = types[TUINT32];
if(is64(r->type)) {
t = types[TUINT64];
regalloc(&n4, t, N);
gmove(&n2, &n4);
n2 = n4;
}
} else {
n2 = *reg;
n2.xoffset = Array_nel;
n2.op = OINDREG;
n2.type = types[TUINT32];
if(is64(r->type)) {
t = types[TUINT64];
regalloc(&n4, t, N);
gmove(&n2, &n4);
n2 = n4;
}
}
} else {
if(is64(r->type))
@ -1904,18 +1932,33 @@ oindex:
}
if(o & ODynam) {
n2 = *reg;
n2.op = OINDREG;
n2.type = types[tptr];
n2.xoffset = Array_array;
gmove(&n2, reg);
if(o & OAddable) {
n2 = *l;
n2.xoffset += Array_array;
n2.type = types[TUINT64];
gmove(&n2, reg);
} else {
n2 = *reg;
n2.xoffset = Array_array;
n2.op = OINDREG;
n2.type = types[tptr];
gmove(&n2, reg);
}
}
naddr(reg1, a, 1);
a->offset = 0;
a->scale = w;
a->index = a->type;
a->type = reg->val.u.reg + D_INDIR;
if(o & OAddable) {
naddr(reg1, a, 1);
a->offset = 0;
a->scale = w;
a->index = a->type;
a->type = reg->val.u.reg + D_INDIR;
} else {
naddr(reg1, a, 1);
a->offset = 0;
a->scale = w;
a->index = a->type;
a->type = reg->val.u.reg + D_INDIR;
}
goto yes;