]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/ssa: combine 2 byte loads + shifts into word load + rolw 8 on...
authorKirill Smelkov <kirr@nexedi.com>
Thu, 1 Dec 2016 20:43:21 +0000 (23:43 +0300)
committerIlya Tocar <ilya.tocar@intel.com>
Tue, 14 Feb 2017 22:17:08 +0000 (22:17 +0000)
... and same for stores. This does for binary.BigEndian.Uint16() what
was already done for Uint32 and Uint64 with BSWAP in 10f75748 (CL 32222).

Here is how generated code changes e.g. for the following function
(omitting saying the same prologue/epilogue):

func get16(b [2]byte) uint16 {
return binary.BigEndian.Uint16(b[:])
}

"".get16 t=1 size=21 args=0x10 locals=0x0

// before
        0x0000 00000 (x.go:15)  MOVBLZX "".b+9(FP), AX
        0x0005 00005 (x.go:15)  MOVBLZX "".b+8(FP), CX
        0x000a 00010 (x.go:15)  SHLL    $8, CX
        0x000d 00013 (x.go:15)  ORL     CX, AX

// after
0x0000 00000 (x.go:15) MOVWLZX "".b+8(FP), AX
0x0005 00005 (x.go:15) ROLW $8, AX

encoding/binary is speedup overall a bit:

name                    old time/op    new time/op    delta
ReadSlice1000Int32s-4     4.83µs ± 0%    4.83µs ± 0%     ~     (p=0.206 n=4+5)
ReadStruct-4              1.29µs ± 2%    1.28µs ± 1%   -1.27%  (p=0.032 n=4+5)
ReadInts-4                 384ns ± 1%     385ns ± 1%     ~     (p=0.968 n=4+5)
WriteInts-4                534ns ± 3%     526ns ± 0%   -1.54%  (p=0.048 n=4+5)
WriteSlice1000Int32s-4    5.02µs ± 0%    5.11µs ± 3%     ~     (p=0.175 n=4+5)
PutUint16-4               0.59ns ± 0%    0.49ns ± 2%  -16.95%  (p=0.016 n=4+5)
PutUint32-4               0.52ns ± 0%    0.52ns ± 0%     ~     (all equal)
PutUint64-4               0.53ns ± 0%    0.53ns ± 0%     ~     (all equal)
PutUvarint32-4            19.9ns ± 0%    19.9ns ± 1%     ~     (p=0.556 n=4+5)
PutUvarint64-4            54.5ns ± 1%    54.2ns ± 0%     ~     (p=0.333 n=4+5)

name                    old speed      new speed      delta
ReadSlice1000Int32s-4    829MB/s ± 0%   828MB/s ± 0%     ~     (p=0.190 n=4+5)
ReadStruct-4            58.0MB/s ± 2%  58.7MB/s ± 1%   +1.30%  (p=0.032 n=4+5)
ReadInts-4              78.0MB/s ± 1%  77.8MB/s ± 1%     ~     (p=0.968 n=4+5)
WriteInts-4             56.1MB/s ± 3%  57.0MB/s ± 0%     ~     (p=0.063 n=4+5)
WriteSlice1000Int32s-4   797MB/s ± 0%   783MB/s ± 3%     ~     (p=0.190 n=4+5)
PutUint16-4             3.37GB/s ± 0%  4.07GB/s ± 2%  +20.83%  (p=0.016 n=4+5)
PutUint32-4             7.73GB/s ± 0%  7.72GB/s ± 0%     ~     (p=0.556 n=4+5)
PutUint64-4             15.1GB/s ± 0%  15.1GB/s ± 0%     ~     (p=0.905 n=4+5)
PutUvarint32-4           201MB/s ± 0%   201MB/s ± 0%     ~     (p=0.905 n=4+5)
PutUvarint64-4           147MB/s ± 1%   147MB/s ± 0%     ~     (p=0.286 n=4+5)

( "a bit" only because most of the time is spent in reflection-like things
  there, not actual bytes decoding. Even for direct PutUint16 benchmark the
  looping adds overhead and lowers visible benefit. For code-generated encoders /
  decoders actual effect is more than 20% )

Adding Uint32 and Uint64 raw benchmarks too for completeness.

NOTE I had to adjust load-combining rule for bswap case to match first 2 bytes
loads as result of "2-bytes load+shift" -> "loadw + rorw 8" rewrite. Reason is:
for loads+shift, even e.g. into uint16 var

var b []byte
var v uin16
v = uint16(b[1]) | uint16(b[0])<<8

the compiler eventually generates L(ong) shift - SHLLconst [8], probably
because it is more straightforward / other reasons to work on the whole
register. This way 2 bytes rewriting rule is using SHLLconst (not SHLWconst) in
its pattern, and then it always gets matched first, even if 2-byte rule comes
syntactically after 4-byte rule in AMD64.rules because 4-bytes rule seemingly
needs more applyRewrite() cycles to trigger. If 2-bytes rule gets matched for
inner half of

var b []byte
var v uin32
v = uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24

and we keep 4-byte load rule unchanged, the result will be MOVW + RORW $8 and
then series of byte loads and shifts - not one MOVL + BSWAPL.

There is no such problem for stores: there compiler, since it probably knows
store destination is 2 bytes wide, uses SHRWconst 8 (not SHRLconst 8) and thus
2-byte store rule is not a subset of rule for 4-byte stores.

Fixes #17151  (int16 was last missing piece there)

Change-Id: Idc03ba965bfce2b94fef456b02ff6742194748f6
Reviewed-on: https://go-review.googlesource.com/34636
Reviewed-by: Ilya Tocar <ilya.tocar@intel.com>
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/asm_test.go
src/cmd/compile/internal/ssa/gen/AMD64.rules
src/cmd/compile/internal/ssa/rewriteAMD64.go
src/encoding/binary/binary_test.go

index 4373cfa6b62fde9912f97092e15329b0851b257c..fafb8a6b04a591dc4fa7abc0e9d859c6aede5eb7 100644 (file)
@@ -221,6 +221,38 @@ func f(b []byte, i int, v uint32) {
 `,
                []string{"\tBSWAPL\t"},
        },
+       {"amd64", "linux", `
+import "encoding/binary"
+func f(b []byte) uint16 {
+       return binary.BigEndian.Uint16(b)
+}
+`,
+               []string{"\tROLW\t\\$8,"},
+       },
+       {"amd64", "linux", `
+import "encoding/binary"
+func f(b []byte, i int) uint16 {
+       return binary.BigEndian.Uint16(b[i:])
+}
+`,
+               []string{"\tROLW\t\\$8,"},
+       },
+       {"amd64", "linux", `
+import "encoding/binary"
+func f(b []byte, v uint16) {
+       binary.BigEndian.PutUint16(b, v)
+}
+`,
+               []string{"\tROLW\t\\$8,"},
+       },
+       {"amd64", "linux", `
+import "encoding/binary"
+func f(b []byte, i int, v uint16) {
+       binary.BigEndian.PutUint16(b[i:], v)
+}
+`,
+               []string{"\tROLW\t\\$8,"},
+       },
        {"386", "linux", `
 import "encoding/binary"
 func f(b []byte) uint32 {
index 7beaa373de43f89cd7433f2482af4d90389b4dea..b996dca4217590906c6f451922cc629e030d88fa 100644 (file)
   && clobber(o5)
   -> @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVQloadidx1 <v.Type> [i] {s} p idx mem)
 
-// Combine byte loads + shifts into larger (unaligned) loads + bswap
-(ORL o1:(ORL o0:(ORL
+// Combine 2 byte loads + shifts into (unaligned) word load + rolw 8
+(ORL
                        x0:(MOVBload [i] {s} p mem)
     s0:(SHLLconst [8]  x1:(MOVBload [i-1] {s} p mem)))
-    s1:(SHLLconst [16] x2:(MOVBload [i-2] {s} p mem)))
-    s2:(SHLLconst [24] x3:(MOVBload [i-3] {s} p mem)))
   && x0.Uses == 1
   && x1.Uses == 1
+  && s0.Uses == 1
+  && mergePoint(b,x0,x1) != nil
+  && clobber(x0)
+  && clobber(x1)
+  && clobber(s0)
+  -> @mergePoint(b,x0,x1) (ROLWconst <v.Type> [8] (MOVWload [i-1] {s} p mem))
+
+(ORL
+                       x0:(MOVBloadidx1 [i] {s} p idx mem)
+    s0:(SHLLconst [8]  x1:(MOVBloadidx1 [i-1] {s} p idx mem)))
+  && x0.Uses == 1
+  && x1.Uses == 1
+  && s0.Uses == 1
+  && mergePoint(b,x0,x1) != nil
+  && clobber(x0)
+  && clobber(x1)
+  && clobber(s0)
+  -> @mergePoint(b,x0,x1) (ROLWconst <v.Type> [8] (MOVWloadidx1 <v.Type> [i-1] {s} p idx mem))
+
+// Combine byte loads + shifts into larger (unaligned) loads + bswap
+// (for L version first 2 bytes loads are matched as result of above 2-bytes load+shift rewrite)
+(ORL o1:(ORL o0:(ROLWconst [8] x01:(MOVWload [i1] {s} p mem))
+    s1:(SHLLconst [16] x2:(MOVBload [i1-1] {s} p mem)))
+    s2:(SHLLconst [24] x3:(MOVBload [i1-2] {s} p mem)))
+  && x01.Uses == 1
   && x2.Uses == 1
   && x3.Uses == 1
-  && s0.Uses == 1
   && s1.Uses == 1
   && s2.Uses == 1
   && o0.Uses == 1
   && o1.Uses == 1
-  && mergePoint(b,x0,x1,x2,x3) != nil
-  && clobber(x0)
-  && clobber(x1)
+  && mergePoint(b,x01,x2,x3) != nil
+  && clobber(x01)
   && clobber(x2)
   && clobber(x3)
-  && clobber(s0)
   && clobber(s1)
   && clobber(s2)
   && clobber(o0)
   && clobber(o1)
-  -> @mergePoint(b,x0,x1,x2,x3) (BSWAPL <v.Type> (MOVLload [i-3] {s} p mem))
+  -> @mergePoint(b,x01,x2,x3) (BSWAPL <v.Type> (MOVLload [i1-2] {s} p mem))
 
-(ORL o1:(ORL o0:(ORL
-                       x0:(MOVBloadidx1 [i] {s} p idx mem)
-    s0:(SHLLconst [8]  x1:(MOVBloadidx1 [i-1] {s} p idx mem)))
-    s1:(SHLLconst [16] x2:(MOVBloadidx1 [i-2] {s} p idx mem)))
-    s2:(SHLLconst [24] x3:(MOVBloadidx1 [i-3] {s} p idx mem)))
-  && x0.Uses == 1
-  && x1.Uses == 1
+(ORL o1:(ORL o0:(ROLWconst [8] x01:(MOVWloadidx1 [i1] {s} p idx mem))
+    s1:(SHLLconst [16] x2:(MOVBloadidx1 [i1-1] {s} p idx mem)))
+    s2:(SHLLconst [24] x3:(MOVBloadidx1 [i1-2] {s} p idx mem)))
+  && x01.Uses == 1
   && x2.Uses == 1
   && x3.Uses == 1
-  && s0.Uses == 1
   && s1.Uses == 1
   && s2.Uses == 1
   && o0.Uses == 1
   && o1.Uses == 1
-  && mergePoint(b,x0,x1,x2,x3) != nil
-  && clobber(x0)
-  && clobber(x1)
+  && mergePoint(b,x01,x2,x3) != nil
+  && clobber(x01)
   && clobber(x2)
   && clobber(x3)
-  && clobber(s0)
   && clobber(s1)
   && clobber(s2)
   && clobber(o0)
   && clobber(o1)
-  -> @mergePoint(b,x0,x1,x2,x3) (BSWAPL <v.Type> (MOVLloadidx1 <v.Type> [i-3] {s} p idx mem))
+  -> @mergePoint(b,x01,x2,x3) (BSWAPL <v.Type> (MOVLloadidx1 <v.Type> [i1-2] {s} p idx mem))
 
 (ORQ o5:(ORQ o4:(ORQ o3:(ORQ o2:(ORQ o1:(ORQ o0:(ORQ
                        x0:(MOVBload [i] {s} p mem)
   && clobber(o5)
   -> @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (BSWAPQ <v.Type> (MOVQloadidx1 <v.Type> [i-7] {s} p idx mem))
 
+// Combine 2 byte stores + shift into rolw 8 + word store
+(MOVBstore [i] {s} p w
+  x0:(MOVBstore [i-1] {s} p (SHRWconst [8] w) mem))
+  && x0.Uses == 1
+  && clobber(x0)
+  -> (MOVWstore [i-1] {s} p (ROLWconst <w.Type> [8] w) mem)
+
+(MOVBstoreidx1 [i] {s} p idx w
+  x0:(MOVBstoreidx1 [i-1] {s} p idx (SHRWconst [8] w) mem))
+  && x0.Uses == 1
+  && clobber(x0)
+  -> (MOVWstoreidx1 [i-1] {s} p idx (ROLWconst <w.Type> [8] w) mem)
+
 // Combine stores + shifts into bswap and larger (unaligned) stores
 (MOVBstore [i] {s} p w
   x2:(MOVBstore [i-1] {s} p (SHRLconst [8] w)
index acd88bd057253a2d354ae7c9d97642a25095b006..5ade11d2117f24cdedc6ccb4cb6db2e6f82866e2 100644 (file)
@@ -4148,6 +4148,52 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value, config *Config) bool {
                v.AddArg(mem)
                return true
        }
+       // match: (MOVBstore [i] {s} p w   x0:(MOVBstore [i-1] {s} p (SHRWconst [8] w) mem))
+       // cond: x0.Uses == 1   && clobber(x0)
+       // result: (MOVWstore [i-1] {s} p (ROLWconst <w.Type> [8] w) mem)
+       for {
+               i := v.AuxInt
+               s := v.Aux
+               p := v.Args[0]
+               w := v.Args[1]
+               x0 := v.Args[2]
+               if x0.Op != OpAMD64MOVBstore {
+                       break
+               }
+               if x0.AuxInt != i-1 {
+                       break
+               }
+               if x0.Aux != s {
+                       break
+               }
+               if p != x0.Args[0] {
+                       break
+               }
+               x0_1 := x0.Args[1]
+               if x0_1.Op != OpAMD64SHRWconst {
+                       break
+               }
+               if x0_1.AuxInt != 8 {
+                       break
+               }
+               if w != x0_1.Args[0] {
+                       break
+               }
+               mem := x0.Args[2]
+               if !(x0.Uses == 1 && clobber(x0)) {
+                       break
+               }
+               v.reset(OpAMD64MOVWstore)
+               v.AuxInt = i - 1
+               v.Aux = s
+               v.AddArg(p)
+               v0 := b.NewValue0(v.Pos, OpAMD64ROLWconst, w.Type)
+               v0.AuxInt = 8
+               v0.AddArg(w)
+               v.AddArg(v0)
+               v.AddArg(mem)
+               return true
+       }
        // match: (MOVBstore [i] {s} p w   x2:(MOVBstore [i-1] {s} p (SHRLconst [8] w)   x1:(MOVBstore [i-2] {s} p (SHRLconst [16] w)   x0:(MOVBstore [i-3] {s} p (SHRLconst [24] w) mem))))
        // cond: x0.Uses == 1   && x1.Uses == 1   && x2.Uses == 1   && clobber(x0)   && clobber(x1)   && clobber(x2)
        // result: (MOVLstore [i-3] {s} p (BSWAPL <w.Type> w) mem)
@@ -4875,6 +4921,57 @@ func rewriteValueAMD64_OpAMD64MOVBstoreidx1(v *Value, config *Config) bool {
                v.AddArg(mem)
                return true
        }
+       // match: (MOVBstoreidx1 [i] {s} p idx w   x0:(MOVBstoreidx1 [i-1] {s} p idx (SHRWconst [8] w) mem))
+       // cond: x0.Uses == 1   && clobber(x0)
+       // result: (MOVWstoreidx1 [i-1] {s} p idx (ROLWconst <w.Type> [8] w) mem)
+       for {
+               i := v.AuxInt
+               s := v.Aux
+               p := v.Args[0]
+               idx := v.Args[1]
+               w := v.Args[2]
+               x0 := v.Args[3]
+               if x0.Op != OpAMD64MOVBstoreidx1 {
+                       break
+               }
+               if x0.AuxInt != i-1 {
+                       break
+               }
+               if x0.Aux != s {
+                       break
+               }
+               if p != x0.Args[0] {
+                       break
+               }
+               if idx != x0.Args[1] {
+                       break
+               }
+               x0_2 := x0.Args[2]
+               if x0_2.Op != OpAMD64SHRWconst {
+                       break
+               }
+               if x0_2.AuxInt != 8 {
+                       break
+               }
+               if w != x0_2.Args[0] {
+                       break
+               }
+               mem := x0.Args[3]
+               if !(x0.Uses == 1 && clobber(x0)) {
+                       break
+               }
+               v.reset(OpAMD64MOVWstoreidx1)
+               v.AuxInt = i - 1
+               v.Aux = s
+               v.AddArg(p)
+               v.AddArg(idx)
+               v0 := b.NewValue0(v.Pos, OpAMD64ROLWconst, w.Type)
+               v0.AuxInt = 8
+               v0.AddArg(w)
+               v.AddArg(v0)
+               v.AddArg(mem)
+               return true
+       }
        // match: (MOVBstoreidx1 [i] {s} p idx w   x2:(MOVBstoreidx1 [i-1] {s} p idx (SHRLconst [8] w)   x1:(MOVBstoreidx1 [i-2] {s} p idx (SHRLconst [16] w)   x0:(MOVBstoreidx1 [i-3] {s} p idx (SHRLconst [24] w) mem))))
        // cond: x0.Uses == 1   && x1.Uses == 1   && x2.Uses == 1   && clobber(x0)   && clobber(x1)   && clobber(x2)
        // result: (MOVLstoreidx1 [i-3] {s} p idx (BSWAPL <w.Type> w) mem)
@@ -11866,19 +11963,11 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value, config *Config) bool {
                v0.AddArg(mem)
                return true
        }
-       // match: (ORL o1:(ORL o0:(ORL                        x0:(MOVBload [i] {s} p mem)     s0:(SHLLconst [8]  x1:(MOVBload [i-1] {s} p mem)))     s1:(SHLLconst [16] x2:(MOVBload [i-2] {s} p mem)))     s2:(SHLLconst [24] x3:(MOVBload [i-3] {s} p mem)))
-       // cond: x0.Uses == 1   && x1.Uses == 1   && x2.Uses == 1   && x3.Uses == 1   && s0.Uses == 1   && s1.Uses == 1   && s2.Uses == 1   && o0.Uses == 1   && o1.Uses == 1   && mergePoint(b,x0,x1,x2,x3) != nil   && clobber(x0)   && clobber(x1)   && clobber(x2)   && clobber(x3)   && clobber(s0)   && clobber(s1)   && clobber(s2)   && clobber(o0)   && clobber(o1)
-       // result: @mergePoint(b,x0,x1,x2,x3) (BSWAPL <v.Type> (MOVLload [i-3] {s} p mem))
+       // match: (ORL                        x0:(MOVBload [i] {s} p mem)     s0:(SHLLconst [8]  x1:(MOVBload [i-1] {s} p mem)))
+       // cond: x0.Uses == 1   && x1.Uses == 1   && s0.Uses == 1   && mergePoint(b,x0,x1) != nil   && clobber(x0)   && clobber(x1)   && clobber(s0)
+       // result: @mergePoint(b,x0,x1) (ROLWconst <v.Type> [8] (MOVWload [i-1] {s} p mem))
        for {
-               o1 := v.Args[0]
-               if o1.Op != OpAMD64ORL {
-                       break
-               }
-               o0 := o1.Args[0]
-               if o0.Op != OpAMD64ORL {
-                       break
-               }
-               x0 := o0.Args[0]
+               x0 := v.Args[0]
                if x0.Op != OpAMD64MOVBload {
                        break
                }
@@ -11886,7 +11975,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value, config *Config) bool {
                s := x0.Aux
                p := x0.Args[0]
                mem := x0.Args[1]
-               s0 := o0.Args[1]
+               s0 := v.Args[1]
                if s0.Op != OpAMD64SHLLconst {
                        break
                }
@@ -11909,6 +11998,101 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value, config *Config) bool {
                if mem != x1.Args[1] {
                        break
                }
+               if !(x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0) && clobber(x1) && clobber(s0)) {
+                       break
+               }
+               b = mergePoint(b, x0, x1)
+               v0 := b.NewValue0(v.Pos, OpAMD64ROLWconst, v.Type)
+               v.reset(OpCopy)
+               v.AddArg(v0)
+               v0.AuxInt = 8
+               v1 := b.NewValue0(v.Pos, OpAMD64MOVWload, config.fe.TypeUInt16())
+               v1.AuxInt = i - 1
+               v1.Aux = s
+               v1.AddArg(p)
+               v1.AddArg(mem)
+               v0.AddArg(v1)
+               return true
+       }
+       // match: (ORL                        x0:(MOVBloadidx1 [i] {s} p idx mem)     s0:(SHLLconst [8]  x1:(MOVBloadidx1 [i-1] {s} p idx mem)))
+       // cond: x0.Uses == 1   && x1.Uses == 1   && s0.Uses == 1   && mergePoint(b,x0,x1) != nil   && clobber(x0)   && clobber(x1)   && clobber(s0)
+       // result: @mergePoint(b,x0,x1) (ROLWconst <v.Type> [8] (MOVWloadidx1 <v.Type> [i-1] {s} p idx mem))
+       for {
+               x0 := v.Args[0]
+               if x0.Op != OpAMD64MOVBloadidx1 {
+                       break
+               }
+               i := x0.AuxInt
+               s := x0.Aux
+               p := x0.Args[0]
+               idx := x0.Args[1]
+               mem := x0.Args[2]
+               s0 := v.Args[1]
+               if s0.Op != OpAMD64SHLLconst {
+                       break
+               }
+               if s0.AuxInt != 8 {
+                       break
+               }
+               x1 := s0.Args[0]
+               if x1.Op != OpAMD64MOVBloadidx1 {
+                       break
+               }
+               if x1.AuxInt != i-1 {
+                       break
+               }
+               if x1.Aux != s {
+                       break
+               }
+               if p != x1.Args[0] {
+                       break
+               }
+               if idx != x1.Args[1] {
+                       break
+               }
+               if mem != x1.Args[2] {
+                       break
+               }
+               if !(x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0) && clobber(x1) && clobber(s0)) {
+                       break
+               }
+               b = mergePoint(b, x0, x1)
+               v0 := b.NewValue0(v.Pos, OpAMD64ROLWconst, v.Type)
+               v.reset(OpCopy)
+               v.AddArg(v0)
+               v0.AuxInt = 8
+               v1 := b.NewValue0(v.Pos, OpAMD64MOVWloadidx1, v.Type)
+               v1.AuxInt = i - 1
+               v1.Aux = s
+               v1.AddArg(p)
+               v1.AddArg(idx)
+               v1.AddArg(mem)
+               v0.AddArg(v1)
+               return true
+       }
+       // match: (ORL o1:(ORL o0:(ROLWconst [8] x01:(MOVWload [i1] {s} p mem))     s1:(SHLLconst [16] x2:(MOVBload [i1-1] {s} p mem)))     s2:(SHLLconst [24] x3:(MOVBload [i1-2] {s} p mem)))
+       // cond: x01.Uses == 1   && x2.Uses == 1   && x3.Uses == 1   && s1.Uses == 1   && s2.Uses == 1   && o0.Uses == 1   && o1.Uses == 1   && mergePoint(b,x01,x2,x3) != nil   && clobber(x01)   && clobber(x2)   && clobber(x3)   && clobber(s1)   && clobber(s2)   && clobber(o0)   && clobber(o1)
+       // result: @mergePoint(b,x01,x2,x3) (BSWAPL <v.Type> (MOVLload [i1-2] {s} p mem))
+       for {
+               o1 := v.Args[0]
+               if o1.Op != OpAMD64ORL {
+                       break
+               }
+               o0 := o1.Args[0]
+               if o0.Op != OpAMD64ROLWconst {
+                       break
+               }
+               if o0.AuxInt != 8 {
+                       break
+               }
+               x01 := o0.Args[0]
+               if x01.Op != OpAMD64MOVWload {
+                       break
+               }
+               i1 := x01.AuxInt
+               s := x01.Aux
+               p := x01.Args[0]
+               mem := x01.Args[1]
                s1 := o1.Args[1]
                if s1.Op != OpAMD64SHLLconst {
                        break
@@ -11920,7 +12104,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value, config *Config) bool {
                if x2.Op != OpAMD64MOVBload {
                        break
                }
-               if x2.AuxInt != i-2 {
+               if x2.AuxInt != i1-1 {
                        break
                }
                if x2.Aux != s {
@@ -11943,7 +12127,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value, config *Config) bool {
                if x3.Op != OpAMD64MOVBload {
                        break
                }
-               if x3.AuxInt != i-3 {
+               if x3.AuxInt != i1-2 {
                        break
                }
                if x3.Aux != s {
@@ -11955,68 +12139,45 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value, config *Config) bool {
                if mem != x3.Args[1] {
                        break
                }
-               if !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1, x2, x3) != nil && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(s0) && clobber(s1) && clobber(s2) && clobber(o0) && clobber(o1)) {
+               if !(x01.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && mergePoint(b, x01, x2, x3) != nil && clobber(x01) && clobber(x2) && clobber(x3) && clobber(s1) && clobber(s2) && clobber(o0) && clobber(o1)) {
                        break
                }
-               b = mergePoint(b, x0, x1, x2, x3)
+               b = mergePoint(b, x01, x2, x3)
                v0 := b.NewValue0(v.Pos, OpAMD64BSWAPL, v.Type)
                v.reset(OpCopy)
                v.AddArg(v0)
                v1 := b.NewValue0(v.Pos, OpAMD64MOVLload, config.fe.TypeUInt32())
-               v1.AuxInt = i - 3
+               v1.AuxInt = i1 - 2
                v1.Aux = s
                v1.AddArg(p)
                v1.AddArg(mem)
                v0.AddArg(v1)
                return true
        }
-       // match: (ORL o1:(ORL o0:(ORL                        x0:(MOVBloadidx1 [i] {s} p idx mem)     s0:(SHLLconst [8]  x1:(MOVBloadidx1 [i-1] {s} p idx mem)))     s1:(SHLLconst [16] x2:(MOVBloadidx1 [i-2] {s} p idx mem)))     s2:(SHLLconst [24] x3:(MOVBloadidx1 [i-3] {s} p idx mem)))
-       // cond: x0.Uses == 1   && x1.Uses == 1   && x2.Uses == 1   && x3.Uses == 1   && s0.Uses == 1   && s1.Uses == 1   && s2.Uses == 1   && o0.Uses == 1   && o1.Uses == 1   && mergePoint(b,x0,x1,x2,x3) != nil   && clobber(x0)   && clobber(x1)   && clobber(x2)   && clobber(x3)   && clobber(s0)   && clobber(s1)   && clobber(s2)   && clobber(o0)   && clobber(o1)
-       // result: @mergePoint(b,x0,x1,x2,x3) (BSWAPL <v.Type> (MOVLloadidx1 <v.Type> [i-3] {s} p idx mem))
+       // match: (ORL o1:(ORL o0:(ROLWconst [8] x01:(MOVWloadidx1 [i1] {s} p idx mem))     s1:(SHLLconst [16] x2:(MOVBloadidx1 [i1-1] {s} p idx mem)))     s2:(SHLLconst [24] x3:(MOVBloadidx1 [i1-2] {s} p idx mem)))
+       // cond: x01.Uses == 1   && x2.Uses == 1   && x3.Uses == 1   && s1.Uses == 1   && s2.Uses == 1   && o0.Uses == 1   && o1.Uses == 1   && mergePoint(b,x01,x2,x3) != nil   && clobber(x01)   && clobber(x2)   && clobber(x3)   && clobber(s1)   && clobber(s2)   && clobber(o0)   && clobber(o1)
+       // result: @mergePoint(b,x01,x2,x3) (BSWAPL <v.Type> (MOVLloadidx1 <v.Type> [i1-2] {s} p idx mem))
        for {
                o1 := v.Args[0]
                if o1.Op != OpAMD64ORL {
                        break
                }
                o0 := o1.Args[0]
-               if o0.Op != OpAMD64ORL {
+               if o0.Op != OpAMD64ROLWconst {
                        break
                }
-               x0 := o0.Args[0]
-               if x0.Op != OpAMD64MOVBloadidx1 {
+               if o0.AuxInt != 8 {
                        break
                }
-               i := x0.AuxInt
-               s := x0.Aux
-               p := x0.Args[0]
-               idx := x0.Args[1]
-               mem := x0.Args[2]
-               s0 := o0.Args[1]
-               if s0.Op != OpAMD64SHLLconst {
-                       break
-               }
-               if s0.AuxInt != 8 {
-                       break
-               }
-               x1 := s0.Args[0]
-               if x1.Op != OpAMD64MOVBloadidx1 {
-                       break
-               }
-               if x1.AuxInt != i-1 {
-                       break
-               }
-               if x1.Aux != s {
-                       break
-               }
-               if p != x1.Args[0] {
-                       break
-               }
-               if idx != x1.Args[1] {
-                       break
-               }
-               if mem != x1.Args[2] {
+               x01 := o0.Args[0]
+               if x01.Op != OpAMD64MOVWloadidx1 {
                        break
                }
+               i1 := x01.AuxInt
+               s := x01.Aux
+               p := x01.Args[0]
+               idx := x01.Args[1]
+               mem := x01.Args[2]
                s1 := o1.Args[1]
                if s1.Op != OpAMD64SHLLconst {
                        break
@@ -12028,7 +12189,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value, config *Config) bool {
                if x2.Op != OpAMD64MOVBloadidx1 {
                        break
                }
-               if x2.AuxInt != i-2 {
+               if x2.AuxInt != i1-1 {
                        break
                }
                if x2.Aux != s {
@@ -12054,7 +12215,7 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value, config *Config) bool {
                if x3.Op != OpAMD64MOVBloadidx1 {
                        break
                }
-               if x3.AuxInt != i-3 {
+               if x3.AuxInt != i1-2 {
                        break
                }
                if x3.Aux != s {
@@ -12069,15 +12230,15 @@ func rewriteValueAMD64_OpAMD64ORL(v *Value, config *Config) bool {
                if mem != x3.Args[2] {
                        break
                }
-               if !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1, x2, x3) != nil && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(s0) && clobber(s1) && clobber(s2) && clobber(o0) && clobber(o1)) {
+               if !(x01.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && mergePoint(b, x01, x2, x3) != nil && clobber(x01) && clobber(x2) && clobber(x3) && clobber(s1) && clobber(s2) && clobber(o0) && clobber(o1)) {
                        break
                }
-               b = mergePoint(b, x0, x1, x2, x3)
+               b = mergePoint(b, x01, x2, x3)
                v0 := b.NewValue0(v.Pos, OpAMD64BSWAPL, v.Type)
                v.reset(OpCopy)
                v.AddArg(v0)
                v1 := b.NewValue0(v.Pos, OpAMD64MOVLloadidx1, v.Type)
-               v1.AuxInt = i - 3
+               v1.AuxInt = i1 - 2
                v1.Aux = s
                v1.AddArg(p)
                v1.AddArg(idx)
index fc7f2765efbcf147dbf213d7bc4081ca961ad287..0547bee43706ed6b461d78f864125dfe523cc6b1 100644 (file)
@@ -500,3 +500,27 @@ func BenchmarkWriteSlice1000Int32s(b *testing.B) {
        }
        b.StopTimer()
 }
+
+func BenchmarkPutUint16(b *testing.B) {
+       buf := [2]byte{}
+       b.SetBytes(2)
+       for i := 0; i < b.N; i++ {
+               BigEndian.PutUint16(buf[:], uint16(i))
+       }
+}
+
+func BenchmarkPutUint32(b *testing.B) {
+       buf := [4]byte{}
+       b.SetBytes(4)
+       for i := 0; i < b.N; i++ {
+               BigEndian.PutUint32(buf[:], uint32(i))
+       }
+}
+
+func BenchmarkPutUint64(b *testing.B) {
+       buf := [8]byte{}
+       b.SetBytes(8)
+       for i := 0; i < b.N; i++ {
+               BigEndian.PutUint64(buf[:], uint64(i))
+       }
+}