]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: intrinsify RotateLeft32 on wasm
authorBrian Kessler <brian.m.kessler@gmail.com>
Fri, 17 May 2019 21:16:38 +0000 (15:16 -0600)
committerBrad Fitzpatrick <bradfitz@golang.org>
Sat, 31 Aug 2019 17:03:04 +0000 (17:03 +0000)
wasm has 32-bit versions of all integer operations. This change
lowers RotateLeft32 to i32.rotl on wasm and intrinsifies the math/bits
call.  Benchmarking on amd64 under node.js this is ~25% faster.

node v10.15.3/amd64
name          old time/op  new time/op  delta
RotateLeft    8.37ns ± 1%  8.28ns ± 0%   -1.05%  (p=0.029 n=4+4)
RotateLeft8   11.9ns ± 1%  11.8ns ± 0%     ~     (p=0.167 n=5+5)
RotateLeft16  11.8ns ± 0%  11.8ns ± 0%     ~     (all equal)
RotateLeft32  11.9ns ± 1%   8.7ns ± 0%  -26.32%  (p=0.008 n=5+5)
RotateLeft64  8.31ns ± 1%  8.43ns ± 2%     ~     (p=0.063 n=5+5)

Updates #31265

Change-Id: I5b8e155978faeea536c4f6427ac9564d2f096a46
Reviewed-on: https://go-review.googlesource.com/c/go/+/182359
Run-TryBot: Brian Kessler <brian.m.kessler@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Richard Musiol <neelance@gmail.com>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/gen/Wasm.rules
src/cmd/compile/internal/ssa/gen/WasmOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteWasm.go
src/cmd/compile/internal/wasm/ssa.go
test/codegen/mathbits.go

index b093e504f1276ea3360127b79746a465d69af34b..ac7f3eb22bdee6c5a60b2ef87dfb50a494946a84 100644 (file)
@@ -3504,7 +3504,7 @@ func init() {
                func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
                        return s.newValue2(ssa.OpRotateLeft32, types.Types[TUINT32], args[0], args[1])
                },
