mirror of https://github.com/golang/go.git
cmd/gc: recognize u<<1 op u>>31 as a rotate when op is ^, not just |.
R=rsc CC=golang-dev https://golang.org/cl/6249071
This commit is contained in:
parent
5612fd770d
commit
947a3ddf87
|
|
@ -468,7 +468,6 @@ walkexpr(Node **np, NodeList **init)
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OAND:
|
case OAND:
|
||||||
case OXOR:
|
|
||||||
case OSUB:
|
case OSUB:
|
||||||
case OMUL:
|
case OMUL:
|
||||||
case OLT:
|
case OLT:
|
||||||
|
|
@ -483,6 +482,7 @@ walkexpr(Node **np, NodeList **init)
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OOR:
|
case OOR:
|
||||||
|
case OXOR:
|
||||||
walkexpr(&n->left, init);
|
walkexpr(&n->left, init);
|
||||||
walkexpr(&n->right, init);
|
walkexpr(&n->right, init);
|
||||||
walkrotate(&n);
|
walkrotate(&n);
|
||||||
|
|
@ -2708,10 +2708,10 @@ walkrotate(Node **np)
|
||||||
|
|
||||||
n = *np;
|
n = *np;
|
||||||
|
|
||||||
// Want << | >> or >> | << on unsigned value.
|
// Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value.
|
||||||
l = n->left;
|
l = n->left;
|
||||||
r = n->right;
|
r = n->right;
|
||||||
if(n->op != OOR ||
|
if((n->op != OOR && n->op != OXOR) ||
|
||||||
(l->op != OLSH && l->op != ORSH) ||
|
(l->op != OLSH && l->op != ORSH) ||
|
||||||
(r->op != OLSH && r->op != ORSH) ||
|
(r->op != OLSH && r->op != ORSH) ||
|
||||||
n->type == T || issigned[n->type->etype] ||
|
n->type == T || issigned[n->type->etype] ||
|
||||||
|
|
|
||||||
101
test/rotate.go
101
test/rotate.go
|
|
@ -9,7 +9,7 @@
|
||||||
// Generate test of shift and rotate by constants.
|
// Generate test of shift and rotate by constants.
|
||||||
// The output is compiled and run.
|
// The output is compiled and run.
|
||||||
//
|
//
|
||||||
// The output takes around a minute to compile, link, and run
|
// The output takes around a minute or two to compile, link, and run
|
||||||
// but it is only done during ./run, not in normal builds using run.go.
|
// but it is only done during ./run, not in normal builds using run.go.
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
@ -86,6 +86,26 @@ func main() {
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var (
|
||||||
|
uop = [2]func(x, y uint64) uint64{
|
||||||
|
func(x, y uint64) uint64 {
|
||||||
|
return x | y
|
||||||
|
},
|
||||||
|
func(x, y uint64) uint64 {
|
||||||
|
return x ^ y
|
||||||
|
},
|
||||||
|
}
|
||||||
|
iop = [2]func(x, y int64) int64{
|
||||||
|
func(x, y int64) int64 {
|
||||||
|
return x | y
|
||||||
|
},
|
||||||
|
func(x, y int64) int64 {
|
||||||
|
return x ^ y
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cop = [2]byte{'|', '^'}
|
||||||
|
)
|
||||||
|
|
||||||
func gentest(b *bufio.Writer, bits uint, unsigned, inverted bool) {
|
func gentest(b *bufio.Writer, bits uint, unsigned, inverted bool) {
|
||||||
fmt.Fprintf(b, "func init() {\n")
|
fmt.Fprintf(b, "func init() {\n")
|
||||||
defer fmt.Fprintf(b, "}\n")
|
defer fmt.Fprintf(b, "}\n")
|
||||||
|
|
@ -94,48 +114,49 @@ func gentest(b *bufio.Writer, bits uint, unsigned, inverted bool) {
|
||||||
// Generate tests for left/right and right/left.
|
// Generate tests for left/right and right/left.
|
||||||
for l := uint(0); l <= bits; l++ {
|
for l := uint(0); l <= bits; l++ {
|
||||||
for r := uint(0); r <= bits; r++ {
|
for r := uint(0); r <= bits; r++ {
|
||||||
typ := fmt.Sprintf("int%d", bits)
|
for o, op := range cop {
|
||||||
v := fmt.Sprintf("i%d", bits)
|
typ := fmt.Sprintf("int%d", bits)
|
||||||
if unsigned {
|
v := fmt.Sprintf("i%d", bits)
|
||||||
typ = "u" + typ
|
if unsigned {
|
||||||
v = "u" + v
|
typ = "u" + typ
|
||||||
}
|
v = "u" + v
|
||||||
v0 := int64(0x123456789abcdef0)
|
}
|
||||||
if inverted {
|
v0 := int64(0x123456789abcdef0)
|
||||||
v = "n" + v
|
if inverted {
|
||||||
v0 = ^v0
|
v = "n" + v
|
||||||
}
|
v0 = ^v0
|
||||||
expr1 := fmt.Sprintf("%s<<%d | %s>>%d", v, l, v, r)
|
}
|
||||||
expr2 := fmt.Sprintf("%s>>%d | %s<<%d", v, r, v, l)
|
expr1 := fmt.Sprintf("%s<<%d %c %s>>%d", v, l, op, v, r)
|
||||||
|
expr2 := fmt.Sprintf("%s>>%d %c %s<<%d", v, r, op, v, l)
|
||||||
var result string
|
|
||||||
if unsigned {
|
|
||||||
v := uint64(v0) >> (64 - bits)
|
|
||||||
v = v<<l | v>>r
|
|
||||||
v <<= 64 - bits
|
|
||||||
v >>= 64 - bits
|
|
||||||
result = fmt.Sprintf("%#x", v)
|
|
||||||
} else {
|
|
||||||
v := int64(v0) >> (64 - bits)
|
|
||||||
v = v<<l | v>>r
|
|
||||||
v <<= 64 - bits
|
|
||||||
v >>= 64 - bits
|
|
||||||
result = fmt.Sprintf("%#x", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(b, "\tcheck(%q, %s, %s(%s))\n", expr1, expr1, typ, result)
|
var result string
|
||||||
fmt.Fprintf(b, "\tcheck(%q, %s, %s(%s))\n", expr2, expr2, typ, result)
|
if unsigned {
|
||||||
|
v := uint64(v0) >> (64 - bits)
|
||||||
|
v = uop[o](v<<l, v>>r)
|
||||||
|
v <<= 64 - bits
|
||||||
|
v >>= 64 - bits
|
||||||
|
result = fmt.Sprintf("%#x", v)
|
||||||
|
} else {
|
||||||
|
v := int64(v0) >> (64 - bits)
|
||||||
|
v = iop[o](v<<l, v>>r)
|
||||||
|
v <<= 64 - bits
|
||||||
|
v >>= 64 - bits
|
||||||
|
result = fmt.Sprintf("%#x", v)
|
||||||
|
}
|
||||||
|
|
||||||
// Chop test into multiple functions so that there's not one
|
fmt.Fprintf(b, "\tcheck(%q, %s, %s(%s))\n", expr1, expr1, typ, result)
|
||||||
// enormous function to compile/link.
|
fmt.Fprintf(b, "\tcheck(%q, %s, %s(%s))\n", expr2, expr2, typ, result)
|
||||||
// All the functions are named init so we don't have to do
|
|
||||||
// anything special to call them. ☺
|
// Chop test into multiple functions so that there's not one
|
||||||
if n++; n >= 100 {
|
// enormous function to compile/link.
|
||||||
fmt.Fprintf(b, "}\n")
|
// All the functions are named init so we don't have to do
|
||||||
fmt.Fprintf(b, "func init() {\n")
|
// anything special to call them. ☺
|
||||||
n = 0
|
if n++; n >= 50 {
|
||||||
|
fmt.Fprintf(b, "}\n")
|
||||||
|
fmt.Fprintf(b, "func init() {\n")
|
||||||
|
n = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue