Commit 6feb6132 authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/6g, cmd/8g: fix two "out of fixed registers" cases.

In two cases, registers were allocated too early resulting
in exhausting of available registers when nesting these
operations.

The case of method calls was due to missing cases in igen,
which only makes calls but doesn't allocate a register for
the result.

The case of 8-bit multiplication was due to a wrong order
in register allocation when Ullman numbers were bigger on the
RHS.

Fixes #3907.
Fixes #4156.

R=rsc
CC=golang-dev, remy
https://golang.org/cl/6560054
parent 7936ab58
...@@ -246,10 +246,11 @@ cgen(Node *n, Node *res) ...@@ -246,10 +246,11 @@ cgen(Node *n, Node *res)
case OADD: case OADD:
case OMUL: case OMUL:
a = optoas(n->op, nl->type); a = optoas(n->op, nl->type);
if(a != AIMULB) if(a == AIMULB) {
goto sbop;
cgen_bmul(n->op, nl, nr, res); cgen_bmul(n->op, nl, nr, res);
break; break;
}
goto sbop;
// asymmetric binary // asymmetric binary
case OSUB: case OSUB:
...@@ -840,8 +841,20 @@ igen(Node *n, Node *a, Node *res) ...@@ -840,8 +841,20 @@ igen(Node *n, Node *a, Node *res)
return; return;
case OCALLFUNC: case OCALLFUNC:
fp = structfirst(&flist, getoutarg(n->left->type)); case OCALLMETH:
case OCALLINTER:
switch(n->op) {
case OCALLFUNC:
cgen_call(n, 0); cgen_call(n, 0);
break;
case OCALLMETH:
cgen_callmeth(n, 0);
break;
case OCALLINTER:
cgen_callinter(n, N, 0);
break;
}
fp = structfirst(&flist, getoutarg(n->left->type));
memset(a, 0, sizeof *a); memset(a, 0, sizeof *a);
a->op = OINDREG; a->op = OINDREG;
a->val.u.reg = D_SP; a->val.u.reg = D_SP;
......
...@@ -978,48 +978,37 @@ ret: ...@@ -978,48 +978,37 @@ ret:
/* /*
* generate byte multiply: * generate byte multiply:
* res = nl * nr * res = nl * nr
* no 2-operand byte multiply instruction so have to do * there is no 2-operand byte multiply instruction so
* 16-bit multiply and take bottom half. * we do a full-width multiplication and truncate afterwards.
*/ */
void void
cgen_bmul(int op, Node *nl, Node *nr, Node *res) cgen_bmul(int op, Node *nl, Node *nr, Node *res)
{ {
Node n1b, n2b, n1w, n2w; Node n1, n2, *tmp;
Type *t; Type *t;
int a; int a;
if(nl->ullman >= nr->ullman) { // copy from byte to full registers
regalloc(&n1b, nl->type, res); t = types[TUINT64];
cgen(nl, &n1b);
regalloc(&n2b, nr->type, N);
cgen(nr, &n2b);
} else {
regalloc(&n2b, nr->type, N);
cgen(nr, &n2b);
regalloc(&n1b, nl->type, res);
cgen(nl, &n1b);
}
// copy from byte to short registers
t = types[TUINT16];
if(issigned[nl->type->etype]) if(issigned[nl->type->etype])
t = types[TINT16]; t = types[TINT64];
regalloc(&n2w, t, &n2b);
cgen(&n2b, &n2w);
regalloc(&n1w, t, &n1b); // largest ullman on left.
cgen(&n1b, &n1w); if(nl->ullman < nr->ullman) {
tmp = nl;
nl = nr;
nr = tmp;
}
regalloc(&n1, t, res);
cgen(nl, &n1);
regalloc(&n2, t, N);
cgen(nr, &n2);
a = optoas(op, t); a = optoas(op, t);
gins(a, &n2w, &n1w); gins(a, &n2, &n1);
cgen(&n1w, &n1b); regfree(&n2);
cgen(&n1b, res); gmove(&n1, res);
regfree(&n1);
regfree(&n1w);
regfree(&n2w);
regfree(&n1b);
regfree(&n2b);
} }
void void
......
...@@ -825,8 +825,20 @@ igen(Node *n, Node *a, Node *res) ...@@ -825,8 +825,20 @@ igen(Node *n, Node *a, Node *res)
return; return;
case OCALLFUNC: case OCALLFUNC:
fp = structfirst(&flist, getoutarg(n->left->type)); case OCALLMETH:
case OCALLINTER:
switch(n->op) {
case OCALLFUNC:
cgen_call(n, 0); cgen_call(n, 0);
break;
case OCALLMETH:
cgen_callmeth(n, 0);
break;
case OCALLINTER:
cgen_callinter(n, N, 0);
break;
}
fp = structfirst(&flist, getoutarg(n->left->type));
memset(a, 0, sizeof *a); memset(a, 0, sizeof *a);
a->op = OINDREG; a->op = OINDREG;
a->val.u.reg = D_SP; a->val.u.reg = D_SP;
......
...@@ -743,46 +743,36 @@ cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res) ...@@ -743,46 +743,36 @@ cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
/* /*
* generate byte multiply: * generate byte multiply:
* res = nl * nr * res = nl * nr
* no byte multiply instruction so have to do * there is no 2-operand byte multiply instruction so
* 16-bit multiply and take bottom half. * we do a full-width multiplication and truncate afterwards.
*/ */
void void
cgen_bmul(int op, Node *nl, Node *nr, Node *res) cgen_bmul(int op, Node *nl, Node *nr, Node *res)
{ {
Node n1b, n2b, n1w, n2w; Node n1, n2, *tmp;
Type *t; Type *t;
int a; int a;
if(nl->ullman >= nr->ullman) { // copy from byte to full registers
regalloc(&n1b, nl->type, res); t = types[TUINT32];
cgen(nl, &n1b);
regalloc(&n2b, nr->type, N);
cgen(nr, &n2b);
} else {
regalloc(&n2b, nr->type, N);
cgen(nr, &n2b);
regalloc(&n1b, nl->type, res);
cgen(nl, &n1b);
}
// copy from byte to short registers
t = types[TUINT16];
if(issigned[nl->type->etype]) if(issigned[nl->type->etype])
t = types[TINT16]; t = types[TINT32];
regalloc(&n2w, t, &n2b);
cgen(&n2b, &n2w);
regalloc(&n1w, t, &n1b); // largest ullman on left.
cgen(&n1b, &n1w); if(nl->ullman < nr->ullman) {
tmp = nl;
nl = nr;
nr = tmp;
}
regalloc(&n1, t, res);
cgen(nl, &n1);
regalloc(&n2, t, N);
cgen(nr, &n2);
a = optoas(op, t); a = optoas(op, t);
gins(a, &n2w, &n1w); gins(a, &n2, &n1);
cgen(&n1w, &n1b); regfree(&n2);
cgen(&n1b, res); gmove(&n1, res);
regfree(&n1);
regfree(&n1w);
regfree(&n2w);
regfree(&n1b);
regfree(&n2b);
} }
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