-               sys.AMD64, sys.ARM, sys.ARM64, sys.S390X, sys.PPC64)
+               sys.AMD64, sys.ARM, sys.ARM64, sys.S390X, sys.PPC64, sys.Wasm)
        addF("math/bits", "RotateLeft64",
                func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
                        return s.newValue2(ssa.OpRotateLeft64, types.Types[TUINT64], args[0], args[1])
index 998a886c0a567dcf169ec0e96ba95aba09fa301a..72080703f5571dde8460f585470ffb638dddcefc 100644 (file)
 // Lowering rotates
 (RotateLeft8 <t> x (I64Const [c])) -> (Or8 (Lsh8x64 <t> x (I64Const [c&7])) (Rsh8Ux64 <t> x (I64Const [-c&7])))
 (RotateLeft16 <t> x (I64Const [c])) -> (Or16 (Lsh16x64 <t> x (I64Const [c&15])) (Rsh16Ux64 <t> x (I64Const [-c&15])))
-(RotateLeft32 <t> x (I64Const [c])) -> (Or32 (Lsh32x64 <t> x (I64Const [c&31])) (Rsh32Ux64 <t> x (I64Const [-c&31])))
+(RotateLeft32 x y) -> (I32Rotl x y)
+(RotateLeft64 x y) -> (I64Rotl x y)
 
 // Lowering comparisons
 (Less64  x y) -> (I64LtS x y)
 
 (BitLen64 x) -> (I64Sub (I64Const [64]) (I64Clz x))
 
-(RotateLeft64 x y) -> (I64Rotl x y)
-
 (PopCount64 x) -> (I64Popcnt x)
 (PopCount32 x) -> (I64Popcnt (ZeroExt32to64 x))
 (PopCount16 x) -> (I64Popcnt (ZeroExt16to64 x))
index de035c985addf95505f20c2fc2353581fe1d575a..500d7201c2c276149037e9adc1a9cd4b2b932f60 100644 (file)
@@ -206,6 +206,7 @@ func init() {
 
                {name: "I64Ctz", asm: "I64Ctz", argLength: 1, reg: gp11, typ: "Int64"},       // ctz(arg0)
                {name: "I64Clz", asm: "I64Clz", argLength: 1, reg: gp11, typ: "Int64"},       // clz(arg0)
+               {name: "I32Rotl", asm: "I32Rotl", argLength: 2, reg: gp21, typ: "Int32"},     // rotl(arg0, arg1)
                {name: "I64Rotl", asm: "I64Rotl", argLength: 2, reg: gp21, typ: "Int64"},     // rotl(arg0, arg1)
                {name: "I64Popcnt", asm: "I64Popcnt", argLength: 1, reg: gp11, typ: "Int64"}, // popcnt(arg0)
        }
index ef99da2330e3e44dc970a5752df4c70d26400275..5785e361dcd73174e7927782795489be150191ca 100644 (file)
@@ -2168,6 +2168,7 @@ const (
        OpWasmF64Copysign
        OpWasmI64Ctz
        OpWasmI64Clz
+       OpWasmI32Rotl
        OpWasmI64Rotl
        OpWasmI64Popcnt
 
@@ -29140,6 +29141,20 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:   "I32Rotl",
+               argLen: 2,
+               asm:    wasm.AI32Rotl,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 4295032831}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+                               {1, 4295032831}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+                       },
+                       outputs: []outputInfo{
+                               {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+                       },
+               },
+       },
        {
                name:   "I64Rotl",
                argLen: 2,
index f374565327fa1940b43bb8b819a4d50c3912631a..45b855027d853f1cb2d52a7123a710f96e9606af 100644 (file)
@@ -3826,36 +3826,17 @@ func rewriteValueWasm_OpRotateLeft16_0(v *Value) bool {
        return false
 }
 func rewriteValueWasm_OpRotateLeft32_0(v *Value) bool {
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (RotateLeft32 <t> x (I64Const [c]))
+       // match: (RotateLeft32 x y)
        // cond:
-       // result: (Or32 (Lsh32x64 <t> x (I64Const [c&31])) (Rsh32Ux64 <t> x (I64Const [-c&31])))
+       // result: (I32Rotl x y)
        for {
-               t := v.Type
-               _ = v.Args[1]
+               y := v.Args[1]
                x := v.Args[0]
-               v_1 := v.Args[1]
-               if v_1.Op != OpWasmI64Const {
-                       break
-               }
-               c := v_1.AuxInt
-               v.reset(OpOr32)
-               v0 := b.NewValue0(v.Pos, OpLsh32x64, t)
-               v0.AddArg(x)
-               v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
-               v1.AuxInt = c & 31
-               v0.AddArg(v1)
-               v.AddArg(v0)
-               v2 := b.NewValue0(v.Pos, OpRsh32Ux64, t)
-               v2.AddArg(x)
-               v3 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
-               v3.AuxInt = -c & 31
-               v2.AddArg(v3)
-               v.AddArg(v2)
+               v.reset(OpWasmI32Rotl)
+               v.AddArg(x)
+               v.AddArg(y)
                return true
        }
-       return false
 }
 func rewriteValueWasm_OpRotateLeft64_0(v *Value) bool {
        // match: (RotateLeft64 x y)
index b50f662a8b526e52d5ea07be45a2ed032a15c424..761a40227d2096bcfc4dbdc2f6175e35d2a21f08 100644 (file)
@@ -299,6 +299,12 @@ func ssaGenValueOnStack(s *gc.SSAGenState, v *ssa.Value, extend bool) {
                getValue64(s, v.Args[1])
                s.Prog(v.Op.Asm())
 
+       case ssa.OpWasmI32Rotl:
+               getValue32(s, v.Args[0])
+               getValue32(s, v.Args[1])
+               s.Prog(wasm.AI32Rotl)
+               s.Prog(wasm.AI64ExtendI32U)
+
        case ssa.OpWasmI64DivS:
                getValue64(s, v.Args[0])
                getValue64(s, v.Args[1])
index 61e5db56e1f10dca53b36c47c9f30fab5369a37b..9cdfe0b06ac861f60f2c6782c58c18ca0470bf88 100644 (file)
@@ -213,6 +213,7 @@ func RotateLeft32(n uint32) uint32 {
        // ppc64:"ROTLW"
        // ppc64le:"ROTLW"
        // s390x:"RLL"
+       // wasm:"I32Rotl"
        return bits.RotateLeft32(n, 9)
 }
 
@@ -232,6 +233,7 @@ func RotateLeftVariable(n uint, m int) uint {
        // ppc64:"ROTL"
        // ppc64le:"ROTL"
        // s390x:"RLLG"
+       // wasm:"I64Rotl"
        return bits.RotateLeft(n, m)
 }
 
@@ -241,6 +243,7 @@ func RotateLeftVariable64(n uint64, m int) uint64 {
        // ppc64:"ROTL"
        // ppc64le:"ROTL"
        // s390x:"RLLG"
+       // wasm:"I64Rotl"
        return bits.RotateLeft64(n, m)
 }
 
@@ -251,6 +254,7 @@ func RotateLeftVariable32(n uint32, m int) uint32 {
        // ppc64:"ROTLW"
        // ppc64le:"ROTLW"
        // s390x:"RLL"
+       // wasm:"I32Rotl"
        return bits.RotateLeft32(n, m)
 }