summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNigel Tao <nigeltao@golang.org>2012-06-04 20:53:32 +1000
committerNigel Tao <nigeltao@golang.org>2012-06-04 20:53:32 +1000
commit829c09875f66a0bf3ea56ad9a1f51d907957958b (patch)
tree3b2acf615c9799db53616f407fc03fb21dc1abbb
parent79349313fa871458577a0aaa8d52d7826f7285b5 (diff)
downloadgo-829c09875f66a0bf3ea56ad9a1f51d907957958b.tar.gz
cmd/gc: recognize u<<1 op u>>31 as a rotate when op is ^, not just |.
R=rsc CC=golang-dev http://codereview.appspot.com/6249071
-rw-r--r--src/cmd/gc/walk.c6
-rw-r--r--test/rotate.go105
2 files changed, 66 insertions, 45 deletions
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 262135bcb..706fe4419 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -468,7 +468,6 @@ walkexpr(Node **np, NodeList **init)
goto ret;
case OAND:
- case OXOR:
case OSUB:
case OMUL:
case OLT:
@@ -483,6 +482,7 @@ walkexpr(Node **np, NodeList **init)
goto ret;
case OOR:
+ case OXOR:
walkexpr(&n->left, init);
walkexpr(&n->right, init);
walkrotate(&n);
@@ -2708,10 +2708,10 @@ walkrotate(Node **np)
n = *np;
- // Want << | >> or >> | << on unsigned value.
+ // Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value.
l = n->left;
r = n->right;
- if(n->op != OOR ||
+ if((n->op != OOR && n->op != OXOR) ||
(l->op != OLSH && l->op != ORSH) ||
(r->op != OLSH && r->op != ORSH) ||
n->type == T || issigned[n->type->etype] ||
diff --git a/test/rotate.go b/test/rotate.go
index 67d32d7ac..30963ff6c 100644
--- a/test/rotate.go
+++ b/test/rotate.go
@@ -9,7 +9,7 @@
// Generate test of shift and rotate by constants.
// 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.
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) {
fmt.Fprintf(b, "func init() {\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.
for l := uint(0); l <= bits; l++ {
for r := uint(0); r <= bits; r++ {
- typ := fmt.Sprintf("int%d", bits)
- v := fmt.Sprintf("i%d", bits)
- if unsigned {
- typ = "u" + typ
- v = "u" + v
- }
- v0 := int64(0x123456789abcdef0)
- if inverted {
- 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)
-
- 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)
- fmt.Fprintf(b, "\tcheck(%q, %s, %s(%s))\n", expr2, expr2, typ, result)
-
- // Chop test into multiple functions so that there's not one
- // enormous function to compile/link.
- // All the functions are named init so we don't have to do
- // anything special to call them. ☺
- if n++; n >= 100 {
- fmt.Fprintf(b, "}\n")
- fmt.Fprintf(b, "func init() {\n")
- n = 0
+ for o, op := range cop {
+ typ := fmt.Sprintf("int%d", bits)
+ v := fmt.Sprintf("i%d", bits)
+ if unsigned {
+ typ = "u" + typ
+ v = "u" + v
+ }
+ v0 := int64(0x123456789abcdef0)
+ if inverted {
+ v = "n" + v
+ v0 = ^v0
+ }
+ 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 = 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)
+ }
+
+ fmt.Fprintf(b, "\tcheck(%q, %s, %s(%s))\n", expr1, expr1, typ, result)
+ fmt.Fprintf(b, "\tcheck(%q, %s, %s(%s))\n", expr2, expr2, typ, result)
+
+ // Chop test into multiple functions so that there's not one
+ // enormous function to compile/link.
+ // All the functions are named init so we don't have to do
+ // anything special to call them. ☺
+ if n++; n >= 50 {
+ fmt.Fprintf(b, "}\n")
+ fmt.Fprintf(b, "func init() {\n")
+ n = 0
+ }
}
}
}
}
-