]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: optimize RotateLeft8/16 on arm64
authorruinan <ruinan.sun@arm.com>
Wed, 13 Jul 2022 09:00:57 +0000 (09:00 +0000)
committerGopher Robot <gobot@golang.org>
Fri, 2 Sep 2022 17:46:31 +0000 (17:46 +0000)
This CL optimizes RotateLeft8/16 on arm64.

For 16 bits, we form a 32 bits register by duplicating two 16 bits
registers, then use RORW instruction to do the rotate shift.

For 8 bits, we just use LSR and LSL instead of RORW because the code is
simpler.

Benchmark          Old          ThisCL       delta
RotateLeft8-46     2.16 ns/op   1.73 ns/op   -19.70%
RotateLeft16-46    2.16 ns/op   1.54 ns/op   -28.53%

Change-Id: I09cde4383d12e31876a57f8cdfd3bb4f324fadb0
Reviewed-on: https://go-review.googlesource.com/c/go/+/420976
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Keith Randall <khr@golang.org>

src/cmd/compile/internal/ssa/gen/ARM64.rules
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewriteARM64.go
test/codegen/mathbits.go

index a91f17a2d34bb2233a26bd8702236de8c19c63b1..0d319609aaee7598c04a3a4440ce7fce6217d0c9 100644 (file)
 (Sqrt32 ...) => (FSQRTS ...)
 
 // lowering rotates
+// we do rotate detection in generic rules, if the following rules need to be changed, chcek generic rules first.
 (RotateLeft8 <t> x (MOVDconst [c])) => (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
+(RotateLeft8 <t> x y) => (OR <t> (SLL <t> x (ANDconst <typ.Int64> [7] y)) (SRL <t> (ZeroExt8to64 x) (ANDconst <typ.Int64> [7] (NEG <typ.Int64> y))))
 (RotateLeft16 <t> x (MOVDconst [c])) => (Or16 (Lsh16x64 <t> x (MOVDconst [c&15])) (Rsh16Ux64 <t> x (MOVDconst [-c&15])))
+(RotateLeft16 <t> x y) => (RORW <t> (ORshiftLL <typ.UInt32> (ZeroExt16to32 x) (ZeroExt16to32 x) [16]) (NEG <typ.Int64> y))
 (RotateLeft32 x y) => (RORW x (NEG <y.Type> y))
 (RotateLeft64 x y) => (ROR x (NEG <y.Type> y))
 
index 44b5173968b744616c41b2024d671e7d6b5f2525..c95d8734564c490c7fb392c990b8bd06cc157c67 100644 (file)
@@ -1986,9 +1986,9 @@ func canRotate(c *Config, bits int64) bool {
                return false
        }
        switch c.arch {
-       case "386", "amd64":
+       case "386", "amd64", "arm64":
                return true
-       case "arm", "arm64", "s390x", "ppc64", "ppc64le", "wasm", "loong64":
+       case "arm", "s390x", "ppc64", "ppc64le", "wasm", "loong64":
                return bits >= 32
        default:
                return false
index ecb8a6b779f4a3876f31c27d1fcea63716b63046..097d1772ab3b2dd3c8b9848c10c07068720f40bf 100644 (file)
@@ -25610,7 +25610,24 @@ func rewriteValueARM64_OpRotateLeft16(v *Value) bool {
                v.AddArg2(v0, v2)
                return true
        }
-       return false
+       // match: (RotateLeft16 <t> x y)
+       // result: (RORW <t> (ORshiftLL <typ.UInt32> (ZeroExt16to32 x) (ZeroExt16to32 x) [16]) (NEG <typ.Int64> y))
+       for {
+               t := v.Type
+               x := v_0
+               y := v_1
+               v.reset(OpARM64RORW)
+               v.Type = t
+               v0 := b.NewValue0(v.Pos, OpARM64ORshiftLL, typ.UInt32)
+               v0.AuxInt = int64ToAuxInt(16)
+               v1 := b.NewValue0(v.Pos, OpZeroExt16to32, typ.UInt32)
+               v1.AddArg(x)
+               v0.AddArg2(v1, v1)
+               v2 := b.NewValue0(v.Pos, OpARM64NEG, typ.Int64)
+               v2.AddArg(y)
+               v.AddArg2(v0, v2)
+               return true
+       }
 }
 func rewriteValueARM64_OpRotateLeft32(v *Value) bool {
        v_1 := v.Args[1]
@@ -25670,7 +25687,31 @@ func rewriteValueARM64_OpRotateLeft8(v *Value) bool {
                v.AddArg2(v0, v2)
                return true
        }
-       return false
+       // match: (RotateLeft8 <t> x y)
+       // result: (OR <t> (SLL <t> x (ANDconst <typ.Int64> [7] y)) (SRL <t> (ZeroExt8to64 x) (ANDconst <typ.Int64> [7] (NEG <typ.Int64> y))))
+       for {
+               t := v.Type
+               x := v_0
+               y := v_1
+               v.reset(OpARM64OR)
+               v.Type = t
+               v0 := b.NewValue0(v.Pos, OpARM64SLL, t)
+               v1 := b.NewValue0(v.Pos, OpARM64ANDconst, typ.Int64)
+               v1.AuxInt = int64ToAuxInt(7)
+               v1.AddArg(y)
+               v0.AddArg2(x, v1)
+               v2 := b.NewValue0(v.Pos, OpARM64SRL, t)
+               v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+               v3.AddArg(x)
+               v4 := b.NewValue0(v.Pos, OpARM64ANDconst, typ.Int64)
+               v4.AuxInt = int64ToAuxInt(7)
+               v5 := b.NewValue0(v.Pos, OpARM64NEG, typ.Int64)
+               v5.AddArg(y)
+               v4.AddArg(v5)
+               v2.AddArg2(v3, v4)
+               v.AddArg2(v0, v2)
+               return true
+       }
 }
 func rewriteValueARM64_OpRsh16Ux16(v *Value) bool {
        v_1 := v.Args[1]
index 9c643647ee900bd644673fb718d60c314851d712..0620766f5aea503e8bdf5fb2528da9f25638ce2e 100644 (file)
@@ -258,14 +258,16 @@ func RotateLeft32(n uint32) uint32 {
        return bits.RotateLeft32(n, 9)
 }
 
-func RotateLeft16(n uint16) uint16 {
+func RotateLeft16(n uint16, s int) uint16 {
        // amd64:"ROLW" 386:"ROLW"
-       return bits.RotateLeft16(n, 5)
+       // arm64:"RORW",-"CSEL"
+       return bits.RotateLeft16(n, s)
 }
 
-func RotateLeft8(n uint8) uint8 {
+func RotateLeft8(n uint8, s int) uint8 {
        // amd64:"ROLB" 386:"ROLB"
-       return bits.RotateLeft8(n, 5)
+       // arm64:"LSL","LSR",-"CSEL"
+       return bits.RotateLeft8(n, s)
 }
 
 func RotateLeftVariable(n uint, m int) uint {