Commit 28a23675 authored by Russ Cox's avatar Russ Cox

5g, 6g, 8g: shift, opt fixes

Fixes #1808.

R=ken2
CC=golang-dev
https://golang.org/cl/4813052
parent 8c23c1ab
......@@ -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,16 +505,43 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
return;
}
if(nl->ullman >= nr->ullman) {
regalloc(&n2, nl->type, res);
cgen(nl, &n2);
regalloc(&n1, nr->type, N);
cgen(nr, &n1);
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 {
regalloc(&n1, nr->type, N);
cgen(nr, &n1);
regalloc(&n2, nl->type, res);
cgen(nl, &n2);
if(nl->ullman >= nr->ullman) {
regalloc(&n2, nl->type, res);
cgen(nl, &n2);
regalloc(&n1, nr->type, N);
cgen(nr, &n1);
} else {
regalloc(&n1, nr->type, N);
cgen(nr, &n1);
regalloc(&n2, nl->type, res);
cgen(nl, &n2);
}
}
// test for shift being 0
......@@ -521,7 +549,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
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:
......
......@@ -9,7 +9,7 @@
#include "../8l/8.out.h"
#ifndef EXTERN
#define EXTERN extern
#define EXTERN extern
#endif
typedef struct Addr Addr;
......
......@@ -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);
}
nodreg(&n1, types[TUINT32], D_CX);
regalloc(&n1, nr->type, &n1); // to hold the shift type in CX
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
gins(optoas(OCMP, nr->type), &n1, ncon(w));
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
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;
......
// $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
*/
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