mirror of
https://github.com/golang/go
synced 2024-11-25 01:17:56 -07:00
fix bug206.
delay calls to savex as long as possible. R=ken OCL=34535 CL=34546
This commit is contained in:
parent
93b1dcbfcb
commit
2204cfddea
@ -898,7 +898,7 @@ stkof(Node *n)
|
|||||||
void
|
void
|
||||||
sgen(Node *n, Node *ns, int32 w)
|
sgen(Node *n, Node *ns, int32 w)
|
||||||
{
|
{
|
||||||
Node nodl, nodr;
|
Node nodl, nodr, oldl, oldr, cx, oldcx;
|
||||||
int32 c, q, odst, osrc;
|
int32 c, q, odst, osrc;
|
||||||
|
|
||||||
if(debug['g']) {
|
if(debug['g']) {
|
||||||
@ -919,20 +919,30 @@ sgen(Node *n, Node *ns, int32 w)
|
|||||||
osrc = stkof(n);
|
osrc = stkof(n);
|
||||||
odst = stkof(ns);
|
odst = stkof(ns);
|
||||||
|
|
||||||
nodreg(&nodl, types[tptr], D_DI);
|
|
||||||
nodreg(&nodr, types[tptr], D_SI);
|
|
||||||
|
|
||||||
if(n->ullman >= ns->ullman) {
|
if(n->ullman >= ns->ullman) {
|
||||||
|
savex(D_SI, &nodr, &oldr, N, types[tptr]);
|
||||||
agen(n, &nodr);
|
agen(n, &nodr);
|
||||||
|
|
||||||
|
regalloc(&nodr, types[tptr], &nodr); // mark nodr as live
|
||||||
|
savex(D_DI, &nodl, &oldl, N, types[tptr]);
|
||||||
agen(ns, &nodl);
|
agen(ns, &nodl);
|
||||||
|
regfree(&nodr);
|
||||||
} else {
|
} else {
|
||||||
|
savex(D_DI, &nodl, &oldl, N, types[tptr]);
|
||||||
agen(ns, &nodl);
|
agen(ns, &nodl);
|
||||||
|
|
||||||
|
regalloc(&nodl, types[tptr], &nodl); // mark nodl as live
|
||||||
|
savex(D_SI, &nodr, &oldr, N, types[tptr]);
|
||||||
agen(n, &nodr);
|
agen(n, &nodr);
|
||||||
|
regfree(&nodl);
|
||||||
}
|
}
|
||||||
|
|
||||||
c = w % 8; // bytes
|
c = w % 8; // bytes
|
||||||
q = w / 8; // quads
|
q = w / 8; // quads
|
||||||
|
|
||||||
|
savex(D_CX, &cx, &oldcx, N, types[TINT64]);
|
||||||
|
|
||||||
// if we are copying forward on the stack and
|
// if we are copying forward on the stack and
|
||||||
// the src and dst overlap, then reverse direction
|
// the src and dst overlap, then reverse direction
|
||||||
if(osrc < odst && odst < osrc+w) {
|
if(osrc < odst && odst < osrc+w) {
|
||||||
@ -982,4 +992,9 @@ sgen(Node *n, Node *ns, int32 w)
|
|||||||
c--;
|
c--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
restx(&nodl, &oldl);
|
||||||
|
restx(&nodr, &oldr);
|
||||||
|
restx(&cx, &oldcx);
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,8 @@ int samaddr(Node*, Node*);
|
|||||||
void naddr(Node*, Addr*);
|
void naddr(Node*, Addr*);
|
||||||
void cgen_aret(Node*, Node*);
|
void cgen_aret(Node*, Node*);
|
||||||
int cgen_inline(Node*, Node*);
|
int cgen_inline(Node*, Node*);
|
||||||
|
void restx(Node*, Node*);
|
||||||
|
void savex(int, Node*, Node*, Node*, Type*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gsubr.c
|
* gsubr.c
|
||||||
|
@ -461,6 +461,8 @@ ret:
|
|||||||
int
|
int
|
||||||
samereg(Node *a, Node *b)
|
samereg(Node *a, Node *b)
|
||||||
{
|
{
|
||||||
|
if(a == N || b == N)
|
||||||
|
return 0;
|
||||||
if(a->op != OREGISTER)
|
if(a->op != OREGISTER)
|
||||||
return 0;
|
return 0;
|
||||||
if(b->op != OREGISTER)
|
if(b->op != OREGISTER)
|
||||||
@ -481,11 +483,12 @@ samereg(Node *a, Node *b)
|
|||||||
* according to op.
|
* according to op.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
|
dodiv(int op, Node *nl, Node *nr, Node *res)
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
Node n3, n4;
|
Node n3, n4;
|
||||||
Type *t;
|
Type *t;
|
||||||
|
Node ax, dx, oldax, olddx;
|
||||||
|
|
||||||
t = nl->type;
|
t = nl->type;
|
||||||
if(t->width == 1) {
|
if(t->width == 1) {
|
||||||
@ -495,62 +498,73 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
|
|||||||
t = types[TUINT32];
|
t = types[TUINT32];
|
||||||
}
|
}
|
||||||
a = optoas(op, t);
|
a = optoas(op, t);
|
||||||
ax->type = t;
|
|
||||||
dx->type = t;
|
|
||||||
|
|
||||||
regalloc(&n3, t, N);
|
regalloc(&n3, t, N);
|
||||||
if(nl->ullman >= nr->ullman) {
|
if(nl->ullman >= nr->ullman) {
|
||||||
cgen(nl, ax);
|
savex(D_AX, &ax, &oldax, res, t);
|
||||||
if(!issigned[t->etype]) {
|
cgen(nl, &ax);
|
||||||
nodconst(&n4, t, 0);
|
regalloc(&ax, t, &ax); // mark ax live during cgen
|
||||||
gmove(&n4, dx);
|
|
||||||
} else
|
|
||||||
gins(optoas(OEXTEND, t), N, N);
|
|
||||||
cgen(nr, &n3);
|
cgen(nr, &n3);
|
||||||
|
regfree(&ax);
|
||||||
} else {
|
} else {
|
||||||
cgen(nr, &n3);
|
cgen(nr, &n3);
|
||||||
cgen(nl, ax);
|
savex(D_AX, &ax, &oldax, res, t);
|
||||||
if(!issigned[t->etype]) {
|
cgen(nl, &ax);
|
||||||
nodconst(&n4, t, 0);
|
|
||||||
gmove(&n4, dx);
|
|
||||||
} else
|
|
||||||
gins(optoas(OEXTEND, t), N, N);
|
|
||||||
}
|
}
|
||||||
|
savex(D_DX, &dx, &olddx, res, t);
|
||||||
|
if(!issigned[t->etype]) {
|
||||||
|
nodconst(&n4, t, 0);
|
||||||
|
gmove(&n4, &dx);
|
||||||
|
} else
|
||||||
|
gins(optoas(OEXTEND, t), N, N);
|
||||||
gins(a, &n3, N);
|
gins(a, &n3, N);
|
||||||
regfree(&n3);
|
regfree(&n3);
|
||||||
|
|
||||||
if(op == ODIV)
|
if(op == ODIV)
|
||||||
gmove(ax, res);
|
gmove(&ax, res);
|
||||||
else
|
else
|
||||||
gmove(dx, res);
|
gmove(&dx, res);
|
||||||
|
restx(&ax, &oldax);
|
||||||
|
restx(&dx, &olddx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/*
|
||||||
|
* register dr is one of the special ones (AX, CX, DI, SI, etc.).
|
||||||
|
* we need to use it. if it is already allocated as a temporary
|
||||||
|
* (r > 1; can only happen if a routine like sgen passed a
|
||||||
|
* special as cgen's res and then cgen used regalloc to reuse
|
||||||
|
* it as its own temporary), then move it for now to another
|
||||||
|
* register. caller must call restx to move it back.
|
||||||
|
* the move is not necessary if dr == res, because res is
|
||||||
|
* known to be dead.
|
||||||
|
*/
|
||||||
|
void
|
||||||
savex(int dr, Node *x, Node *oldx, Node *res, Type *t)
|
savex(int dr, Node *x, Node *oldx, Node *res, Type *t)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = reg[dr];
|
r = reg[dr];
|
||||||
nodreg(x, types[TINT64], dr);
|
|
||||||
|
|
||||||
// save current ax and dx if they are live
|
// save current ax and dx if they are live
|
||||||
// and not the destination
|
// and not the destination
|
||||||
memset(oldx, 0, sizeof *oldx);
|
memset(oldx, 0, sizeof *oldx);
|
||||||
if(r > 0 && !samereg(x, res)) {
|
nodreg(x, t, dr);
|
||||||
|
if(r > 1 && !samereg(x, res)) {
|
||||||
regalloc(oldx, types[TINT64], N);
|
regalloc(oldx, types[TINT64], N);
|
||||||
|
x->type = types[TINT64];
|
||||||
gmove(x, oldx);
|
gmove(x, oldx);
|
||||||
|
x->type = t;
|
||||||
|
oldx->ostk = r; // squirrel away old r value
|
||||||
|
reg[dr] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
regalloc(x, t, x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
restx(Node *x, Node *oldx)
|
restx(Node *x, Node *oldx)
|
||||||
{
|
{
|
||||||
regfree(x);
|
|
||||||
|
|
||||||
if(oldx->op != 0) {
|
if(oldx->op != 0) {
|
||||||
x->type = types[TINT64];
|
x->type = types[TINT64];
|
||||||
|
reg[x->val.u.reg] = oldx->ostk;
|
||||||
gmove(oldx, x);
|
gmove(oldx, x);
|
||||||
regfree(oldx);
|
regfree(oldx);
|
||||||
}
|
}
|
||||||
@ -564,8 +578,8 @@ restx(Node *x, Node *oldx)
|
|||||||
void
|
void
|
||||||
cgen_div(int op, Node *nl, Node *nr, Node *res)
|
cgen_div(int op, Node *nl, Node *nr, Node *res)
|
||||||
{
|
{
|
||||||
Node ax, dx, oldax, olddx;
|
|
||||||
Node n1, n2, n3, savl, savr;
|
Node n1, n2, n3, savl, savr;
|
||||||
|
Node ax, dx, oldax, olddx;
|
||||||
int n, w, s, a;
|
int n, w, s, a;
|
||||||
Magic m;
|
Magic m;
|
||||||
|
|
||||||
@ -701,12 +715,12 @@ divbymul:
|
|||||||
if(op == OMOD)
|
if(op == OMOD)
|
||||||
goto longmod;
|
goto longmod;
|
||||||
|
|
||||||
savex(D_AX, &ax, &oldax, res, nl->type);
|
|
||||||
savex(D_DX, &dx, &olddx, res, nl->type);
|
|
||||||
|
|
||||||
regalloc(&n1, nl->type, N);
|
regalloc(&n1, nl->type, N);
|
||||||
cgen(nl, &n1); // num -> reg(n1)
|
cgen(nl, &n1); // num -> reg(n1)
|
||||||
|
|
||||||
|
savex(D_AX, &ax, &oldax, res, nl->type);
|
||||||
|
savex(D_DX, &dx, &olddx, res, nl->type);
|
||||||
|
|
||||||
nodconst(&n2, nl->type, m.um);
|
nodconst(&n2, nl->type, m.um);
|
||||||
gmove(&n2, &ax); // const->ax
|
gmove(&n2, &ax); // const->ax
|
||||||
|
|
||||||
@ -751,12 +765,12 @@ divbymul:
|
|||||||
if(op == OMOD)
|
if(op == OMOD)
|
||||||
goto longmod;
|
goto longmod;
|
||||||
|
|
||||||
savex(D_AX, &ax, &oldax, res, nl->type);
|
|
||||||
savex(D_DX, &dx, &olddx, res, nl->type);
|
|
||||||
|
|
||||||
regalloc(&n1, nl->type, N);
|
regalloc(&n1, nl->type, N);
|
||||||
cgen(nl, &n1); // num -> reg(n1)
|
cgen(nl, &n1); // num -> reg(n1)
|
||||||
|
|
||||||
|
savex(D_AX, &ax, &oldax, res, nl->type);
|
||||||
|
savex(D_DX, &dx, &olddx, res, nl->type);
|
||||||
|
|
||||||
nodconst(&n2, nl->type, m.sm);
|
nodconst(&n2, nl->type, m.sm);
|
||||||
gmove(&n2, &ax); // const->ax
|
gmove(&n2, &ax); // const->ax
|
||||||
|
|
||||||
@ -798,11 +812,7 @@ divbymul:
|
|||||||
|
|
||||||
longdiv:
|
longdiv:
|
||||||
// division and mod using (slow) hardware instruction
|
// division and mod using (slow) hardware instruction
|
||||||
savex(D_AX, &ax, &oldax, res, nl->type);
|
dodiv(op, nl, nr, res);
|
||||||
savex(D_DX, &dx, &olddx, res, nl->type);
|
|
||||||
dodiv(op, nl, nr, res, &ax, &dx);
|
|
||||||
restx(&ax, &oldax);
|
|
||||||
restx(&dx, &olddx);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
longmod:
|
longmod:
|
||||||
@ -979,7 +989,7 @@ void
|
|||||||
clearfat(Node *nl)
|
clearfat(Node *nl)
|
||||||
{
|
{
|
||||||
uint32 w, c, q;
|
uint32 w, c, q;
|
||||||
Node n1;
|
Node n1, oldn1, ax, oldax;
|
||||||
|
|
||||||
/* clear a fat object */
|
/* clear a fat object */
|
||||||
if(debug['g'])
|
if(debug['g'])
|
||||||
@ -989,10 +999,12 @@ clearfat(Node *nl)
|
|||||||
c = w % 8; // bytes
|
c = w % 8; // bytes
|
||||||
q = w / 8; // quads
|
q = w / 8; // quads
|
||||||
|
|
||||||
gconreg(AMOVQ, 0, D_AX);
|
savex(D_DI, &n1, &oldn1, N, types[tptr]);
|
||||||
nodreg(&n1, types[tptr], D_DI);
|
|
||||||
agen(nl, &n1);
|
agen(nl, &n1);
|
||||||
|
|
||||||
|
savex(D_AX, &ax, &oldax, N, types[tptr]);
|
||||||
|
gconreg(AMOVQ, 0, D_AX);
|
||||||
|
|
||||||
if(q >= 4) {
|
if(q >= 4) {
|
||||||
gconreg(AMOVQ, q, D_CX);
|
gconreg(AMOVQ, q, D_CX);
|
||||||
gins(AREP, N, N); // repeat
|
gins(AREP, N, N); // repeat
|
||||||
@ -1012,6 +1024,9 @@ clearfat(Node *nl)
|
|||||||
gins(ASTOSB, N, N); // STOB AL,*(DI)+
|
gins(ASTOSB, N, N); // STOB AL,*(DI)+
|
||||||
c--;
|
c--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restx(&n1, &oldn1);
|
||||||
|
restx(&ax, &oldax);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -192,8 +192,8 @@ afunclit(Addr *a)
|
|||||||
|
|
||||||
static int resvd[] =
|
static int resvd[] =
|
||||||
{
|
{
|
||||||
// D_DI, // for movstring
|
D_DI, // for movstring
|
||||||
// D_SI, // for movstring
|
D_SI, // for movstring
|
||||||
|
|
||||||
D_AX, // for divide
|
D_AX, // for divide
|
||||||
D_CX, // for shift
|
D_CX, // for shift
|
||||||
|
@ -174,6 +174,3 @@ bugs/bug198.go:8: T is not a type
|
|||||||
bugs/bug198.go:8: too many arguments to return
|
bugs/bug198.go:8: too many arguments to return
|
||||||
bugs/bug198.go:10: too many arguments to CALL
|
bugs/bug198.go:10: too many arguments to CALL
|
||||||
BUG: errchk: compiler crashed
|
BUG: errchk: compiler crashed
|
||||||
|
|
||||||
=========== bugs/bug206.go
|
|
||||||
BUG: bug206
|
|
||||||
|
Loading…
Reference in New Issue
Block a user