Commit ee3e2ac1 authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/5g: introduce componentgen for better registerization.

It is essentially identical to the version in 6g.

R=dave, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/6710043
parent 1158c6b9
...@@ -307,17 +307,11 @@ cgen(Node *n, Node *res) ...@@ -307,17 +307,11 @@ cgen(Node *n, Node *res)
break; break;
case OITAB: case OITAB:
// itable of interface value // interface table is first word of interface value
igen(nl, &n1, res); igen(nl, &n1, res);
n1.op = OREGISTER; // was OINDREG
regalloc(&n2, n->type, &n1);
n1.op = OINDREG;
n1.type = n->type; n1.type = n->type;
n1.xoffset += 0; gmove(&n1, res);
gmove(&n1, &n2);
gmove(&n2, res);
regfree(&n1); regfree(&n1);
regfree(&n2);
break; break;
case OLEN: case OLEN:
...@@ -345,15 +339,10 @@ cgen(Node *n, Node *res) ...@@ -345,15 +339,10 @@ cgen(Node *n, Node *res)
if(istype(nl->type, TSTRING) || isslice(nl->type)) { if(istype(nl->type, TSTRING) || isslice(nl->type)) {
// both slice and string have len one pointer into the struct. // both slice and string have len one pointer into the struct.
igen(nl, &n1, res); igen(nl, &n1, res);
n1.op = OREGISTER; // was OINDREG
regalloc(&n2, types[TUINT32], &n1);
n1.op = OINDREG;
n1.type = types[TUINT32]; n1.type = types[TUINT32];
n1.xoffset += Array_nel; n1.xoffset += Array_nel;
gmove(&n1, &n2); gmove(&n1, res);
gmove(&n2, res);
regfree(&n1); regfree(&n1);
regfree(&n2);
break; break;
} }
fatal("cgen: OLEN: unknown type %lT", nl->type); fatal("cgen: OLEN: unknown type %lT", nl->type);
...@@ -383,11 +372,9 @@ cgen(Node *n, Node *res) ...@@ -383,11 +372,9 @@ cgen(Node *n, Node *res)
break; break;
} }
if(isslice(nl->type)) { if(isslice(nl->type)) {
regalloc(&n1, types[tptr], res); igen(nl, &n1, res);
agen(nl, &n1);
n1.op = OINDREG;
n1.type = types[TUINT32]; n1.type = types[TUINT32];
n1.xoffset = Array_cap; n1.xoffset += Array_cap;
gmove(&n1, res); gmove(&n1, res);
regfree(&n1); regfree(&n1);
break; break;
...@@ -898,6 +885,20 @@ igen(Node *n, Node *a, Node *res) ...@@ -898,6 +885,20 @@ igen(Node *n, Node *a, Node *res)
dump("\nigen-n", n); dump("\nigen-n", n);
} }
switch(n->op) { switch(n->op) {
case ONAME:
if((n->class&PHEAP) || n->class == PPARAMREF)
break;
*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 != REGSP)
reg[n->val.u.reg]++;
*a = *n;
return;
case ODOT: case ODOT:
igen(n->left, a, res); igen(n->left, a, res);
a->xoffset += n->xoffset; a->xoffset += n->xoffset;
...@@ -1150,34 +1151,12 @@ bgen(Node *n, int true, int likely, Prog *to) ...@@ -1150,34 +1151,12 @@ bgen(Node *n, int true, int likely, Prog *to)
break; break;
} }
regalloc(&n1, types[tptr], N); igen(nl, &n1, N);
agen(nl, &n1); n1.xoffset += Array_array;
n2 = n1; n1.type = types[tptr];
n2.op = OINDREG; gencmp0(&n1, types[tptr], a, likely, to);
n2.xoffset = Array_array;
gencmp0(&n2, types[tptr], a, likely, to);
regfree(&n1);
break;
#ifdef NOTDEF
a = optoas(a, types[tptr]);
regalloc(&n1, types[tptr], N);
regalloc(&n3, types[tptr], N);
regalloc(&n4, types[tptr], N);
agen(nl, &n1);
n2 = n1;
n2.op = OINDREG;
n2.xoffset = Array_array;
gmove(&n2, &n4);
nodconst(&tmp, types[tptr], 0);
gmove(&tmp, &n3);
gcmp(optoas(OCMP, types[tptr]), &n4, &n3);
patch(gbranch(a, types[tptr], likely), to);
regfree(&n4);
regfree(&n3);
regfree(&n1); regfree(&n1);
break; break;
#endif
} }
if(isinter(nl->type)) { if(isinter(nl->type)) {
...@@ -1187,34 +1166,12 @@ bgen(Node *n, int true, int likely, Prog *to) ...@@ -1187,34 +1166,12 @@ bgen(Node *n, int true, int likely, Prog *to)
break; break;
} }
regalloc(&n1, types[tptr], N); igen(nl, &n1, N);
agen(nl, &n1); n1.type = types[tptr];
n2 = n1; n1.xoffset += 0;
n2.op = OINDREG; gencmp0(&n1, types[tptr], a, likely, to);
n2.xoffset = 0;
gencmp0(&n2, types[tptr], a, likely, to);
regfree(&n1);
break;
#ifdef NOTDEF
a = optoas(a, types[tptr]);
regalloc(&n1, types[tptr], N);
regalloc(&n3, types[tptr], N);
regalloc(&n4, types[tptr], N);
agen(nl, &n1);
n2 = n1;
n2.op = OINDREG;
n2.xoffset = 0;
gmove(&n2, &n4);
nodconst(&tmp, types[tptr], 0);
gmove(&tmp, &n3);
gcmp(optoas(OCMP, types[tptr]), &n4, &n3);
patch(gbranch(a, types[tptr], likely), to);
regfree(&n1); regfree(&n1);
regfree(&n3);
regfree(&n4);
break; break;
#endif
} }
if(iscomplex[nl->type->etype]) { if(iscomplex[nl->type->etype]) {
...@@ -1399,6 +1356,10 @@ sgen(Node *n, Node *res, int64 w) ...@@ -1399,6 +1356,10 @@ sgen(Node *n, Node *res, int64 w)
return; return;
} }
if(w == 8 || w == 12)
if(componentgen(n, res))
return;
// determine alignment. // determine alignment.
// want to avoid unaligned access, so have to use // want to avoid unaligned access, so have to use
// smaller operations for less aligned types. // smaller operations for less aligned types.
...@@ -1516,3 +1477,156 @@ sgen(Node *n, Node *res, int64 w) ...@@ -1516,3 +1477,156 @@ sgen(Node *n, Node *res, int64 w)
regfree(&src); regfree(&src);
regfree(&tmp); regfree(&tmp);
} }
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, tmp;
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;
}
} else {
// When zeroing, prepare a register containing zero.
nodconst(&tmp, nl->type, 0);
regalloc(&nodr, types[TUINT], N);
gmove(&tmp, &nodr);
freer = 1;
}
switch(nl->type->etype) {
case TARRAY:
nodl.xoffset += Array_array;
nodl.type = ptrto(nl->type->type);
if(nr != N) {
nodr.xoffset += Array_array;
nodr.type = nodl.type;
}
gmove(&nodr, &nodl);
nodl.xoffset += Array_nel-Array_array;
nodl.type = types[simtype[TUINT]];
if(nr != N) {
nodr.xoffset += Array_nel-Array_array;
nodr.type = nodl.type;
}
gmove(&nodr, &nodl);
nodl.xoffset += Array_cap-Array_nel;
nodl.type = types[simtype[TUINT]];
if(nr != N) {
nodr.xoffset += Array_cap-Array_nel;
nodr.type = nodl.type;
}
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;
}
gmove(&nodr, &nodl);
nodl.xoffset += Array_nel-Array_array;
nodl.type = types[simtype[TUINT]];
if(nr != N) {
nodr.xoffset += Array_nel-Array_array;
nodr.type = nodl.type;
}
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;
}
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;
}
gmove(&nodr, &nodl);
goto yes;
}
no:
if(freer)
regfree(&nodr);
if(freel)
regfree(&nodl);
return 0;
yes:
if(freer)
regfree(&nodr);
if(freel)
regfree(&nodl);
return 1;
}
...@@ -103,6 +103,7 @@ Prog * gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs); ...@@ -103,6 +103,7 @@ Prog * gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs);
void naddr(Node*, Addr*, int); void naddr(Node*, Addr*, int);
void cgen_aret(Node*, Node*); void cgen_aret(Node*, Node*);
void cgen_shift(int, int, Node*, Node*, Node*); void cgen_shift(int, int, Node*, Node*, Node*);
int componentgen(Node*, Node*);
/* /*
* cgen64.c * cgen64.c
......
...@@ -616,7 +616,12 @@ clearfat(Node *nl) ...@@ -616,7 +616,12 @@ clearfat(Node *nl)
if(debug['g']) if(debug['g'])
dump("\nclearfat", nl); dump("\nclearfat", nl);
w = nl->type->width; w = nl->type->width;
if(w == 8 || w == 12)
if(componentgen(N, nl))
return;
c = w % 4; // bytes c = w % 4; // bytes
q = w / 4; // quads q = w / 4; // quads
......
...@@ -255,8 +255,9 @@ afunclit(Addr *a) ...@@ -255,8 +255,9 @@ afunclit(Addr *a)
static int resvd[] = static int resvd[] =
{ {
9, // reserved for m 9, // reserved for m
10, // reserved for g 10, // reserved for g
REGSP, // reserved for SP
}; };
void void
...@@ -400,15 +401,17 @@ regfree(Node *n) ...@@ -400,15 +401,17 @@ regfree(Node *n)
print("regalloc fix %d float %d\n", fixfree, floatfree); print("regalloc fix %d float %d\n", fixfree, floatfree);
} }
if(n->op == ONAME && iscomplex[n->type->etype]) if(n->op == ONAME)
return; return;
if(n->op != OREGISTER && n->op != OINDREG) if(n->op != OREGISTER && n->op != OINDREG)
fatal("regfree: not a register"); fatal("regfree: not a register");
i = n->val.u.reg; i = n->val.u.reg;
if(i == REGSP)
return;
if(i < 0 || i >= nelem(reg) || i >= nelem(regpc)) if(i < 0 || i >= nelem(reg) || i >= nelem(regpc))
fatal("regfree: reg out of range"); fatal("regfree: reg out of range");
if(reg[i] <= 0) if(reg[i] <= 0)
fatal("regfree: reg not allocated"); fatal("regfree: reg %R not allocated", i);
reg[i]--; reg[i]--;
if(reg[i] == 0) if(reg[i] == 0)
regpc[i] = 0; regpc[i] = 0;
......
...@@ -95,7 +95,7 @@ setoutvar(void) ...@@ -95,7 +95,7 @@ setoutvar(void)
ovar.b[z] |= bit.b[z]; ovar.b[z] |= bit.b[z];
t = structnext(&save); t = structnext(&save);
} }
//if(bany(ovar)) //if(bany(&ovar))
//print("ovar = %Q\n", ovar); //print("ovar = %Q\n", ovar);
} }
...@@ -987,8 +987,6 @@ mkvar(Reg *r, Adr *a) ...@@ -987,8 +987,6 @@ mkvar(Reg *r, Adr *a)
switch(et) { switch(et) {
case 0: case 0:
case TFUNC: case TFUNC:
case TARRAY:
case TSTRING:
goto none; goto none;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment