mirror of
https://github.com/golang/go
synced 2024-11-21 20:34:40 -07: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
@ -158,7 +158,7 @@ cgen64(Node *n, Node *res)
|
||||
gins(AMOVW, &hi2, &ch);
|
||||
gins(AMOVW, &lo2, &cl);
|
||||
|
||||
// bl * cl
|
||||
// bl * cl -> ah al
|
||||
p1 = gins(AMULLU, N, N);
|
||||
p1->from.type = D_REG;
|
||||
p1->from.reg = bl.val.u.reg;
|
||||
@ -168,7 +168,7 @@ cgen64(Node *n, Node *res)
|
||||
p1->to.offset = al.val.u.reg;
|
||||
//print("%P\n", p1);
|
||||
|
||||
// bl * ch
|
||||
// bl * ch + ah -> ah
|
||||
p1 = gins(AMULA, N, N);
|
||||
p1->from.type = D_REG;
|
||||
p1->from.reg = bl.val.u.reg;
|
||||
@ -178,7 +178,7 @@ cgen64(Node *n, Node *res)
|
||||
p1->to.offset = ah.val.u.reg;
|
||||
//print("%P\n", p1);
|
||||
|
||||
// bh * cl
|
||||
// bh * cl + ah -> ah
|
||||
p1 = gins(AMULA, N, N);
|
||||
p1->from.type = D_REG;
|
||||
p1->from.reg = bh.val.u.reg;
|
||||
|
@ -470,9 +470,10 @@ samereg(Node *a, Node *b)
|
||||
void
|
||||
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;
|
||||
Prog *p1, *p2, *p3;
|
||||
Prog *p1, *p2, *p3, *pbig;
|
||||
Type *tr;
|
||||
uvlong sc;
|
||||
|
||||
if(nl->type->width > 4)
|
||||
@ -504,6 +505,32 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
||||
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) {
|
||||
regalloc(&n2, nl->type, res);
|
||||
cgen(nl, &n2);
|
||||
@ -515,13 +542,14 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
||||
regalloc(&n2, nl->type, res);
|
||||
cgen(nl, &n2);
|
||||
}
|
||||
}
|
||||
|
||||
// test for shift being 0
|
||||
p1 = gins(ATST, &n1, N);
|
||||
p3 = gbranch(ABEQ, T);
|
||||
|
||||
// test and fix up large shifts
|
||||
regalloc(&n3, nr->type, N);
|
||||
regalloc(&n3, tr, N);
|
||||
nodconst(&t, types[TUINT32], w);
|
||||
gmove(&t, &n3);
|
||||
gcmp(ACMP, &n1, &n3);
|
||||
|
@ -497,6 +497,7 @@ fp:
|
||||
n->class = PPARAM;
|
||||
break;
|
||||
}
|
||||
n->typecheck = 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -1173,6 +1174,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
||||
a->name = D_NONE;
|
||||
a->reg = NREG;
|
||||
a->node = N;
|
||||
a->etype = 0;
|
||||
if(n == N)
|
||||
return;
|
||||
|
||||
@ -1308,6 +1310,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
||||
case OLEN:
|
||||
// len of string or slice
|
||||
naddr(n->left, a, canemitcode);
|
||||
a->etype = TINT32;
|
||||
if(a->type == D_CONST && a->offset == 0)
|
||||
break; // len(nil)
|
||||
a->offset += Array_nel;
|
||||
@ -1318,6 +1321,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
||||
case OCAP:
|
||||
// cap of string or slice
|
||||
naddr(n->left, a, canemitcode);
|
||||
a->etype = TINT32;
|
||||
if(a->type == D_CONST && a->offset == 0)
|
||||
break; // cap(nil)
|
||||
a->offset += Array_cap;
|
||||
@ -1327,6 +1331,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
||||
|
||||
case OADDR:
|
||||
naddr(n->left, a, canemitcode);
|
||||
a->etype = tptr;
|
||||
switch(a->type) {
|
||||
case D_OREG:
|
||||
a->type = D_CONST;
|
||||
@ -1819,6 +1824,7 @@ odot:
|
||||
|
||||
a->type = D_NONE;
|
||||
a->name = D_NONE;
|
||||
n1.type = n->type;
|
||||
naddr(&n1, a, 1);
|
||||
goto yes;
|
||||
|
||||
@ -1946,7 +1952,6 @@ oindex:
|
||||
a->type = D_OREG;
|
||||
a->reg = reg->val.u.reg;
|
||||
a->offset = 0;
|
||||
|
||||
goto yes;
|
||||
|
||||
oindex_const:
|
||||
|
@ -933,7 +933,6 @@ xtramodes(Reg *r, Adr *a)
|
||||
int
|
||||
copyu(Prog *p, Adr *v, Adr *s)
|
||||
{
|
||||
|
||||
switch(p->as) {
|
||||
|
||||
default:
|
||||
@ -1011,6 +1010,8 @@ copyu(Prog *p, Adr *v, Adr *s)
|
||||
return 0;
|
||||
}
|
||||
if(copyas(&p->to, v)) {
|
||||
if(p->scond != C_SCOND_NONE)
|
||||
return 2;
|
||||
if(copyau(&p->from, v))
|
||||
return 4;
|
||||
return 3;
|
||||
@ -1069,6 +1070,8 @@ copyu(Prog *p, Adr *v, Adr *s)
|
||||
return 0;
|
||||
}
|
||||
if(copyas(&p->to, v)) {
|
||||
if(p->scond != C_SCOND_NONE)
|
||||
return 2;
|
||||
if(p->reg == NREG)
|
||||
p->reg = p->to.reg;
|
||||
if(copyau(&p->from, v))
|
||||
|
@ -336,6 +336,7 @@ regopt(Prog *firstp)
|
||||
case AMULD:
|
||||
case ADIVF:
|
||||
case ADIVD:
|
||||
case AMULA:
|
||||
case AMULAL:
|
||||
case AMULALU:
|
||||
for(z=0; z<BITS; z++) {
|
||||
@ -770,6 +771,7 @@ addmove(Reg *r, int bn, int rn, int f)
|
||||
break;
|
||||
case TBOOL:
|
||||
case TUINT8:
|
||||
//print("movbu %E %d %S\n", v->etype, bn, v->sym);
|
||||
p1->as = AMOVBU;
|
||||
break;
|
||||
case TINT16:
|
||||
@ -843,9 +845,6 @@ mkvar(Reg *r, Adr *a)
|
||||
n = D_NONE;
|
||||
|
||||
flag = 0;
|
||||
if(a->pun)
|
||||
flag = 1;
|
||||
|
||||
switch(t) {
|
||||
default:
|
||||
print("type %d %d %D\n", t, a->name, a);
|
||||
@ -928,7 +927,7 @@ mkvar(Reg *r, Adr *a)
|
||||
if(!flag)
|
||||
return blsh(i);
|
||||
|
||||
// if they overlaps, disable both
|
||||
// if they overlap, disable both
|
||||
if(overlap(v->offset, v->width, o, w)) {
|
||||
v->addr = 1;
|
||||
flag = 1;
|
||||
@ -952,6 +951,7 @@ mkvar(Reg *r, Adr *a)
|
||||
|
||||
i = nvar;
|
||||
nvar++;
|
||||
//print("var %d %E %D %S\n", i, et, a, s);
|
||||
v = var+i;
|
||||
v->sym = s;
|
||||
v->offset = o;
|
||||
@ -963,7 +963,7 @@ mkvar(Reg *r, Adr *a)
|
||||
v->node = a->node;
|
||||
|
||||
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);
|
||||
if(n == D_EXTERN || n == D_STATIC)
|
||||
@ -1453,10 +1453,6 @@ paint3(Reg *r, int bn, int32 rb, int rn)
|
||||
void
|
||||
addreg(Adr *a, int rn)
|
||||
{
|
||||
|
||||
if(a->type == D_CONST)
|
||||
fatal("addreg: cant do this %D %d\n", a, rn);
|
||||
|
||||
a->sym = 0;
|
||||
a->name = D_NONE;
|
||||
a->type = D_REG;
|
||||
@ -1477,8 +1473,7 @@ addreg(Adr *a, int rn)
|
||||
int32
|
||||
RtoB(int r)
|
||||
{
|
||||
|
||||
if(r < 2 || r >= REGTMP-2) // excluded R9 and R10 for m and g
|
||||
if(r >= REGTMP-2) // excluded R9 and R10 for m and g
|
||||
return 0;
|
||||
return 1L << r;
|
||||
}
|
||||
|
@ -473,6 +473,7 @@ fatal("shouldnt be used");
|
||||
n->xoffset += types[tptr]->width;
|
||||
break;
|
||||
}
|
||||
n->typecheck = 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -987,7 +988,6 @@ gins(int as, Node *f, Node *t)
|
||||
if(debug['g'])
|
||||
print("%P\n", p);
|
||||
|
||||
|
||||
w = 0;
|
||||
switch(as) {
|
||||
case AMOVB:
|
||||
|
@ -620,9 +620,9 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
|
||||
void
|
||||
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;
|
||||
Prog *p1;
|
||||
Prog *p1, *p2;
|
||||
uvlong sc;
|
||||
|
||||
if(nl->type->width > 4)
|
||||
@ -656,8 +656,13 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
|
||||
gmove(&cx, &oldcx);
|
||||
}
|
||||
|
||||
if(nr->type->width > 4) {
|
||||
tempname(&nt, nr->type);
|
||||
n1 = nt;
|
||||
} else {
|
||||
nodreg(&n1, types[TUINT32], D_CX);
|
||||
regalloc(&n1, nr->type, &n1); // to hold the shift type in CX
|
||||
}
|
||||
|
||||
if(samereg(&cx, res))
|
||||
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
|
||||
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));
|
||||
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
|
||||
}
|
||||
if(op == ORSH && issigned[nl->type->etype]) {
|
||||
gins(a, ncon(w-1), &n2);
|
||||
} else {
|
||||
|
@ -865,7 +865,7 @@ mkvar(Reg *r, Adr *a)
|
||||
if(v->width == w)
|
||||
return blsh(i);
|
||||
|
||||
// if they overlaps, disable both
|
||||
// if they overlap, disable both
|
||||
if(overlap(v->offset, v->width, o, w)) {
|
||||
if(debug['R'])
|
||||
print("disable %s\n", v->sym->name);
|
||||
@ -874,8 +874,6 @@ mkvar(Reg *r, Adr *a)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(a->pun)
|
||||
flag = 1;
|
||||
|
||||
switch(et) {
|
||||
case 0:
|
||||
@ -902,7 +900,7 @@ mkvar(Reg *r, Adr *a)
|
||||
v->node = a->node;
|
||||
|
||||
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++;
|
||||
|
||||
bit = blsh(i);
|
||||
|
@ -150,8 +150,11 @@ Qconv(Fmt *fp)
|
||||
fmtprint(fp, " ");
|
||||
if(var[i].sym == S)
|
||||
fmtprint(fp, "$%lld", var[i].offset);
|
||||
else
|
||||
else {
|
||||
fmtprint(fp, var[i].sym->name);
|
||||
if(var[i].offset != 0)
|
||||
fmtprint(fp, "%+d", var[i].offset);
|
||||
}
|
||||
bits.b[i/32] &= ~(1L << (i%32));
|
||||
}
|
||||
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…
Reference in New Issue
Block a user