]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: improve rotations for riscv64
authorJoel Sing <joel@sing.id.au>
Thu, 1 Feb 2024 12:58:54 +0000 (23:58 +1100)
committerJoel Sing <joel@sing.id.au>
Fri, 16 Feb 2024 11:59:07 +0000 (11:59 +0000)
Enable canRotate for riscv64, enable rotation intrinsics and provide
better rewrite implementations for rotations. By avoiding Lsh*x64
and Rsh*Ux64 we can produce better code, especially for 32 and 64
bit rotations. By enabling canRotate we also benefit from the generic
rotation rewrite rules.

Benchmark on a StarFive VisionFive 2:

               │   rotate.1   │              rotate.2               │
               │    sec/op    │   sec/op     vs base                │
RotateLeft-4     14.700n ± 0%   8.016n ± 0%  -45.47% (p=0.000 n=10)
RotateLeft8-4     14.70n ± 0%   10.69n ± 0%  -27.28% (p=0.000 n=10)
RotateLeft16-4    14.70n ± 0%   12.02n ± 0%  -18.23% (p=0.000 n=10)
RotateLeft32-4   13.360n ± 0%   8.016n ± 0%  -40.00% (p=0.000 n=10)
RotateLeft64-4   13.360n ± 0%   8.016n ± 0%  -40.00% (p=0.000 n=10)
geomean           14.15n        9.208n       -34.92%

Change-Id: I1a2036fdc57cf88ebb6617eb8d92e1d187e183b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/560315
Reviewed-by: M Zhuo <mengzhuo1203@gmail.com>
Run-TryBot: Joel Sing <joel@sing.id.au>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Mark Ryan <markdryan@rivosinc.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/riscv64/ssa.go
src/cmd/compile/internal/ssa/_gen/RISCV64.rules
src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewriteRISCV64.go
src/cmd/compile/internal/ssagen/ssa.go
test/codegen/rotate.go

index caca504d28460618b8c3a07cdadb5e633b2c0873..17f0d9853283b7b443ffdd0056d85819c1a61a63 100644 (file)
@@ -278,7 +278,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
                p.To.Type = obj.TYPE_REG
                p.To.Reg = rd
        case ssa.OpRISCV64ADD, ssa.OpRISCV64SUB, ssa.OpRISCV64SUBW, ssa.OpRISCV64XOR, ssa.OpRISCV64OR, ssa.OpRISCV64AND,
-               ssa.OpRISCV64SLL, ssa.OpRISCV64SRA, ssa.OpRISCV64SRAW, ssa.OpRISCV64SRL, ssa.OpRISCV64SRLW,
+               ssa.OpRISCV64SLL, ssa.OpRISCV64SLLW, ssa.OpRISCV64SRA, ssa.OpRISCV64SRAW, ssa.OpRISCV64SRL, ssa.OpRISCV64SRLW,
                ssa.OpRISCV64SLT, ssa.OpRISCV64SLTU, ssa.OpRISCV64MUL, ssa.OpRISCV64MULW, ssa.OpRISCV64MULH,
                ssa.OpRISCV64MULHU, ssa.OpRISCV64DIV, ssa.OpRISCV64DIVU, ssa.OpRISCV64DIVW,
                ssa.OpRISCV64DIVUW, ssa.OpRISCV64REM, ssa.OpRISCV64REMU, ssa.OpRISCV64REMW,
@@ -422,8 +422,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
                p.To.Type = obj.TYPE_REG
                p.To.Reg = v.Reg()
        case ssa.OpRISCV64ADDI, ssa.OpRISCV64ADDIW, ssa.OpRISCV64XORI, ssa.OpRISCV64ORI, ssa.OpRISCV64ANDI,
