diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 262135bcbe5..706fe44191d 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 67d32d7ac2d..30963ff6c64 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<>r - v <<= 64 - bits - v >>= 64 - bits - result = fmt.Sprintf("%#x", v) - } else { - v := int64(v0) >> (64 - bits) - v = v<>r - v <<= 64 - bits - v >>= 64 - bits - result = fmt.Sprintf("%#x", v) - } + 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) - 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) + var result string + if unsigned { + v := uint64(v0) >> (64 - bits) + v = uop[o](v<>r) + v <<= 64 - bits + v >>= 64 - bits + result = fmt.Sprintf("%#x", v) + } else { + v := int64(v0) >> (64 - bits) + v = iop[o](v<>r) + v <<= 64 - bits + v >>= 64 - bits + result = fmt.Sprintf("%#x", v) + } - // 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 + 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 + } } } } } -