]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: recognize u<<1 op u>>31 as a rotate when op is ^, not just |.
authorNigel Tao <nigeltao@golang.org>
Mon, 4 Jun 2012 10:53:32 +0000 (20:53 +1000)
committerNigel Tao <nigeltao@golang.org>
Mon, 4 Jun 2012 10:53:32 +0000 (20:53 +1000)
R=rsc
CC=golang-dev
https://golang.org/cl/6249071

src/cmd/gc/walk.c
test/rotate.go

index 262135bcbe546261aa3c5431d5defdeb2c224567..706fe44191d7c30e0403ab98626b56572e00020f 100644 (file)
@@ -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] ||
index 67d32d7ac2dc0da38155de2baaee19eb98b78fca..30963ff6c648ca7079c72abc266c5d4eab7c39d4 100644 (file)
@@ -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
+                               }
                        }
                }
        }
 }
-