ssa.OpLOONG64SLLV,
ssa.OpLOONG64SRLV,
ssa.OpLOONG64SRAV,
+ ssa.OpLOONG64ROTR,
+ ssa.OpLOONG64ROTRV,
ssa.OpLOONG64ADDF,
ssa.OpLOONG64ADDD,
ssa.OpLOONG64SUBF,
ssa.OpLOONG64SLLVconst,
ssa.OpLOONG64SRLVconst,
ssa.OpLOONG64SRAVconst,
+ ssa.OpLOONG64ROTRconst,
+ ssa.OpLOONG64ROTRVconst,
ssa.OpLOONG64SGTconst,
ssa.OpLOONG64SGTUconst:
p := s.Prog(v.Op.Asm())
// rotates
(RotateLeft8 <t> x (MOVVconst [c])) => (Or8 (Lsh8x64 <t> x (MOVVconst [c&7])) (Rsh8Ux64 <t> x (MOVVconst [-c&7])))
(RotateLeft16 <t> x (MOVVconst [c])) => (Or16 (Lsh16x64 <t> x (MOVVconst [c&15])) (Rsh16Ux64 <t> x (MOVVconst [-c&15])))
-(RotateLeft32 <t> x (MOVVconst [c])) => (Or32 (Lsh32x64 <t> x (MOVVconst [c&31])) (Rsh32Ux64 <t> x (MOVVconst [-c&31])))
-(RotateLeft64 <t> x (MOVVconst [c])) => (Or64 (Lsh64x64 <t> x (MOVVconst [c&63])) (Rsh64Ux64 <t> x (MOVVconst [-c&63])))
+(RotateLeft32 x y) => (ROTR x (NEGV <y.Type> y))
+(RotateLeft64 x y) => (ROTRV x (NEGV <y.Type> y))
// unary ops
(Neg(64|32|16|8) ...) => (NEGV ...)
(SLLV x (MOVVconst [c])) => (SLLVconst x [c])
(SRLV x (MOVVconst [c])) => (SRLVconst x [c])
(SRAV x (MOVVconst [c])) => (SRAVconst x [c])
+(ROTR x (MOVVconst [c])) => (ROTRconst x [c&31])
+(ROTRV x (MOVVconst [c])) => (ROTRVconst x [c&63])
(SGT (MOVVconst [c]) x) && is32Bit(c) => (SGTconst [c] x)
(SGTU (MOVVconst [c]) x) && is32Bit(c) => (SGTUconst [c] x)
{name: "SQRTF", argLength: 1, reg: fp11, asm: "SQRTF"}, // sqrt(arg0), float32
// shifts
- {name: "SLLV", argLength: 2, reg: gp21, asm: "SLLV"}, // arg0 << arg1, shift amount is mod 64
- {name: "SLLVconst", argLength: 1, reg: gp11, asm: "SLLV", aux: "Int64"}, // arg0 << auxInt
- {name: "SRLV", argLength: 2, reg: gp21, asm: "SRLV"}, // arg0 >> arg1, unsigned, shift amount is mod 64
- {name: "SRLVconst", argLength: 1, reg: gp11, asm: "SRLV", aux: "Int64"}, // arg0 >> auxInt, unsigned
- {name: "SRAV", argLength: 2, reg: gp21, asm: "SRAV"}, // arg0 >> arg1, signed, shift amount is mod 64
- {name: "SRAVconst", argLength: 1, reg: gp11, asm: "SRAV", aux: "Int64"}, // arg0 >> auxInt, signed
+ {name: "SLLV", argLength: 2, reg: gp21, asm: "SLLV"}, // arg0 << arg1, shift amount is mod 64
+ {name: "SLLVconst", argLength: 1, reg: gp11, asm: "SLLV", aux: "Int64"}, // arg0 << auxInt
+ {name: "SRLV", argLength: 2, reg: gp21, asm: "SRLV"}, // arg0 >> arg1, unsigned, shift amount is mod 64
+ {name: "SRLVconst", argLength: 1, reg: gp11, asm: "SRLV", aux: "Int64"}, // arg0 >> auxInt, unsigned
+ {name: "SRAV", argLength: 2, reg: gp21, asm: "SRAV"}, // arg0 >> arg1, signed, shift amount is mod 64
+ {name: "SRAVconst", argLength: 1, reg: gp11, asm: "SRAV", aux: "Int64"}, // arg0 >> auxInt, signed
+ {name: "ROTR", argLength: 2, reg: gp21, asm: "ROTR"}, // arg0 right rotate by (arg1 mod 32) bits
+ {name: "ROTRV", argLength: 2, reg: gp21, asm: "ROTRV"}, // arg0 right rotate by (arg1 mod 64) bits
+ {name: "ROTRconst", argLength: 1, reg: gp11, asm: "ROTR", aux: "Int64"}, // uint32(arg0) right rotate by auxInt bits, auxInt should be in the range 0 to 31.
+ {name: "ROTRVconst", argLength: 1, reg: gp11, asm: "ROTRV", aux: "Int64"}, // arg0 right rotate by auxInt bits, auxInt should be in the range 0 to 63.
// comparisons
{name: "SGT", argLength: 2, reg: gp21, asm: "SGT", typ: "Bool"}, // 1 if arg0 > arg1 (signed), 0 otherwise
OpLOONG64SRLVconst
OpLOONG64SRAV
OpLOONG64SRAVconst
+ OpLOONG64ROTR
+ OpLOONG64ROTRV
+ OpLOONG64ROTRconst
+ OpLOONG64ROTRVconst
OpLOONG64SGT
OpLOONG64SGTconst
OpLOONG64SGTU
},
},
},
+ {
+ name: "ROTR",
+ argLen: 2,
+ asm: loong64.AROTR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+ {1, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ outputs: []outputInfo{
+ {0, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ },
+ },
+ {
+ name: "ROTRV",
+ argLen: 2,
+ asm: loong64.AROTRV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+ {1, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ outputs: []outputInfo{
+ {0, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ },
+ },
+ {
+ name: "ROTRconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: loong64.AROTR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ outputs: []outputInfo{
+ {0, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ },
+ },
+ {
+ name: "ROTRVconst",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: loong64.AROTRV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ outputs: []outputInfo{
+ {0, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ },
+ },
{
name: "SGT",
argLen: 2,
switch c.arch {
case "386", "amd64":
return true
- case "arm", "arm64", "s390x", "ppc64", "ppc64le", "wasm":
+ case "arm", "arm64", "s390x", "ppc64", "ppc64le", "wasm", "loong64":
return bits >= 32
default:
return false
return rewriteValueLOONG64_OpLOONG64OR(v)
case OpLOONG64ORconst:
return rewriteValueLOONG64_OpLOONG64ORconst(v)
+ case OpLOONG64ROTR:
+ return rewriteValueLOONG64_OpLOONG64ROTR(v)
+ case OpLOONG64ROTRV:
+ return rewriteValueLOONG64_OpLOONG64ROTRV(v)
case OpLOONG64SGT:
return rewriteValueLOONG64_OpLOONG64SGT(v)
case OpLOONG64SGTU:
}
return false
}
+func rewriteValueLOONG64_OpLOONG64ROTR(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ROTR x (MOVVconst [c]))
+ // result: (ROTRconst x [c&31])
+ for {
+ x := v_0
+ if v_1.Op != OpLOONG64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpLOONG64ROTRconst)
+ v.AuxInt = int64ToAuxInt(c & 31)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueLOONG64_OpLOONG64ROTRV(v *Value) bool {
+ v_1 := v.Args[1]
+ v_0 := v.Args[0]
+ // match: (ROTRV x (MOVVconst [c]))
+ // result: (ROTRVconst x [c&63])
+ for {
+ x := v_0
+ if v_1.Op != OpLOONG64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_1.AuxInt)
+ v.reset(OpLOONG64ROTRVconst)
+ v.AuxInt = int64ToAuxInt(c & 63)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
func rewriteValueLOONG64_OpLOONG64SGT(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
- typ := &b.Func.Config.Types
- // match: (RotateLeft32 <t> x (MOVVconst [c]))
- // result: (Or32 (Lsh32x64 <t> x (MOVVconst [c&31])) (Rsh32Ux64 <t> x (MOVVconst [-c&31])))
+ // match: (RotateLeft32 x y)
+ // result: (ROTR x (NEGV <y.Type> y))
for {
- t := v.Type
x := v_0
- if v_1.Op != OpLOONG64MOVVconst {
- break
- }
- c := auxIntToInt64(v_1.AuxInt)
- v.reset(OpOr32)
- v0 := b.NewValue0(v.Pos, OpLsh32x64, t)
- v1 := b.NewValue0(v.Pos, OpLOONG64MOVVconst, typ.UInt64)
- v1.AuxInt = int64ToAuxInt(c & 31)
- v0.AddArg2(x, v1)
- v2 := b.NewValue0(v.Pos, OpRsh32Ux64, t)
- v3 := b.NewValue0(v.Pos, OpLOONG64MOVVconst, typ.UInt64)
- v3.AuxInt = int64ToAuxInt(-c & 31)
- v2.AddArg2(x, v3)
- v.AddArg2(v0, v2)
+ y := v_1
+ v.reset(OpLOONG64ROTR)
+ v0 := b.NewValue0(v.Pos, OpLOONG64NEGV, y.Type)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
return true
}
- return false
}
func rewriteValueLOONG64_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 (MOVVconst [c]))
- // result: (Or64 (Lsh64x64 <t> x (MOVVconst [c&63])) (Rsh64Ux64 <t> x (MOVVconst [-c&63])))
+ // match: (RotateLeft64 x y)
+ // result: (ROTRV x (NEGV <y.Type> y))
for {
- t := v.Type
x := v_0
- if v_1.Op != OpLOONG64MOVVconst {
- break
- }
- c := auxIntToInt64(v_1.AuxInt)
- v.reset(OpOr64)
- v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
- v1 := b.NewValue0(v.Pos, OpLOONG64MOVVconst, typ.UInt64)
- v1.AuxInt = int64ToAuxInt(c & 63)
- v0.AddArg2(x, v1)
- v2 := b.NewValue0(v.Pos, OpRsh64Ux64, t)
- v3 := b.NewValue0(v.Pos, OpLOONG64MOVVconst, typ.UInt64)
- v3.AuxInt = int64ToAuxInt(-c & 63)
- v2.AddArg2(x, v3)
- v.AddArg2(v0, v2)
+ y := v_1
+ v.reset(OpLOONG64ROTRV)
+ v0 := b.NewValue0(v.Pos, OpLOONG64NEGV, y.Type)
+ v0.AddArg(y)
+ v.AddArg2(x, v0)
return true
}
- return false
}
func rewriteValueLOONG64_OpRotateLeft8(v *Value) bool {
v_1 := v.Args[1]
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.AMD64, sys.ARM, sys.ARM64, sys.S390X, sys.PPC64, sys.Wasm, sys.Loong64)
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.AMD64, sys.ARM64, sys.S390X, sys.PPC64, sys.Wasm, sys.Loong64)
alias("math/bits", "RotateLeft", "math/bits", "RotateLeft64", p8...)
makeOnesCountAMD64 := func(op ssa.Op) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
// amd64:"ROLQ\t[$]7"
// ppc64:"ROTL\t[$]7"
// ppc64le:"ROTL\t[$]7"
+ // loong64: "ROTRV\t[$]57"
a += x<<7 | x>>57
// amd64:"ROLQ\t[$]8"
// s390x:"RISBGZ\t[$]0, [$]63, [$]8, "
// ppc64:"ROTL\t[$]8"
// ppc64le:"ROTL\t[$]8"
+ // loong64: "ROTRV\t[$]56"
a += x<<8 + x>>56
// amd64:"ROLQ\t[$]9"
// s390x:"RISBGZ\t[$]0, [$]63, [$]9, "
// ppc64:"ROTL\t[$]9"
// ppc64le:"ROTL\t[$]9"
+ // loong64: "ROTRV\t[$]55"
a += x<<9 ^ x>>55
// amd64:"ROLQ\t[$]10"
// ppc64le:"ROTL\t[$]10"
// arm64:"ROR\t[$]54"
// s390x:"RISBGZ\t[$]0, [$]63, [$]10, "
+ // loong64: "ROTRV\t[$]54"
a += bits.RotateLeft64(x, 10)
return a
// arm:"MOVW\tR\\d+@>25"
// ppc64:"ROTLW\t[$]7"
// ppc64le:"ROTLW\t[$]7"
+ // loong64: "ROTR\t[$]25"
a += x<<7 | x>>25
// amd64:`ROLL\t[$]8`
// s390x:"RLL\t[$]8"
// ppc64:"ROTLW\t[$]8"
// ppc64le:"ROTLW\t[$]8"
+ // loong64: "ROTR\t[$]24"
a += x<<8 + x>>24
// amd64:"ROLL\t[$]9"
// s390x:"RLL\t[$]9"
// ppc64:"ROTLW\t[$]9"
// ppc64le:"ROTLW\t[$]9"
+ // loong64: "ROTR\t[$]23"
a += x<<9 ^ x>>23
// amd64:"ROLL\t[$]10"
// ppc64le:"ROTLW\t[$]10"
// arm64:"RORW\t[$]22"
// s390x:"RLL\t[$]10"
+ // loong64: "ROTR\t[$]22"
a += bits.RotateLeft32(x, 10)
return a
// arm64:"ROR","NEG",-"AND"
// ppc64:"ROTL",-"NEG",-"AND"
// ppc64le:"ROTL",-"NEG",-"AND"
+ // loong64: "ROTRV", -"AND"
a += x<<z | x>>(64-z)
// amd64:"RORQ",-"AND"
// arm64:"ROR",-"NEG",-"AND"
// ppc64:"ROTL","NEG",-"AND"
// ppc64le:"ROTL","NEG",-"AND"
+ // loong64: "ROTRV", -"AND"
a += x>>z | x<<(64-z)
return a
// arm64:"ROR","NEG",-"AND"
// ppc64:"ROTLW",-"NEG",-"AND"
// ppc64le:"ROTLW",-"NEG",-"AND"
+ // loong64: "ROTR", -"AND"
a += x<<z | x>>(32-z)
// amd64:"RORL",-"AND"
// arm64:"ROR",-"NEG",-"AND"
// ppc64:"ROTLW","NEG",-"AND"
// ppc64le:"ROTLW","NEG",-"AND"
+ // loong64: "ROTR", -"AND"
a += x>>z | x<<(32-z)
return a