ssa.OpLOONG64MOVVgpfp,
ssa.OpLOONG64NEGF,
ssa.OpLOONG64NEGD,
+ ssa.OpLOONG64CLZW,
+ ssa.OpLOONG64CLZV,
ssa.OpLOONG64SQRTD,
ssa.OpLOONG64SQRTF,
ssa.OpLOONG64ABSD:
(Com(64|32|16|8) x) => (NOR (MOVVconst [0]) x)
+(BitLen64 <t> x) => (NEGV <t> (SUBVconst <t> [64] (CLZV <t> x)))
+(BitLen32 <t> x) => (NEGV <t> (SUBVconst <t> [32] (CLZW <t> x)))
+
// math package intrinsics
(Sqrt ...) => (SQRTD ...)
(Sqrt32 ...) => (SQRTF ...)
(CondSelect <t> x y cond) => (OR (MASKEQZ <t> x cond) (MASKNEZ <t> y cond))
+// c > d-x => x > d-c
+(SGT (MOVVconst [c]) (NEGV (SUBVconst [d] x))) && is32Bit(d-c) => (SGT x (MOVVconst [d-c]))
+
(SGT (MOVVconst [c]) x) && is32Bit(c) => (SGTconst [c] x)
(SGTU (MOVVconst [c]) x) && is32Bit(c) => (SGTUconst [c] x)
(SUBVconst [c] (MOVVconst [d])) => (MOVVconst [d-c])
(SUBVconst [c] (SUBVconst [d] x)) && is32Bit(-c-d) => (ADDVconst [-c-d] x)
(SUBVconst [c] (ADDVconst [d] x)) && is32Bit(-c+d) => (ADDVconst [-c+d] x)
+(SUBV (MOVVconst [c]) (NEGV (SUBVconst [d] x))) => (ADDVconst [c-d] x)
(SLLVconst [c] (MOVVconst [d])) => (MOVVconst [d<<uint64(c)])
(SRLVconst [c] (MOVVconst [d])) => (MOVVconst [int64(uint64(d)>>uint64(c))])
(SRAVconst [c] (MOVVconst [d])) => (MOVVconst [d>>uint64(c)])
{name: "SQRTD", argLength: 1, reg: fp11, asm: "SQRTD"}, // sqrt(arg0), float64
{name: "SQRTF", argLength: 1, reg: fp11, asm: "SQRTF"}, // sqrt(arg0), float32
+ {name: "CLZW", argLength: 1, reg: gp11, asm: "CLZW"}, // Count leading (high order) zeroes (returns 0-32)
+ {name: "CLZV", argLength: 1, reg: gp11, asm: "CLZV"}, // Count leading (high order) zeroes (returns 0-64)
+
{name: "FMINF", argLength: 2, reg: fp21, resultNotInArgs: true, asm: "FMINF", commutative: true, typ: "Float32"}, // min(arg0, arg1), float32
{name: "FMIND", argLength: 2, reg: fp21, resultNotInArgs: true, asm: "FMIND", commutative: true, typ: "Float64"}, // min(arg0, arg1), float64
{name: "FMAXF", argLength: 2, reg: fp21, resultNotInArgs: true, asm: "FMAXF", commutative: true, typ: "Float32"}, // max(arg0, arg1), float32
OpLOONG64NEGD
OpLOONG64SQRTD
OpLOONG64SQRTF
+ OpLOONG64CLZW
+ OpLOONG64CLZV
OpLOONG64FMINF
OpLOONG64FMIND
OpLOONG64FMAXF
},
},
},
+ {
+ name: "CLZW",
+ argLen: 1,
+ asm: loong64.ACLZW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ outputs: []outputInfo{
+ {0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ },
+ },
+ {
+ name: "CLZV",
+ argLen: 1,
+ asm: loong64.ACLZV,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ outputs: []outputInfo{
+ {0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
+ },
+ },
+ },
{
name: "FMINF",
argLen: 2,
return true
case OpAvg64u:
return rewriteValueLOONG64_OpAvg64u(v)
+ case OpBitLen32:
+ return rewriteValueLOONG64_OpBitLen32(v)
+ case OpBitLen64:
+ return rewriteValueLOONG64_OpBitLen64(v)
case OpClosureCall:
v.Op = OpLOONG64CALLclosure
return true
return true
}
}
+func rewriteValueLOONG64_OpBitLen32(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (BitLen32 <t> x)
+ // result: (NEGV <t> (SUBVconst <t> [32] (CLZW <t> x)))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpLOONG64NEGV)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpLOONG64SUBVconst, t)
+ v0.AuxInt = int64ToAuxInt(32)
+ v1 := b.NewValue0(v.Pos, OpLOONG64CLZW, t)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueLOONG64_OpBitLen64(v *Value) bool {
+ v_0 := v.Args[0]
+ b := v.Block
+ // match: (BitLen64 <t> x)
+ // result: (NEGV <t> (SUBVconst <t> [64] (CLZV <t> x)))
+ for {
+ t := v.Type
+ x := v_0
+ v.reset(OpLOONG64NEGV)
+ v.Type = t
+ v0 := b.NewValue0(v.Pos, OpLOONG64SUBVconst, t)
+ v0.AuxInt = int64ToAuxInt(64)
+ v1 := b.NewValue0(v.Pos, OpLOONG64CLZV, t)
+ v1.AddArg(x)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ return true
+ }
+}
func rewriteValueLOONG64_OpCom16(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
func rewriteValueLOONG64_OpLOONG64SGT(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
+ // match: (SGT (MOVVconst [c]) (NEGV (SUBVconst [d] x)))
+ // cond: is32Bit(d-c)
+ // result: (SGT x (MOVVconst [d-c]))
+ for {
+ if v_0.Op != OpLOONG64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpLOONG64NEGV {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpLOONG64SUBVconst {
+ break
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_0.Args[0]
+ if !(is32Bit(d - c)) {
+ break
+ }
+ v.reset(OpLOONG64SGT)
+ v0 := b.NewValue0(v.Pos, OpLOONG64MOVVconst, typ.UInt64)
+ v0.AuxInt = int64ToAuxInt(d - c)
+ v.AddArg2(x, v0)
+ return true
+ }
// match: (SGT (MOVVconst [c]) x)
// cond: is32Bit(c)
// result: (SGTconst [c] x)
v.AddArg(x)
return true
}
+ // match: (SUBV (MOVVconst [c]) (NEGV (SUBVconst [d] x)))
+ // result: (ADDVconst [c-d] x)
+ for {
+ if v_0.Op != OpLOONG64MOVVconst {
+ break
+ }
+ c := auxIntToInt64(v_0.AuxInt)
+ if v_1.Op != OpLOONG64NEGV {
+ break
+ }
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpLOONG64SUBVconst {
+ break
+ }
+ d := auxIntToInt64(v_1_0.AuxInt)
+ x := v_1_0.Args[0]
+ v.reset(OpLOONG64ADDVconst)
+ v.AuxInt = int64ToAuxInt(c - d)
+ v.AddArg(x)
+ return true
+ }
return false
}
func rewriteValueLOONG64_OpLOONG64SUBVconst(v *Value) bool {
func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], args[0])
},
- sys.AMD64, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
+ sys.AMD64, sys.ARM64, sys.ARM, sys.Loong64, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
addF("math/bits", "Len32",
func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], args[0])
},
- sys.AMD64, sys.ARM64, sys.PPC64)
+ sys.AMD64, sys.ARM64, sys.Loong64, sys.PPC64)
addF("math/bits", "Len32",
func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
if s.config.PtrSize == 4 {
x := s.newValue1(ssa.OpZeroExt16to64, types.Types[types.TUINT64], args[0])
return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], x)
},
- sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
+ sys.ARM64, sys.ARM, sys.Loong64, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
addF("math/bits", "Len16",
func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return s.newValue1(ssa.OpBitLen16, types.Types[types.TINT], args[0])
x := s.newValue1(ssa.OpZeroExt8to64, types.Types[types.TUINT64], args[0])
return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], x)
},
- sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
+ sys.ARM64, sys.ARM, sys.Loong64, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
addF("math/bits", "Len8",
func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return s.newValue1(ssa.OpBitLen8, types.Types[types.TINT], args[0])
}
return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], args[0])
},
- sys.AMD64, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
+ sys.AMD64, sys.ARM64, sys.ARM, sys.Loong64, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
// LeadingZeros is handled because it trivially calls Len.
addF("math/bits", "Reverse64",
func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
{"loong64", "internal/runtime/sys", "GetCallerPC"}: struct{}{},
{"loong64", "internal/runtime/sys", "GetCallerSP"}: struct{}{},
{"loong64", "internal/runtime/sys", "GetClosurePtr"}: struct{}{},
+ {"loong64", "internal/runtime/sys", "Len64"}: struct{}{},
+ {"loong64", "internal/runtime/sys", "Len8"}: struct{}{},
{"loong64", "math", "Abs"}: struct{}{},
{"loong64", "math", "Copysign"}: struct{}{},
{"loong64", "math", "sqrt"}: struct{}{},
{"loong64", "math/bits", "Add64"}: struct{}{},
{"loong64", "math/bits", "Mul"}: struct{}{},
{"loong64", "math/bits", "Mul64"}: struct{}{},
+ {"loong64", "math/bits", "Len"}: struct{}{},
+ {"loong64", "math/bits", "Len8"}: struct{}{},
+ {"loong64", "math/bits", "Len16"}: struct{}{},
+ {"loong64", "math/bits", "Len32"}: struct{}{},
+ {"loong64", "math/bits", "Len64"}: struct{}{},
{"loong64", "math/bits", "RotateLeft"}: struct{}{},
{"loong64", "math/bits", "RotateLeft32"}: struct{}{},
{"loong64", "math/bits", "RotateLeft64"}: struct{}{},
// amd64/v3:"LZCNTQ", -"BSRQ"
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
+ // loong64:"CLZV",-"SUB"
// mips:"CLZ"
// wasm:"I64Clz"
// ppc64x:"CNTLZD"
// amd64/v3:"LZCNTQ", -"BSRQ"
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
+ // loong64:"CLZV",-"SUB"
// mips:"CLZ"
// wasm:"I64Clz"
// ppc64x:"CNTLZD"
// amd64/v3: "LZCNTL",- "BSRL"
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZW"
+ // loong64:"CLZW",-"SUB"
// mips:"CLZ"
// wasm:"I64Clz"
// ppc64x:"CNTLZW"
// amd64/v3: "LZCNTL",- "BSRL"
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
+ // loong64:"CLZV"
// mips:"CLZ"
// wasm:"I64Clz"
// ppc64x:"CNTLZD"
// amd64/v3: "LZCNTL",- "BSRL"
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
+ // loong64:"CLZV"
// mips:"CLZ"
// wasm:"I64Clz"
// ppc64x:"CNTLZD"
// amd64/v3: "LZCNTQ"
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
+ // loong64:"CLZV"
// mips:"CLZ"
// wasm:"I64Clz"
// ppc64x:"SUBC","CNTLZD"
// amd64/v3: "LZCNTQ"
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
+ // loong64:"CLZV"
// mips:"CLZ"
// wasm:"I64Clz"
// ppc64x:"SUBC","CNTLZD"
}
func SubFromLen64(n uint64) int {
+ // loong64:"CLZV",-"ADD"
// ppc64x:"CNTLZD",-"SUBC"
return 64 - bits.Len64(n)
}
+func CompareWithLen64(n uint64) bool {
+ // loong64:"CLZV",-"ADD",-"[$]64",-"[$]9"
+ return bits.Len64(n) < 9
+}
+
func Len32(n uint32) int {
// amd64/v1,amd64/v2:"BSRQ","LEAQ",-"CMOVQEQ"
// amd64/v3: "LZCNTL"
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
+ // loong64:"CLZW"
// mips:"CLZ"
// wasm:"I64Clz"
// ppc64x: "CNTLZW"
// amd64/v3: "LZCNTL"
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
+ // loong64:"CLZV"
// mips:"CLZ"
// wasm:"I64Clz"
// ppc64x:"SUBC","CNTLZD"
// amd64/v3: "LZCNTL"
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
+ // loong64:"CLZV"
// mips:"CLZ"
// wasm:"I64Clz"
// ppc64x:"SUBC","CNTLZD"