-               ssa.OpRISCV64SLLI, ssa.OpRISCV64SRAI, ssa.OpRISCV64SRAIW, ssa.OpRISCV64SRLI, ssa.OpRISCV64SRLIW, ssa.OpRISCV64SLTI,
-               ssa.OpRISCV64SLTIU:
+               ssa.OpRISCV64SLLI, ssa.OpRISCV64SLLIW, ssa.OpRISCV64SRAI, ssa.OpRISCV64SRAIW,
+               ssa.OpRISCV64SRLI, ssa.OpRISCV64SRLIW, ssa.OpRISCV64SLTI, ssa.OpRISCV64SLTIU:
                p := s.Prog(v.Op.Asm())
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = v.AuxInt
index 4fef20a565137d66d4962d4efe9674c597a51752..135d70bc4787815f5b5577c3329fe978bfb14a0a 100644 (file)
 (Rsh64x(64|32|16|8) x y) && shiftIsBounded(v) => (SRA   x                y)
 
 // Rotates.
-(RotateLeft8  <t> x (MOVDconst [c])) => (Or8  (Lsh8x64  <t> x (MOVDconst [c&7]))  (Rsh8Ux64  <t> x (MOVDconst [-c&7])))
-(RotateLeft16 <t> x (MOVDconst [c])) => (Or16 (Lsh16x64 <t> x (MOVDconst [c&15])) (Rsh16Ux64 <t> x (MOVDconst [-c&15])))
-(RotateLeft32 <t> x (MOVDconst [c])) => (Or32 (Lsh32x64 <t> x (MOVDconst [c&31])) (Rsh32Ux64 <t> x (MOVDconst [-c&31])))
-(RotateLeft64 <t> x (MOVDconst [c])) => (Or64 (Lsh64x64 <t> x (MOVDconst [c&63])) (Rsh64Ux64 <t> x (MOVDconst [-c&63])))
+(RotateLeft8  <t> x y) => (OR (SLL  <t> x (ANDI [7]  <y.Type> y)) (SRL <t> (ZeroExt8to64  x) (ANDI [7]  <y.Type> (NEG <y.Type> y))))
+(RotateLeft16 <t> x y) => (OR (SLL  <t> x (ANDI [15] <y.Type> y)) (SRL <t> (ZeroExt16to64 x) (ANDI [15] <y.Type> (NEG <y.Type> y))))
+(RotateLeft32 <t> x y) => (OR (SLLW <t> x y) (SRLW <t> x (NEG <y.Type> y)))
+(RotateLeft64 <t> x y) => (OR (SLL  <t> x y) (SRL  <t> x (NEG <y.Type> y)))
 
 (Less64  ...) => (SLT  ...)
 (Less32  x y) => (SLT  (SignExt32to64 x) (SignExt32to64 y))
 (XOR (MOVDconst [val]) x) && is32Bit(val) => (XORI [val] x)
 (SLL  x (MOVDconst [val])) => (SLLI [int64(val&63)] x)
 (SRL  x (MOVDconst [val])) => (SRLI [int64(val&63)] x)
+(SLLW x (MOVDconst [val])) => (SLLIW [int64(val&31)] x)
 (SRLW x (MOVDconst [val])) => (SRLIW [int64(val&31)] x)
 (SRA  x (MOVDconst [val])) => (SRAI [int64(val&63)] x)
 (SRAW x (MOVDconst [val])) => (SRAIW [int64(val&31)] x)
