mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
5g, 6g, 8g: shift, opt fixes
Fixes #1808. R=ken2 CC=golang-dev https://golang.org/cl/4813052
This commit is contained in:
parent
8c23c1ab87
commit
28a23675cd
11 changed files with 132 additions and 41 deletions
|
|
@ -158,7 +158,7 @@ cgen64(Node *n, Node *res)
|
||||||
gins(AMOVW, &hi2, &ch);
|
gins(AMOVW, &hi2, &ch);
|
||||||
gins(AMOVW, &lo2, &cl);
|
gins(AMOVW, &lo2, &cl);
|
||||||
|
|
||||||
// bl * cl
|
// bl * cl -> ah al
|
||||||
p1 = gins(AMULLU, N, N);
|
p1 = gins(AMULLU, N, N);
|
||||||
p1->from.type = D_REG;
|
p1->from.type = D_REG;
|
||||||
p1->from.reg = bl.val.u.reg;
|
p1->from.reg = bl.val.u.reg;
|
||||||
|
|
@ -168,7 +168,7 @@ cgen64(Node *n, Node *res)
|
||||||
p1->to.offset = al.val.u.reg;
|
p1->to.offset = al.val.u.reg;
|
||||||
//print("%P\n", p1);
|
//print("%P\n", p1);
|
||||||
|
|
||||||
// bl * ch
|
// bl * ch + ah -> ah
|
||||||
p1 = gins(AMULA, N, N);
|
p1 = gins(AMULA, N, N);
|
||||||
p1->from.type = D_REG;
|
p1->from.type = D_REG;
|
||||||
p1->from.reg = bl.val.u.reg;
|
p1->from.reg = bl.val.u.reg;
|
||||||
|
|
@ -178,7 +178,7 @@ cgen64(Node *n, Node *res)
|
||||||
p1->to.offset = ah.val.u.reg;
|
p1->to.offset = ah.val.u.reg;
|
||||||
//print("%P\n", p1);
|
//print("%P\n", p1);
|
||||||
|
|
||||||
// bh * cl
|
// bh * cl + ah -> ah
|
||||||
p1 = gins(AMULA, N, N);
|
p1 = gins(AMULA, N, N);
|
||||||
p1->from.type = D_REG;
|
p1->from.type = D_REG;
|
||||||
p1->from.reg = bh.val.u.reg;
|
p1->from.reg = bh.val.u.reg;
|
||||||
|
|
|
||||||
|
|
@ -470,9 +470,10 @@ samereg(Node *a, Node *b)
|
||||||
void
|
void
|
||||||
cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
||||||
{
|
{
|
||||||
Node n1, n2, n3, t;
|
Node n1, n2, n3, nt, t, lo, hi;
|
||||||
int w;
|
int w;
|
||||||
Prog *p1, *p2, *p3;
|
Prog *p1, *p2, *p3, *pbig;
|
||||||
|
Type *tr;
|
||||||
uvlong sc;
|
uvlong sc;
|
||||||
|
|
||||||
if(nl->type->width > 4)
|
if(nl->type->width > 4)
|
||||||
|
|
@ -504,6 +505,32 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pbig = P;
|
||||||
|
tr = nr->type;
|
||||||
|
if(tr->width > 4) {
|
||||||
|
tempname(&nt, nr->type);
|
||||||
|
if(nl->ullman >= nr->ullman) {
|
||||||
|
regalloc(&n2, nl->type, res);
|
||||||
|
cgen(nl, &n2);
|
||||||
|
cgen(nr, &nt);
|
||||||
|
n1 = nt;
|
||||||
|
} else {
|
||||||
|
cgen(nr, &nt);
|
||||||
|
regalloc(&n2, nl->type, res);
|
||||||
|
cgen(nl, &n2);
|
||||||
|
}
|
||||||
|
split64(&nt, &lo, &hi);
|
||||||
|
regalloc(&n1, types[TUINT32], N);
|
||||||
|
regalloc(&n3, types[TUINT32], N);
|
||||||
|
gmove(&lo, &n1);
|
||||||
|
gmove(&hi, &n3);
|
||||||
|
gins(ATST, &n3, N);
|
||||||
|
nodconst(&t, types[TUINT32], w);
|
||||||
|
p1 = gins(AMOVW, &t, &n1);
|
||||||
|
p1->scond = C_SCOND_NE;
|
||||||
|
tr = types[TUINT32];
|
||||||
|
regfree(&n3);
|
||||||
|
} else {
|
||||||
if(nl->ullman >= nr->ullman) {
|
if(nl->ullman >= nr->ullman) {
|
||||||
regalloc(&n2, nl->type, res);
|
regalloc(&n2, nl->type, res);
|
||||||
cgen(nl, &n2);
|
cgen(nl, &n2);
|
||||||
|
|
@ -515,13 +542,14 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
||||||
regalloc(&n2, nl->type, res);
|
regalloc(&n2, nl->type, res);
|
||||||
cgen(nl, &n2);
|
cgen(nl, &n2);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// test for shift being 0
|
// test for shift being 0
|
||||||
p1 = gins(ATST, &n1, N);
|
p1 = gins(ATST, &n1, N);
|
||||||
p3 = gbranch(ABEQ, T);
|
p3 = gbranch(ABEQ, T);
|
||||||
|
|
||||||
// test and fix up large shifts
|
// test and fix up large shifts
|
||||||
regalloc(&n3, nr->type, N);
|
regalloc(&n3, tr, N);
|
||||||
nodconst(&t, types[TUINT32], w);
|
nodconst(&t, types[TUINT32], w);
|
||||||
gmove(&t, &n3);
|
gmove(&t, &n3);
|
||||||
gcmp(ACMP, &n1, &n3);
|
gcmp(ACMP, &n1, &n3);
|
||||||
|
|
|
||||||
|
|
@ -497,6 +497,7 @@ fp:
|
||||||
n->class = PPARAM;
|
n->class = PPARAM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
n->typecheck = 1;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1173,6 +1174,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
||||||
a->name = D_NONE;
|
a->name = D_NONE;
|
||||||
a->reg = NREG;
|
a->reg = NREG;
|
||||||
a->node = N;
|
a->node = N;
|
||||||
|
a->etype = 0;
|
||||||
if(n == N)
|
if(n == N)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -1308,6 +1310,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
||||||
case OLEN:
|
case OLEN:
|
||||||
// len of string or slice
|
// len of string or slice
|
||||||
naddr(n->left, a, canemitcode);
|
naddr(n->left, a, canemitcode);
|
||||||
|
a->etype = TINT32;
|
||||||
if(a->type == D_CONST && a->offset == 0)
|
if(a->type == D_CONST && a->offset == 0)
|
||||||
break; // len(nil)
|
break; // len(nil)
|
||||||
a->offset += Array_nel;
|
a->offset += Array_nel;
|
||||||
|
|
@ -1318,6 +1321,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
||||||
case OCAP:
|
case OCAP:
|
||||||
// cap of string or slice
|
// cap of string or slice
|
||||||
naddr(n->left, a, canemitcode);
|
naddr(n->left, a, canemitcode);
|
||||||
|
a->etype = TINT32;
|
||||||
if(a->type == D_CONST && a->offset == 0)
|
if(a->type == D_CONST && a->offset == 0)
|
||||||
break; // cap(nil)
|
break; // cap(nil)
|
||||||
a->offset += Array_cap;
|
a->offset += Array_cap;
|
||||||
|
|
@ -1327,6 +1331,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
||||||
|
|
||||||
case OADDR:
|
case OADDR:
|
||||||
naddr(n->left, a, canemitcode);
|
naddr(n->left, a, canemitcode);
|
||||||
|
a->etype = tptr;
|
||||||
switch(a->type) {
|
switch(a->type) {
|
||||||
case D_OREG:
|
case D_OREG:
|
||||||
a->type = D_CONST;
|
a->type = D_CONST;
|
||||||
|
|
@ -1819,6 +1824,7 @@ odot:
|
||||||
|
|
||||||
a->type = D_NONE;
|
a->type = D_NONE;
|
||||||
a->name = D_NONE;
|
a->name = D_NONE;
|
||||||
|
n1.type = n->type;
|
||||||
naddr(&n1, a, 1);
|
naddr(&n1, a, 1);
|
||||||
goto yes;
|
goto yes;
|
||||||
|
|
||||||
|
|
@ -1946,7 +1952,6 @@ oindex:
|
||||||
a->type = D_OREG;
|
a->type = D_OREG;
|
||||||
a->reg = reg->val.u.reg;
|
a->reg = reg->val.u.reg;
|
||||||
a->offset = 0;
|
a->offset = 0;
|
||||||
|
|
||||||
goto yes;
|
goto yes;
|
||||||
|
|
||||||
oindex_const:
|
oindex_const:
|
||||||
|
|
|
||||||
|
|
@ -933,7 +933,6 @@ xtramodes(Reg *r, Adr *a)
|
||||||
int
|
int
|
||||||
copyu(Prog *p, Adr *v, Adr *s)
|
copyu(Prog *p, Adr *v, Adr *s)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch(p->as) {
|
switch(p->as) {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -1011,6 +1010,8 @@ copyu(Prog *p, Adr *v, Adr *s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(copyas(&p->to, v)) {
|
if(copyas(&p->to, v)) {
|
||||||
|
if(p->scond != C_SCOND_NONE)
|
||||||
|
return 2;
|
||||||
if(copyau(&p->from, v))
|
if(copyau(&p->from, v))
|
||||||
return 4;
|
return 4;
|
||||||
return 3;
|
return 3;
|
||||||
|
|
@ -1069,6 +1070,8 @@ copyu(Prog *p, Adr *v, Adr *s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(copyas(&p->to, v)) {
|
if(copyas(&p->to, v)) {
|
||||||
|
if(p->scond != C_SCOND_NONE)
|
||||||
|
return 2;
|
||||||
if(p->reg == NREG)
|
if(p->reg == NREG)
|
||||||
p->reg = p->to.reg;
|
p->reg = p->to.reg;
|
||||||
if(copyau(&p->from, v))
|
if(copyau(&p->from, v))
|
||||||
|
|
|
||||||
|
|
@ -336,6 +336,7 @@ regopt(Prog *firstp)
|
||||||
case AMULD:
|
case AMULD:
|
||||||
case ADIVF:
|
case ADIVF:
|
||||||
case ADIVD:
|
case ADIVD:
|
||||||
|
case AMULA:
|
||||||
case AMULAL:
|
case AMULAL:
|
||||||
case AMULALU:
|
case AMULALU:
|
||||||
for(z=0; z<BITS; z++) {
|
for(z=0; z<BITS; z++) {
|
||||||
|
|
@ -770,6 +771,7 @@ addmove(Reg *r, int bn, int rn, int f)
|
||||||
break;
|
break;
|
||||||
case TBOOL:
|
case TBOOL:
|
||||||
case TUINT8:
|
case TUINT8:
|
||||||
|
//print("movbu %E %d %S\n", v->etype, bn, v->sym);
|
||||||
p1->as = AMOVBU;
|
p1->as = AMOVBU;
|
||||||
break;
|
break;
|
||||||
case TINT16:
|
case TINT16:
|
||||||
|
|
@ -843,9 +845,6 @@ mkvar(Reg *r, Adr *a)
|
||||||
n = D_NONE;
|
n = D_NONE;
|
||||||
|
|
||||||
flag = 0;
|
flag = 0;
|
||||||
if(a->pun)
|
|
||||||
flag = 1;
|
|
||||||
|
|
||||||
switch(t) {
|
switch(t) {
|
||||||
default:
|
default:
|
||||||
print("type %d %d %D\n", t, a->name, a);
|
print("type %d %d %D\n", t, a->name, a);
|
||||||
|
|
@ -928,7 +927,7 @@ mkvar(Reg *r, Adr *a)
|
||||||
if(!flag)
|
if(!flag)
|
||||||
return blsh(i);
|
return blsh(i);
|
||||||
|
|
||||||
// if they overlaps, disable both
|
// if they overlap, disable both
|
||||||
if(overlap(v->offset, v->width, o, w)) {
|
if(overlap(v->offset, v->width, o, w)) {
|
||||||
v->addr = 1;
|
v->addr = 1;
|
||||||
flag = 1;
|
flag = 1;
|
||||||
|
|
@ -952,6 +951,7 @@ mkvar(Reg *r, Adr *a)
|
||||||
|
|
||||||
i = nvar;
|
i = nvar;
|
||||||
nvar++;
|
nvar++;
|
||||||
|
//print("var %d %E %D %S\n", i, et, a, s);
|
||||||
v = var+i;
|
v = var+i;
|
||||||
v->sym = s;
|
v->sym = s;
|
||||||
v->offset = o;
|
v->offset = o;
|
||||||
|
|
@ -963,7 +963,7 @@ mkvar(Reg *r, Adr *a)
|
||||||
v->node = a->node;
|
v->node = a->node;
|
||||||
|
|
||||||
if(debug['R'])
|
if(debug['R'])
|
||||||
print("bit=%2d et=%E pun=%d %D\n", i, et, flag, a);
|
print("bit=%2d et=%2d w=%d+%d %S %D flag=%d\n", i, et, o, w, s, a, v->addr);
|
||||||
|
|
||||||
bit = blsh(i);
|
bit = blsh(i);
|
||||||
if(n == D_EXTERN || n == D_STATIC)
|
if(n == D_EXTERN || n == D_STATIC)
|
||||||
|
|
@ -1453,10 +1453,6 @@ paint3(Reg *r, int bn, int32 rb, int rn)
|
||||||
void
|
void
|
||||||
addreg(Adr *a, int rn)
|
addreg(Adr *a, int rn)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(a->type == D_CONST)
|
|
||||||
fatal("addreg: cant do this %D %d\n", a, rn);
|
|
||||||
|
|
||||||
a->sym = 0;
|
a->sym = 0;
|
||||||
a->name = D_NONE;
|
a->name = D_NONE;
|
||||||
a->type = D_REG;
|
a->type = D_REG;
|
||||||
|
|
@ -1477,8 +1473,7 @@ addreg(Adr *a, int rn)
|
||||||
int32
|
int32
|
||||||
RtoB(int r)
|
RtoB(int r)
|
||||||
{
|
{
|
||||||
|
if(r >= REGTMP-2) // excluded R9 and R10 for m and g
|
||||||
if(r < 2 || r >= REGTMP-2) // excluded R9 and R10 for m and g
|
|
||||||
return 0;
|
return 0;
|
||||||
return 1L << r;
|
return 1L << r;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -473,6 +473,7 @@ fatal("shouldnt be used");
|
||||||
n->xoffset += types[tptr]->width;
|
n->xoffset += types[tptr]->width;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
n->typecheck = 1;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -987,7 +988,6 @@ gins(int as, Node *f, Node *t)
|
||||||
if(debug['g'])
|
if(debug['g'])
|
||||||
print("%P\n", p);
|
print("%P\n", p);
|
||||||
|
|
||||||
|
|
||||||
w = 0;
|
w = 0;
|
||||||
switch(as) {
|
switch(as) {
|
||||||
case AMOVB:
|
case AMOVB:
|
||||||
|
|
|
||||||
|
|
@ -620,9 +620,9 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
|
||||||
void
|
void
|
||||||
cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
||||||
{
|
{
|
||||||
Node n1, n2, cx, oldcx;
|
Node n1, n2, nt, cx, oldcx, hi, lo;
|
||||||
int a, w;
|
int a, w;
|
||||||
Prog *p1;
|
Prog *p1, *p2;
|
||||||
uvlong sc;
|
uvlong sc;
|
||||||
|
|
||||||
if(nl->type->width > 4)
|
if(nl->type->width > 4)
|
||||||
|
|
@ -656,8 +656,13 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
||||||
gmove(&cx, &oldcx);
|
gmove(&cx, &oldcx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(nr->type->width > 4) {
|
||||||
|
tempname(&nt, nr->type);
|
||||||
|
n1 = nt;
|
||||||
|
} else {
|
||||||
nodreg(&n1, types[TUINT32], D_CX);
|
nodreg(&n1, types[TUINT32], D_CX);
|
||||||
regalloc(&n1, nr->type, &n1); // to hold the shift type in CX
|
regalloc(&n1, nr->type, &n1); // to hold the shift type in CX
|
||||||
|
}
|
||||||
|
|
||||||
if(samereg(&cx, res))
|
if(samereg(&cx, res))
|
||||||
regalloc(&n2, nl->type, N);
|
regalloc(&n2, nl->type, N);
|
||||||
|
|
@ -672,8 +677,21 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// test and fix up large shifts
|
// test and fix up large shifts
|
||||||
|
if(nr->type->width > 4) {
|
||||||
|
// delayed reg alloc
|
||||||
|
nodreg(&n1, types[TUINT32], D_CX);
|
||||||
|
regalloc(&n1, types[TUINT32], &n1); // to hold the shift type in CX
|
||||||
|
split64(&nt, &lo, &hi);
|
||||||
|
gmove(&lo, &n1);
|
||||||
|
gins(optoas(OCMP, types[TUINT32]), &hi, ncon(0));
|
||||||
|
p2 = gbranch(optoas(ONE, types[TUINT32]), T);
|
||||||
|
gins(optoas(OCMP, types[TUINT32]), &n1, ncon(w));
|
||||||
|
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
|
||||||
|
patch(p2, pc);
|
||||||
|
} else {
|
||||||
gins(optoas(OCMP, nr->type), &n1, ncon(w));
|
gins(optoas(OCMP, nr->type), &n1, ncon(w));
|
||||||
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
|
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
|
||||||
|
}
|
||||||
if(op == ORSH && issigned[nl->type->etype]) {
|
if(op == ORSH && issigned[nl->type->etype]) {
|
||||||
gins(a, ncon(w-1), &n2);
|
gins(a, ncon(w-1), &n2);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -865,7 +865,7 @@ mkvar(Reg *r, Adr *a)
|
||||||
if(v->width == w)
|
if(v->width == w)
|
||||||
return blsh(i);
|
return blsh(i);
|
||||||
|
|
||||||
// if they overlaps, disable both
|
// if they overlap, disable both
|
||||||
if(overlap(v->offset, v->width, o, w)) {
|
if(overlap(v->offset, v->width, o, w)) {
|
||||||
if(debug['R'])
|
if(debug['R'])
|
||||||
print("disable %s\n", v->sym->name);
|
print("disable %s\n", v->sym->name);
|
||||||
|
|
@ -874,8 +874,6 @@ mkvar(Reg *r, Adr *a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(a->pun)
|
|
||||||
flag = 1;
|
|
||||||
|
|
||||||
switch(et) {
|
switch(et) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
@ -902,7 +900,7 @@ mkvar(Reg *r, Adr *a)
|
||||||
v->node = a->node;
|
v->node = a->node;
|
||||||
|
|
||||||
if(debug['R'])
|
if(debug['R'])
|
||||||
print("bit=%2d et=%2d w=%d %S %D flag=%d\n", i, et, w, s, a, v->addr);
|
print("bit=%2d et=%2d w=%d+%d %S %D flag=%d\n", i, et, o, w, s, a, v->addr);
|
||||||
ostats.nvar++;
|
ostats.nvar++;
|
||||||
|
|
||||||
bit = blsh(i);
|
bit = blsh(i);
|
||||||
|
|
|
||||||
|
|
@ -150,8 +150,11 @@ Qconv(Fmt *fp)
|
||||||
fmtprint(fp, " ");
|
fmtprint(fp, " ");
|
||||||
if(var[i].sym == S)
|
if(var[i].sym == S)
|
||||||
fmtprint(fp, "$%lld", var[i].offset);
|
fmtprint(fp, "$%lld", var[i].offset);
|
||||||
else
|
else {
|
||||||
fmtprint(fp, var[i].sym->name);
|
fmtprint(fp, var[i].sym->name);
|
||||||
|
if(var[i].offset != 0)
|
||||||
|
fmtprint(fp, "%+d", var[i].offset);
|
||||||
|
}
|
||||||
bits.b[i/32] &= ~(1L << (i%32));
|
bits.b[i/32] &= ~(1L << (i%32));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
41
test/fixedbugs/bug356.go
Normal file
41
test/fixedbugs/bug356.go
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug344
|
||||||
|
|
||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// issue 1808
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var i uint64
|
||||||
|
var x int = 12345
|
||||||
|
|
||||||
|
if y := x << (i&5); y != 12345<<0 {
|
||||||
|
println("BUG bug344", y)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
if y := x << (i&5); y != 12345<<1 {
|
||||||
|
println("BUG bug344a", y)
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 70
|
||||||
|
if y := x << i; y != 0 {
|
||||||
|
println("BUG bug344b", y)
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 1<<32
|
||||||
|
if y := x << i; y != 0 {
|
||||||
|
println("BUG bug344c", y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
typecheck [1008592b0]
|
||||||
|
. INDREG a(1) l(15) x(24) tc(2) runtime.ret G0 string
|
||||||
|
bug343.go:15: internal compiler error: typecheck INDREG
|
||||||
|
*/
|
||||||
Loading…
Add table
Add a link
Reference in a new issue