1
0
mirror of https://github.com/golang/go synced 2024-11-25 10:07:56 -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"); 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) if(w < 0)
fatal("sgen copy %d", w); fatal("sgen copy %d", w);

View File

@ -1041,6 +1041,34 @@ clearfat(Node *nl)
if(debug['g']) if(debug['g'])
dump("\nclearfat", nl); 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; w = nl->type->width;
c = w % 8; // bytes c = w % 8; // bytes
q = w / 8; // quads q = w / 8; // quads

View File

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