index 9ce6450166ead401a702da5c668cd8333c65326d..e9f1df0d58ada204d315a569f7f8d34ae0beb376 100644 (file)
@@ -207,16 +207,18 @@ func init() {
                {name: "MOVDnop", argLength: 1, reg: regInfo{inputs: []regMask{gpMask}, outputs: []regMask{gpMask}}, resultInArg0: true}, // nop, return arg0 in same register
 
                // Shift ops
-               {name: "SLL", argLength: 2, reg: gp21, asm: "SLL"},                   // arg0 << (aux1 & 63)
-               {name: "SRA", argLength: 2, reg: gp21, asm: "SRA"},                   // arg0 >> (aux1 & 63), signed
-               {name: "SRAW", argLength: 2, reg: gp21, asm: "SRAW"},                 // arg0 >> (aux1 & 31), signed
-               {name: "SRL", argLength: 2, reg: gp21, asm: "SRL"},                   // arg0 >> (aux1 & 63), unsigned
-               {name: "SRLW", argLength: 2, reg: gp21, asm: "SRLW"},                 // arg0 >> (aux1 & 31), unsigned
-               {name: "SLLI", argLength: 1, reg: gp11, asm: "SLLI", aux: "Int64"},   // arg0 << auxint, shift amount 0-63
-               {name: "SRAI", argLength: 1, reg: gp11, asm: "SRAI", aux: "Int64"},   // arg0 >> auxint, signed, shift amount 0-63
-               {name: "SRAIW", argLength: 1, reg: gp11, asm: "SRAIW", aux: "Int64"}, // arg0 >> auxint, signed, shift amount 0-31
-               {name: "SRLI", argLength: 1, reg: gp11, asm: "SRLI", aux: "Int64"},   // arg0 >> auxint, unsigned, shift amount 0-63
-               {name: "SRLIW", argLength: 1, reg: gp11, asm: "SRLIW", aux: "Int64"}, // arg0 >> auxint, unsigned, shift amount 0-31
+               {name: "SLL", argLength: 2, reg: gp21, asm: "SLL"},                   // arg0 << (aux1 & 63), logical left shift
+               {name: "SLLW", argLength: 2, reg: gp21, asm: "SLLW"},                 // arg0 << (aux1 & 31), logical left shift of 32 bit value, sign extended to 64 bits
+               {name: "SRA", argLength: 2, reg: gp21, asm: "SRA"},                   // arg0 >> (aux1 & 63), arithmetic right shift
+               {name: "SRAW", argLength: 2, reg: gp21, asm: "SRAW"},                 // arg0 >> (aux1 & 31), arithmetic right shift of 32 bit value, sign extended to 64 bits
+               {name: "SRL", argLength: 2, reg: gp21, asm: "SRL"},                   // arg0 >> (aux1 & 63), logical right shift
+               {name: "SRLW", argLength: 2, reg: gp21, asm: "SRLW"},                 // arg0 >> (aux1 & 31), logical right shift of 32 bit value, sign extended to 64 bits
+               {name: "SLLI", argLength: 1, reg: gp11, asm: "SLLI", aux: "Int64"},   // arg0 << auxint, shift amount 0-63, logical left shift
+               {name: "SLLIW", argLength: 1, reg: gp11, asm: "SLLIW", aux: "Int64"}, // arg0 << auxint, shift amount 0-31, logical left shift of 32 bit value, sign extended to 64 bits
+               {name: "SRAI", argLength: 1, reg: gp11, asm: "SRAI", aux: "Int64"},   // arg0 >> auxint, shift amount 0-63, arithmetic right shift
+               {name: "SRAIW", argLength: 1, reg: gp11, asm: "SRAIW", aux: "Int64"}, // arg0 >> auxint, shift amount 0-31, arithmetic right shift of 32 bit value, sign extended to 64 bits
+               {name: "SRLI", argLength: 1, reg: gp11, asm: "SRLI", aux: "Int64"},   // arg0 >> auxint, shift amount 0-63, logical right shift
+               {name: "SRLIW", argLength: 1, reg: gp11, asm: "SRLIW", aux: "Int64"}, // arg0 >> auxint, shift amount 0-31, logical right shift of 32 bit value, sign extended to 64 bits
 
                // Bitwise ops
                {name: "XOR", argLength: 2, reg: gp21, asm: "XOR", commutative: true}, // arg0 ^ arg1
index 5a2ca1a42472e5fa823a84a2dfe54c9f24d28479..2378c7abc22218f2f9a9dece4bd7e990ce615745 100644 (file)
@@ -2388,11 +2388,13 @@ const (
        OpRISCV64MOVWUreg
        OpRISCV64MOVDnop
        OpRISCV64SLL
+       OpRISCV64SLLW
        OpRISCV64SRA
        OpRISCV64SRAW
        OpRISCV64SRL
        OpRISCV64SRLW
        OpRISCV64SLLI
+       OpRISCV64SLLIW
        OpRISCV64SRAI
        OpRISCV64SRAIW
        OpRISCV64SRLI
@@ -32045,6 +32047,20 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:   "SLLW",
+               argLen: 2,
+               asm:    riscv.ASLLW,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+                               {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+                       },
+                       outputs: []outputInfo{
+                               {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+                       },
+               },
+       },
        {
                name:   "SRA",
                argLen: 2,
@@ -32115,6 +32131,20 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:    "SLLIW",
+               auxType: auxInt64,
+               argLen:  1,
+               asm:     riscv.ASLLIW,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+                       },
+                       outputs: []outputInfo{
+                               {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
+                       },
+               },
+       },
        {
                name:    "SRAI",
                auxType: auxInt64,
index fa4208228e78cbb49c16ecf5704b04d19ee068e5..db21246446aac97922edab830d25517557aaece7 100644 (file)
@@ -2144,7 +2144,7 @@ func canRotate(c *Config, bits int64) bool {
                return false
        }
        switch c.arch {
-       case "386", "amd64", "arm64":
+       case "386", "amd64", "arm64", "riscv64":
                return true
        case "arm", "s390x", "ppc64", "ppc64le", "wasm", "loong64":
                return bits >= 32
index cf86572b8d67000ec472d1ee6200e430c258ea82..9b816760017b6beff650aff8b0bd471c47e74711 100644 (file)
@@ -536,6 +536,8 @@ func rewriteValueRISCV64(v *Value) bool {
                return rewriteValueRISCV64_OpRISCV64SLL(v)
        case OpRISCV64SLLI:
                return rewriteValueRISCV64_OpRISCV64SLLI(v)
+       case OpRISCV64SLLW:
+               return rewriteValueRISCV64_OpRISCV64SLLW(v)
        case OpRISCV64SLT:
                return rewriteValueRISCV64_OpRISCV64SLT(v)
        case OpRISCV64SLTI:
@@ -6070,6 +6072,24 @@ func rewriteValueRISCV64_OpRISCV64SLLI(v *Value) bool {
        }
        return false
 }
+func rewriteValueRISCV64_OpRISCV64SLLW(v *Value) bool {
+       v_1 := v.Args[1]
+       v_0 := v.Args[0]
+       // match: (SLLW x (MOVDconst [val]))
+       // result: (SLLIW [int64(val&31)] x)
+       for {
+               x := v_0
+               if v_1.Op != OpRISCV64MOVDconst {
+                       break
+               }
+               val := auxIntToInt64(v_1.AuxInt)
+               v.reset(OpRISCV64SLLIW)
+               v.AuxInt = int64ToAuxInt(int64(val & 31))
+               v.AddArg(x)
+               return true
+       }
+       return false
+}
 func rewriteValueRISCV64_OpRISCV64SLT(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
@@ -6644,112 +6664,102 @@ func rewriteValueRISCV64_OpRotateLeft16(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
        typ := &b.Func.Config.Types
-       // match: (RotateLeft16 <t> x (MOVDconst [c]))
-       // result: (Or16 (Lsh16x64 <t> x (MOVDconst [c&15])) (Rsh16Ux64 <t> x (MOVDconst [-c&15])))
+       // match: (RotateLeft16 <t> x y)
+       // result: (OR (SLL <t> x (ANDI [15] <y.Type> y)) (SRL <t> (ZeroExt16to64 x) (ANDI [15] <y.Type> (NEG <y.Type> y))))
        for {
                t := v.Type
                x := v_0
-               if v_1.Op != OpRISCV64MOVDconst {
-                       break
-               }
-               c := auxIntToInt64(v_1.AuxInt)
-               v.reset(OpOr16)
-               v0 := b.NewValue0(v.Pos, OpLsh16x64, t)
-               v1 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
-               v1.AuxInt = int64ToAuxInt(c & 15)
+               y := v_1
+               v.reset(OpRISCV64OR)
+               v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+               v1 := b.NewValue0(v.Pos, OpRISCV64ANDI, y.Type)
+               v1.AuxInt = int64ToAuxInt(15)
+               v1.AddArg(y)
                v0.AddArg2(x, v1)
-               v2 := b.NewValue0(v.Pos, OpRsh16Ux64, t)
-               v3 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
-               v3.AuxInt = int64ToAuxInt(-c & 15)
-               v2.AddArg2(x, v3)
+               v2 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+               v3 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
+               v3.AddArg(x)
+               v4 := b.NewValue0(v.Pos, OpRISCV64ANDI, y.Type)
+               v4.AuxInt = int64ToAuxInt(15)
+               v5 := b.NewValue0(v.Pos, OpRISCV64NEG, y.Type)
+               v5.AddArg(y)
+               v4.AddArg(v5)
+               v2.AddArg2(v3, v4)
                v.AddArg2(v0, v2)
                return true
        }
-       return false
 }
 func rewriteValueRISCV64_OpRotateLeft32(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
        b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (RotateLeft32 <t> x (MOVDconst [c]))
-       // result: (Or32 (Lsh32x64 <t> x (MOVDconst [c&31])) (Rsh32Ux64 <t> x (MOVDconst [-c&31])))
+       // match: (RotateLeft32 <t> x y)
+       // result: (OR (SLLW <t> x y) (SRLW <t> x (NEG <y.Type> y)))
        for {
                t := v.Type
                x := v_0
-               if v_1.Op != OpRISCV64MOVDconst {
-                       break
-               }
-               c := auxIntToInt64(v_1.AuxInt)
-               v.reset(OpOr32)
-               v0 := b.NewValue0(v.Pos, OpLsh32x64, t)
-               v1 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
-               v1.AuxInt = int64ToAuxInt(c & 31)
-               v0.AddArg2(x, v1)
-               v2 := b.NewValue0(v.Pos, OpRsh32Ux64, t)
-               v3 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
-               v3.AuxInt = int64ToAuxInt(-c & 31)
-               v2.AddArg2(x, v3)
-               v.AddArg2(v0, v2)
+               y := v_1
+               v.reset(OpRISCV64OR)
+               v0 := b.NewValue0(v.Pos, OpRISCV64SLLW, t)
+               v0.AddArg2(x, y)
+               v1 := b.NewValue0(v.Pos, OpRISCV64SRLW, t)
+               v2 := b.NewValue0(v.Pos, OpRISCV64NEG, y.Type)
+               v2.AddArg(y)
+               v1.AddArg2(x, v2)
+               v.AddArg2(v0, v1)
                return true
        }
-       return false
 }
 func rewriteValueRISCV64_OpRotateLeft64(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
        b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (RotateLeft64 <t> x (MOVDconst [c]))
-       // result: (Or64 (Lsh64x64 <t> x (MOVDconst [c&63])) (Rsh64Ux64 <t> x (MOVDconst [-c&63])))
+       // match: (RotateLeft64 <t> x y)
+       // result: (OR (SLL <t> x y) (SRL <t> x (NEG <y.Type> y)))
        for {
                t := v.Type
                x := v_0
-               if v_1.Op != OpRISCV64MOVDconst {
-                       break
-               }
-               c := auxIntToInt64(v_1.AuxInt)
-               v.reset(OpOr64)
-               v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
-               v1 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
-               v1.AuxInt = int64ToAuxInt(c & 63)
-               v0.AddArg2(x, v1)
-               v2 := b.NewValue0(v.Pos, OpRsh64Ux64, t)
-               v3 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
-               v3.AuxInt = int64ToAuxInt(-c & 63)
-               v2.AddArg2(x, v3)
-               v.AddArg2(v0, v2)
+               y := v_1
+               v.reset(OpRISCV64OR)
+               v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+               v0.AddArg2(x, y)
+               v1 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+               v2 := b.NewValue0(v.Pos, OpRISCV64NEG, y.Type)
+               v2.AddArg(y)
+               v1.AddArg2(x, v2)
+               v.AddArg2(v0, v1)
                return true
        }
-       return false
 }
 func rewriteValueRISCV64_OpRotateLeft8(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
        b := v.Block
        typ := &b.Func.Config.Types
-       // match: (RotateLeft8 <t> x (MOVDconst [c]))
-       // result: (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
+       // match: (RotateLeft8 <t> x y)
+       // result: (OR (SLL <t> x (ANDI [7] <y.Type> y)) (SRL <t> (ZeroExt8to64 x) (ANDI [7] <y.Type> (NEG <y.Type> y))))
        for {
                t := v.Type
                x := v_0
-               if v_1.Op != OpRISCV64MOVDconst {
-                       break
-               }
-               c := auxIntToInt64(v_1.AuxInt)
-               v.reset(OpOr8)
-               v0 := b.NewValue0(v.Pos, OpLsh8x64, t)
-               v1 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
-               v1.AuxInt = int64ToAuxInt(c & 7)
+               y := v_1
+               v.reset(OpRISCV64OR)
+               v0 := b.NewValue0(v.Pos, OpRISCV64SLL, t)
+               v1 := b.NewValue0(v.Pos, OpRISCV64ANDI, y.Type)
+               v1.AuxInt = int64ToAuxInt(7)
+               v1.AddArg(y)
                v0.AddArg2(x, v1)
-               v2 := b.NewValue0(v.Pos, OpRsh8Ux64, t)
-               v3 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
-               v3.AuxInt = int64ToAuxInt(-c & 7)
-               v2.AddArg2(x, v3)
+               v2 := b.NewValue0(v.Pos, OpRISCV64SRL, t)
+               v3 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
+               v3.AddArg(x)
+               v4 := b.NewValue0(v.Pos, OpRISCV64ANDI, y.Type)
+               v4.AuxInt = int64ToAuxInt(7)
+               v5 := b.NewValue0(v.Pos, OpRISCV64NEG, y.Type)
+               v5.AddArg(y)
+               v4.AddArg(v5)
+               v2.AddArg2(v3, v4)
                v.AddArg2(v0, v2)
                return true
        }
-       return false
 }
 func rewriteValueRISCV64_OpRsh16Ux16(v *Value) bool {
        v_1 := v.Args[1]
index 060be3dc25bd3eb29a48ab5b14b12538e791edd6..6544c469bfec6d81282b2f08e8d3df0580244306 100644 (file)
@@ -4894,22 +4894,22 @@ func InitTables() {
                func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
                        return s.newValue2(ssa.OpRotateLeft8, types.Types[types.TUINT8], args[0], args[1])
                },
-               sys.AMD64)
+               sys.AMD64, sys.RISCV64)
        addF("math/bits", "RotateLeft16",
                func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
                        return s.newValue2(ssa.OpRotateLeft16, types.Types[types.TUINT16], args[0], args[1])
                },
-               sys.AMD64)
+               sys.AMD64, sys.RISCV64)
        addF("math/bits", "RotateLeft32",
                func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
                        return s.newValue2(ssa.OpRotateLeft32, types.Types[types.TUINT32], args[0], args[1])
                },
-               sys.AMD64, sys.ARM, sys.ARM64, sys.S390X, sys.PPC64, sys.Wasm, sys.Loong64)
+               sys.AMD64, sys.ARM, sys.ARM64, sys.Loong64, sys.PPC64, sys.RISCV64, sys.S390X, sys.Wasm)
        addF("math/bits", "RotateLeft64",
                func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
                        return s.newValue2(ssa.OpRotateLeft64, types.Types[types.TUINT64], args[0], args[1])
                },
-               sys.AMD64, sys.ARM64, sys.S390X, sys.PPC64, sys.Wasm, sys.Loong64)
+               sys.AMD64, sys.ARM64, sys.Loong64, sys.PPC64, sys.RISCV64, sys.S390X, sys.Wasm)
        alias("math/bits", "RotateLeft", "math/bits", "RotateLeft64", p8...)
 
        makeOnesCountAMD64 := func(op ssa.Op) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
index 5495f86b792284b5b8fb587c5f89daaabf30bcb6..109e55763c16d07db5026bbbdbcd78fc9a057d37 100644 (file)
@@ -18,6 +18,7 @@ func rot64(x uint64) uint64 {
        // amd64:"ROLQ\t[$]7"
        // ppc64x:"ROTL\t[$]7"
        // loong64: "ROTRV\t[$]57"
+       // riscv64: "OR","SLLI","SRLI",-"AND"
        a += x<<7 | x>>57
 
        // amd64:"ROLQ\t[$]8"
@@ -25,6 +26,7 @@ func rot64(x uint64) uint64 {
        // s390x:"RISBGZ\t[$]0, [$]63, [$]8, "
        // ppc64x:"ROTL\t[$]8"
        // loong64: "ROTRV\t[$]56"
+       // riscv64: "OR","SLLI","SRLI",-"AND"
        a += x<<8 + x>>56
 
        // amd64:"ROLQ\t[$]9"
@@ -32,6 +34,7 @@ func rot64(x uint64) uint64 {
        // s390x:"RISBGZ\t[$]0, [$]63, [$]9, "
        // ppc64x:"ROTL\t[$]9"
        // loong64: "ROTRV\t[$]55"
+       // riscv64: "OR","SLLI","SRLI",-"AND"
        a += x<<9 ^ x>>55
 
        // amd64:"ROLQ\t[$]10"
@@ -41,6 +44,7 @@ func rot64(x uint64) uint64 {
        // arm64:"ROR\t[$]54"
        // s390x:"RISBGZ\t[$]0, [$]63, [$]10, "
        // loong64: "ROTRV\t[$]54"
+       // riscv64: "OR","SLLI","SRLI",-"AND"
        a += bits.RotateLeft64(x, 10)
 
        return a
@@ -53,6 +57,7 @@ func rot32(x uint32) uint32 {
        // arm:"MOVW\tR\\d+@>25"
        // ppc64x:"ROTLW\t[$]7"
        // loong64: "ROTR\t[$]25"
+       // riscv64: "OR","SLLIW","SRLIW",-"AND"
        a += x<<7 | x>>25
 
        // amd64:`ROLL\t[$]8`
@@ -61,6 +66,7 @@ func rot32(x uint32) uint32 {
        // s390x:"RLL\t[$]8"
        // ppc64x:"ROTLW\t[$]8"
        // loong64: "ROTR\t[$]24"
+       // riscv64: "OR","SLLIW","SRLIW",-"AND"
        a += x<<8 + x>>24
 
        // amd64:"ROLL\t[$]9"
@@ -69,6 +75,7 @@ func rot32(x uint32) uint32 {
        // s390x:"RLL\t[$]9"
        // ppc64x:"ROTLW\t[$]9"
        // loong64: "ROTR\t[$]23"
+       // riscv64: "OR","SLLIW","SRLIW",-"AND"
        a += x<<9 ^ x>>23
 
        // amd64:"ROLL\t[$]10"
@@ -79,6 +86,7 @@ func rot32(x uint32) uint32 {
        // arm64:"RORW\t[$]22"
        // s390x:"RLL\t[$]10"
        // loong64: "ROTR\t[$]22"
+       // riscv64: "OR","SLLIW","SRLIW",-"AND"
        a += bits.RotateLeft32(x, 10)
 
        return a
@@ -88,12 +96,15 @@ func rot16(x uint16) uint16 {
        var a uint16
 
        // amd64:"ROLW\t[$]7"
+       // riscv64: "OR","SLLI","SRLI",-"AND"
        a += x<<7 | x>>9
 
        // amd64:`ROLW\t[$]8`
+       // riscv64: "OR","SLLI","SRLI",-"AND"
        a += x<<8 + x>>8
 
        // amd64:"ROLW\t[$]9"
+       // riscv64: "OR","SLLI","SRLI",-"AND"
        a += x<<9 ^ x>>7
 
        return a
@@ -103,12 +114,15 @@ func rot8(x uint8) uint8 {
        var a uint8
 
        // amd64:"ROLB\t[$]5"
+       // riscv64: "OR","SLLI","SRLI",-"AND"
        a += x<<5 | x>>3
 
        // amd64:`ROLB\t[$]6`
+       // riscv64: "OR","SLLI","SRLI",-"AND"
        a += x<<6 + x>>2
 
        // amd64:"ROLB\t[$]7"
+       // riscv64: "OR","SLLI","SRLI",-"AND"
        a += x<<7 ^ x>>1
 
        return a
@@ -127,12 +141,14 @@ func rot64nc(x uint64, z uint) uint64 {
        // arm64:"ROR","NEG",-"AND"
        // ppc64x:"ROTL",-"NEG",-"AND"
        // loong64: "ROTRV", -"AND"
+       // riscv64: "OR","SLL","SRL",-"AND"
        a += x<<z | x>>(64-z)
 
        // amd64:"RORQ",-"AND"
        // arm64:"ROR",-"NEG",-"AND"
        // ppc64x:"ROTL","NEG",-"AND"
        // loong64: "ROTRV", -"AND"
+       // riscv64: "OR","SLL","SRL",-"AND"
        a += x>>z | x<<(64-z)
 
        return a
@@ -147,12 +163,14 @@ func rot32nc(x uint32, z uint) uint32 {
        // arm64:"ROR","NEG",-"AND"
        // ppc64x:"ROTLW",-"NEG",-"AND"
        // loong64: "ROTR", -"AND"
+       // riscv64: "OR","SLLW","SRLW",-"AND"
        a += x<<z | x>>(32-z)
 
        // amd64:"RORL",-"AND"
        // arm64:"ROR",-"NEG",-"AND"
        // ppc64x:"ROTLW","NEG",-"AND"
        // loong64: "ROTR", -"AND"
+       // riscv64: "OR","SLLW","SRLW",-"AND"
        a += x>>z | x<<(32-z)
 
        return a
@@ -164,9 +182,11 @@ func rot16nc(x uint16, z uint) uint16 {
        z &= 15
 
        // amd64:"ROLW",-"ANDQ"
+       // riscv64: "OR","SLL","SRL",-"AND\t"
        a += x<<z | x>>(16-z)
 
        // amd64:"RORW",-"ANDQ"
+       // riscv64: "OR","SLL","SRL",-"AND\t"
        a += x>>z | x<<(16-z)
 
        return a
@@ -178,9 +198,11 @@ func rot8nc(x uint8, z uint) uint8 {
        z &= 7
 
        // amd64:"ROLB",-"ANDQ"
+       // riscv64: "OR","SLL","SRL",-"AND\t"
        a += x<<z | x>>(8-z)
 
        // amd64:"RORB",-"ANDQ"
+       // riscv64: "OR","SLL","SRL",-"AND\t"
        a += x>>z | x<<(8-z)
 
        return a