cmd/compile: split DIVV/DIVVU op on loong64

Previously, we need calculate both quotient and remainder together.
However, in most cases, only one result is needed. By separating these
instructions, we can save one instruction in most cases.

Change-Id: I0a2d4167cda68ab606783ba1aa2720ede19d6b53
Reviewed-on: https://go-review.googlesource.com/c/go/+/475315
Reviewed-by: Than McIntosh <thanm@google.com>
Run-TryBot: Wayne Zuo <wdvxdr@golangcn.org>
Reviewed-by: abner chenc <chenguoqi@loongson.cn>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Wayne Zuo 2023-03-02 15:55:03 +08:00
parent df6d442c38
commit 96428e160d
5 changed files with 310 additions and 387 deletions

View File

@ -141,7 +141,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
ssa.OpLOONG64MULD,
ssa.OpLOONG64DIVF,
ssa.OpLOONG64DIVD,
ssa.OpLOONG64MULV, ssa.OpLOONG64MULHV, ssa.OpLOONG64MULHVU:
ssa.OpLOONG64MULV, ssa.OpLOONG64MULHV, ssa.OpLOONG64MULHVU,
ssa.OpLOONG64DIVV, ssa.OpLOONG64REMV, ssa.OpLOONG64DIVVU, ssa.OpLOONG64REMVU:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[1].Reg()
@ -175,32 +176,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpLOONG64DIVV:
p := s.Prog(loong64.ADIVV)
p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[1].Reg()
p.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg1()
p1 := s.Prog(loong64.AREMV)
p1.From.Type = obj.TYPE_REG
p1.From.Reg = v.Args[1].Reg()
p1.Reg = v.Args[0].Reg()
p1.To.Type = obj.TYPE_REG
p1.To.Reg = v.Reg0()
case ssa.OpLOONG64DIVVU:
p := s.Prog(loong64.ADIVVU)
p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[1].Reg()
p.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg1()
p1 := s.Prog(loong64.AREMVU)
p1.From.Type = obj.TYPE_REG
p1.From.Reg = v.Args[1].Reg()
p1.Reg = v.Args[0].Reg()
p1.To.Type = obj.TYPE_REG
p1.To.Reg = v.Reg0()
case ssa.OpLOONG64MOVVconst:
r := v.Reg()
p := s.Prog(v.Op.Asm())

View File

@ -20,24 +20,24 @@
(Hmul32 x y) => (SRAVconst (MULV (SignExt32to64 x) (SignExt32to64 y)) [32])
(Hmul32u x y) => (SRLVconst (MULV (ZeroExt32to64 x) (ZeroExt32to64 y)) [32])
(Div64 x y) => (Select1 (DIVV x y))
(Div64u x y) => (Select1 (DIVVU x y))
(Div32 x y) => (Select1 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
(Div32u x y) => (Select1 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
(Div16 x y) => (Select1 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
(Div16u x y) => (Select1 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
(Div8 x y) => (Select1 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
(Div8u x y) => (Select1 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
(Div64 x y) => (DIVV x y)
(Div64u ...) => (DIVVU ...)
(Div32 x y) => (DIVV (SignExt32to64 x) (SignExt32to64 y))
(Div32u x y) => (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y))
(Div16 x y) => (DIVV (SignExt16to64 x) (SignExt16to64 y))
(Div16u x y) => (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y))
(Div8 x y) => (DIVV (SignExt8to64 x) (SignExt8to64 y))
(Div8u x y) => (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y))
(Div(32|64)F ...) => (DIV(F|D) ...)
(Mod64 x y) => (Select0 (DIVV x y))
(Mod64u x y) => (Select0 (DIVVU x y))
(Mod32 x y) => (Select0 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
(Mod32u x y) => (Select0 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
(Mod16 x y) => (Select0 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
(Mod16u x y) => (Select0 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
(Mod8 x y) => (Select0 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
(Mod8u x y) => (Select0 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
(Mod64 x y) => (REMV x y)
(Mod64u ...) => (REMVU ...)
(Mod32 x y) => (REMV (SignExt32to64 x) (SignExt32to64 y))
(Mod32u x y) => (REMVU (ZeroExt32to64 x) (ZeroExt32to64 y))
(Mod16 x y) => (REMV (SignExt16to64 x) (SignExt16to64 y))
(Mod16u x y) => (REMVU (ZeroExt16to64 x) (ZeroExt16to64 y))
(Mod8 x y) => (REMV (SignExt8to64 x) (SignExt8to64 y))
(Mod8u x y) => (REMVU (ZeroExt8to64 x) (ZeroExt8to64 y))
(Select0 <t> (Add64carry x y c)) => (ADDV (ADDV <t> x y) c)
(Select1 <t> (Add64carry x y c)) =>
@ -598,10 +598,10 @@
(MULV x (MOVVconst [c])) && isPowerOfTwo64(c) => (SLLVconst [log64(c)] x)
// div by constant
(Select1 (DIVVU x (MOVVconst [1]))) => x
(Select1 (DIVVU x (MOVVconst [c]))) && isPowerOfTwo64(c) => (SRLVconst [log64(c)] x)
(Select0 (DIVVU _ (MOVVconst [1]))) => (MOVVconst [0]) // mod
(Select0 (DIVVU x (MOVVconst [c]))) && isPowerOfTwo64(c) => (ANDconst [c-1] x) // mod
(DIVVU x (MOVVconst [1])) => x
(DIVVU x (MOVVconst [c])) && isPowerOfTwo64(c) => (SRLVconst [log64(c)] x)
(REMVU _ (MOVVconst [1])) => (MOVVconst [0]) // mod
(REMVU x (MOVVconst [c])) && isPowerOfTwo64(c) => (ANDconst [c-1] x) // mod
// generic simplifications
(ADDV x (NEGV y)) => (SUBV x y)
@ -636,10 +636,10 @@
(SRLVconst [c] (MOVVconst [d])) => (MOVVconst [int64(uint64(d)>>uint64(c))])
(SRAVconst [c] (MOVVconst [d])) => (MOVVconst [d>>uint64(c)])
(MULV (MOVVconst [c]) (MOVVconst [d])) => (MOVVconst [c*d])
(Select1 (DIVV (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c/d])
(Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)/uint64(d))])
(Select0 (DIVV (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c%d]) // mod
(Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)%uint64(d))]) // mod
(DIVV (MOVVconst [c]) (MOVVconst [d])) && d != 0 => (MOVVconst [c/d])
(DIVVU (MOVVconst [c]) (MOVVconst [d])) && d != 0 => (MOVVconst [int64(uint64(c)/uint64(d))])
(REMV (MOVVconst [c]) (MOVVconst [d])) && d != 0 => (MOVVconst [c%d]) // mod
(REMVU (MOVVconst [c]) (MOVVconst [d])) && d != 0 => (MOVVconst [int64(uint64(c)%uint64(d))]) // mod
(ANDconst [c] (MOVVconst [d])) => (MOVVconst [c&d])
(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
(ORconst [c] (MOVVconst [d])) => (MOVVconst [c|d])

View File

@ -124,7 +124,6 @@ func init() {
// Common individual register masks
var (
gp = buildReg("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") // R1 is LR, R2 is thread pointer, R3 is stack pointer, R21-unused, R22 is g, R30 is REGTMP
gps = buildReg("R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31") | buildReg("g")
gpg = gp | buildReg("g")
gpsp = gp | buildReg("SP")
gpspg = gpg | buildReg("SP")
@ -142,7 +141,6 @@ func init() {
gp11 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
gp11sp = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
gp21 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
gp22 = regInfo{inputs: []regMask{gps, gps}, outputs: []regMask{gp, gp}}
gpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
gpstore = regInfo{inputs: []regMask{gpspsbg, gpg}}
gpstore0 = regInfo{inputs: []regMask{gpspsbg}}
@ -166,8 +164,10 @@ func init() {
{name: "MULV", argLength: 2, reg: gp21, asm: "MULV", commutative: true, typ: "Int64"}, // arg0 * arg1
{name: "MULHV", argLength: 2, reg: gp21, asm: "MULHV", commutative: true, typ: "Int64"}, // (arg0 * arg1) >> 64, signed
{name: "MULHVU", argLength: 2, reg: gp21, asm: "MULHVU", commutative: true, typ: "UInt64"}, // (arg0 * arg1) >> 64, unsigned
{name: "DIVV", argLength: 2, reg: gp22, resultNotInArgs: true, typ: "(Int64,Int64)"}, // arg0 / arg1, signed
{name: "DIVVU", argLength: 2, reg: gp22, resultNotInArgs: true, typ: "(UInt64,UInt64)"}, // arg0 / arg1, unsigned
{name: "DIVV", argLength: 2, reg: gp21, asm: "DIVV", typ: "Int64"}, // arg0 / arg1, signed
{name: "DIVVU", argLength: 2, reg: gp21, asm: "DIVVU", typ: "UInt64"}, // arg0 / arg1, unsigned
{name: "REMV", argLength: 2, reg: gp21, asm: "REMV", typ: "Int64"}, // arg0 / arg1, signed
{name: "REMVU", argLength: 2, reg: gp21, asm: "REMVU", typ: "UInt64"}, // arg0 / arg1, unsigned
{name: "ADDF", argLength: 2, reg: fp21, asm: "ADDF", commutative: true}, // arg0 + arg1
{name: "ADDD", argLength: 2, reg: fp21, asm: "ADDD", commutative: true}, // arg0 + arg1

View File

@ -1723,6 +1723,8 @@ const (
OpLOONG64MULHVU
OpLOONG64DIVV
OpLOONG64DIVVU
OpLOONG64REMV
OpLOONG64REMVU
OpLOONG64ADDF
OpLOONG64ADDD
OpLOONG64SUBF
@ -22992,32 +22994,58 @@ var opcodeTable = [...]opInfo{
},
},
{
name: "DIVV",
argLen: 2,
resultNotInArgs: true,
name: "DIVV",
argLen: 2,
asm: loong64.ADIVV,
reg: regInfo{
inputs: []inputInfo{
{0, 1072496632}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
{1, 1072496632}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
{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
{1, 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: "DIVVU",
argLen: 2,
resultNotInArgs: true,
name: "DIVVU",
argLen: 2,
asm: loong64.ADIVVU,
reg: regInfo{
inputs: []inputInfo{
{0, 1072496632}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
{1, 1072496632}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
{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: "REMV",
argLen: 2,
asm: loong64.AREMV,
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: "REMVU",
argLen: 2,
asm: loong64.AREMVU,
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
{1, 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
},
},
},

View File

@ -166,7 +166,8 @@ func rewriteValueLOONG64(v *Value) bool {
v.Op = OpLOONG64DIVD
return true
case OpDiv64u:
return rewriteValueLOONG64_OpDiv64u(v)
v.Op = OpLOONG64DIVVU
return true
case OpDiv8:
return rewriteValueLOONG64_OpDiv8(v)
case OpDiv8u:
@ -223,6 +224,10 @@ func rewriteValueLOONG64(v *Value) bool {
return rewriteValueLOONG64_OpLOONG64AND(v)
case OpLOONG64ANDconst:
return rewriteValueLOONG64_OpLOONG64ANDconst(v)
case OpLOONG64DIVV:
return rewriteValueLOONG64_OpLOONG64DIVV(v)
case OpLOONG64DIVVU:
return rewriteValueLOONG64_OpLOONG64DIVVU(v)
case OpLOONG64LoweredAtomicAdd32:
return rewriteValueLOONG64_OpLOONG64LoweredAtomicAdd32(v)
case OpLOONG64LoweredAtomicAdd64:
@ -299,6 +304,10 @@ func rewriteValueLOONG64(v *Value) bool {
return rewriteValueLOONG64_OpLOONG64OR(v)
case OpLOONG64ORconst:
return rewriteValueLOONG64_OpLOONG64ORconst(v)
case OpLOONG64REMV:
return rewriteValueLOONG64_OpLOONG64REMV(v)
case OpLOONG64REMVU:
return rewriteValueLOONG64_OpLOONG64REMVU(v)
case OpLOONG64ROTR:
return rewriteValueLOONG64_OpLOONG64ROTR(v)
case OpLOONG64ROTRV:
@ -418,7 +427,8 @@ func rewriteValueLOONG64(v *Value) bool {
case OpMod64:
return rewriteValueLOONG64_OpMod64(v)
case OpMod64u:
return rewriteValueLOONG64_OpMod64u(v)
v.Op = OpLOONG64REMVU
return true
case OpMod8:
return rewriteValueLOONG64_OpMod8(v)
case OpMod8u:
@ -915,18 +925,16 @@ func rewriteValueLOONG64_OpDiv16(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Div16 x y)
// result: (Select1 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
// result: (DIVV (SignExt16to64 x) (SignExt16to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVV, types.NewTuple(typ.Int64, typ.Int64))
v.reset(OpLOONG64DIVV)
v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
@ -936,18 +944,16 @@ func rewriteValueLOONG64_OpDiv16u(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Div16u x y)
// result: (Select1 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
// result: (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
v.reset(OpLOONG64DIVVU)
v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
@ -957,18 +963,16 @@ func rewriteValueLOONG64_OpDiv32(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Div32 x y)
// result: (Select1 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
// result: (DIVV (SignExt32to64 x) (SignExt32to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVV, types.NewTuple(typ.Int64, typ.Int64))
v.reset(OpLOONG64DIVV)
v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
@ -978,52 +982,29 @@ func rewriteValueLOONG64_OpDiv32u(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Div32u x y)
// result: (Select1 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
// result: (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
v.reset(OpLOONG64DIVVU)
v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
func rewriteValueLOONG64_OpDiv64(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (Div64 x y)
// result: (Select1 (DIVV x y))
// result: (DIVV x y)
for {
x := v_0
y := v_1
v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVV, types.NewTuple(typ.Int64, typ.Int64))
v0.AddArg2(x, y)
v.AddArg(v0)
return true
}
}
func rewriteValueLOONG64_OpDiv64u(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (Div64u x y)
// result: (Select1 (DIVVU x y))
for {
x := v_0
y := v_1
v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
v0.AddArg2(x, y)
v.AddArg(v0)
v.reset(OpLOONG64DIVV)
v.AddArg2(x, y)
return true
}
}
@ -1033,18 +1014,16 @@ func rewriteValueLOONG64_OpDiv8(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Div8 x y)
// result: (Select1 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
// result: (DIVV (SignExt8to64 x) (SignExt8to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVV, types.NewTuple(typ.Int64, typ.Int64))
v.reset(OpLOONG64DIVV)
v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
@ -1054,18 +1033,16 @@ func rewriteValueLOONG64_OpDiv8u(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Div8u x y)
// result: (Select1 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
// result: (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect1)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
v.reset(OpLOONG64DIVVU)
v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
@ -1526,6 +1503,81 @@ func rewriteValueLOONG64_OpLOONG64ANDconst(v *Value) bool {
}
return false
}
func rewriteValueLOONG64_OpLOONG64DIVV(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (DIVV (MOVVconst [c]) (MOVVconst [d]))
// cond: d != 0
// result: (MOVVconst [c/d])
for {
if v_0.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_0.AuxInt)
if v_1.Op != OpLOONG64MOVVconst {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpLOONG64MOVVconst)
v.AuxInt = int64ToAuxInt(c / d)
return true
}
return false
}
func rewriteValueLOONG64_OpLOONG64DIVVU(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (DIVVU x (MOVVconst [1]))
// result: x
for {
x := v_0
if v_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_1.AuxInt) != 1 {
break
}
v.copyOf(x)
return true
}
// match: (DIVVU x (MOVVconst [c]))
// cond: isPowerOfTwo64(c)
// result: (SRLVconst [log64(c)] x)
for {
x := v_0
if v_1.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_1.AuxInt)
if !(isPowerOfTwo64(c)) {
break
}
v.reset(OpLOONG64SRLVconst)
v.AuxInt = int64ToAuxInt(log64(c))
v.AddArg(x)
return true
}
// match: (DIVVU (MOVVconst [c]) (MOVVconst [d]))
// cond: d != 0
// result: (MOVVconst [int64(uint64(c)/uint64(d))])
for {
if v_0.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_0.AuxInt)
if v_1.Op != OpLOONG64MOVVconst {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpLOONG64MOVVconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d)))
return true
}
return false
}
func rewriteValueLOONG64_OpLOONG64LoweredAtomicAdd32(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
@ -3467,6 +3519,81 @@ func rewriteValueLOONG64_OpLOONG64ORconst(v *Value) bool {
}
return false
}
func rewriteValueLOONG64_OpLOONG64REMV(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (REMV (MOVVconst [c]) (MOVVconst [d]))
// cond: d != 0
// result: (MOVVconst [c%d])
for {
if v_0.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_0.AuxInt)
if v_1.Op != OpLOONG64MOVVconst {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpLOONG64MOVVconst)
v.AuxInt = int64ToAuxInt(c % d)
return true
}
return false
}
func rewriteValueLOONG64_OpLOONG64REMVU(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (REMVU _ (MOVVconst [1]))
// result: (MOVVconst [0])
for {
if v_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_1.AuxInt) != 1 {
break
}
v.reset(OpLOONG64MOVVconst)
v.AuxInt = int64ToAuxInt(0)
return true
}
// match: (REMVU x (MOVVconst [c]))
// cond: isPowerOfTwo64(c)
// result: (ANDconst [c-1] x)
for {
x := v_0
if v_1.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_1.AuxInt)
if !(isPowerOfTwo64(c)) {
break
}
v.reset(OpLOONG64ANDconst)
v.AuxInt = int64ToAuxInt(c - 1)
v.AddArg(x)
return true
}
// match: (REMVU (MOVVconst [c]) (MOVVconst [d]))
// cond: d != 0
// result: (MOVVconst [int64(uint64(c)%uint64(d))])
for {
if v_0.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_0.AuxInt)
if v_1.Op != OpLOONG64MOVVconst {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpLOONG64MOVVconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d)))
return true
}
return false
}
func rewriteValueLOONG64_OpLOONG64ROTR(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
@ -5131,18 +5258,16 @@ func rewriteValueLOONG64_OpMod16(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Mod16 x y)
// result: (Select0 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
// result: (REMV (SignExt16to64 x) (SignExt16to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect0)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVV, types.NewTuple(typ.Int64, typ.Int64))
v.reset(OpLOONG64REMV)
v0 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpSignExt16to64, typ.Int64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
@ -5152,18 +5277,16 @@ func rewriteValueLOONG64_OpMod16u(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Mod16u x y)
// result: (Select0 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
// result: (REMVU (ZeroExt16to64 x) (ZeroExt16to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect0)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
v.reset(OpLOONG64REMVU)
v0 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
@ -5173,18 +5296,16 @@ func rewriteValueLOONG64_OpMod32(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Mod32 x y)
// result: (Select0 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
// result: (REMV (SignExt32to64 x) (SignExt32to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect0)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVV, types.NewTuple(typ.Int64, typ.Int64))
v.reset(OpLOONG64REMV)
v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
@ -5194,52 +5315,29 @@ func rewriteValueLOONG64_OpMod32u(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Mod32u x y)
// result: (Select0 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
// result: (REMVU (ZeroExt32to64 x) (ZeroExt32to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect0)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
v.reset(OpLOONG64REMVU)
v0 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
func rewriteValueLOONG64_OpMod64(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (Mod64 x y)
// result: (Select0 (DIVV x y))
// result: (REMV x y)
for {
x := v_0
y := v_1
v.reset(OpSelect0)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVV, types.NewTuple(typ.Int64, typ.Int64))
v0.AddArg2(x, y)
v.AddArg(v0)
return true
}
}
func rewriteValueLOONG64_OpMod64u(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (Mod64u x y)
// result: (Select0 (DIVVU x y))
for {
x := v_0
y := v_1
v.reset(OpSelect0)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
v0.AddArg2(x, y)
v.AddArg(v0)
v.reset(OpLOONG64REMV)
v.AddArg2(x, y)
return true
}
}
@ -5249,18 +5347,16 @@ func rewriteValueLOONG64_OpMod8(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Mod8 x y)
// result: (Select0 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
// result: (REMV (SignExt8to64 x) (SignExt8to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect0)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVV, types.NewTuple(typ.Int64, typ.Int64))
v.reset(OpLOONG64REMV)
v0 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpSignExt8to64, typ.Int64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
@ -5270,18 +5366,16 @@ func rewriteValueLOONG64_OpMod8u(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (Mod8u x y)
// result: (Select0 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
// result: (REMVU (ZeroExt8to64 x) (ZeroExt8to64 y))
for {
x := v_0
y := v_1
v.reset(OpSelect0)
v0 := b.NewValue0(v.Pos, OpLOONG64DIVVU, types.NewTuple(typ.UInt64, typ.UInt64))
v.reset(OpLOONG64REMVU)
v0 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
v1.AddArg(x)
v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
v2.AddArg(y)
v0.AddArg2(v1, v2)
v.AddArg(v0)
v1.AddArg(y)
v.AddArg2(v0, v1)
return true
}
}
@ -6919,93 +7013,6 @@ func rewriteValueLOONG64_OpSelect0(v *Value) bool {
v.AddArg2(v0, c)
return true
}
// match: (Select0 (DIVVU _ (MOVVconst [1])))
// result: (MOVVconst [0])
for {
if v_0.Op != OpLOONG64DIVVU {
break
}
_ = v_0.Args[1]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 1 {
break
}
v.reset(OpLOONG64MOVVconst)
v.AuxInt = int64ToAuxInt(0)
return true
}
// match: (Select0 (DIVVU x (MOVVconst [c])))
// cond: isPowerOfTwo64(c)
// result: (ANDconst [c-1] x)
for {
if v_0.Op != OpLOONG64DIVVU {
break
}
_ = v_0.Args[1]
x := v_0.Args[0]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_0_1.AuxInt)
if !(isPowerOfTwo64(c)) {
break
}
v.reset(OpLOONG64ANDconst)
v.AuxInt = int64ToAuxInt(c - 1)
v.AddArg(x)
return true
}
// match: (Select0 (DIVV (MOVVconst [c]) (MOVVconst [d])))
// cond: d != 0
// result: (MOVVconst [c%d])
for {
if v_0.Op != OpLOONG64DIVV {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_0_0.AuxInt)
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpLOONG64MOVVconst {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpLOONG64MOVVconst)
v.AuxInt = int64ToAuxInt(c % d)
return true
}
// match: (Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d])))
// cond: d != 0
// result: (MOVVconst [int64(uint64(c)%uint64(d))])
for {
if v_0.Op != OpLOONG64DIVVU {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_0_0.AuxInt)
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpLOONG64MOVVconst {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpLOONG64MOVVconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d)))
return true
}
return false
}
func rewriteValueLOONG64_OpSelect1(v *Value) bool {
@ -7085,93 +7092,6 @@ func rewriteValueLOONG64_OpSelect1(v *Value) bool {
v.AddArg2(v0, v2)
return true
}
// match: (Select1 (DIVVU x (MOVVconst [1])))
// result: x
for {
if v_0.Op != OpLOONG64DIVVU {
break
}
_ = v_0.Args[1]
x := v_0.Args[0]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 1 {
break
}
v.copyOf(x)
return true
}
// match: (Select1 (DIVVU x (MOVVconst [c])))
// cond: isPowerOfTwo64(c)
// result: (SRLVconst [log64(c)] x)
for {
if v_0.Op != OpLOONG64DIVVU {
break
}
_ = v_0.Args[1]
x := v_0.Args[0]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_0_1.AuxInt)
if !(isPowerOfTwo64(c)) {
break
}
v.reset(OpLOONG64SRLVconst)
v.AuxInt = int64ToAuxInt(log64(c))
v.AddArg(x)
return true
}
// match: (Select1 (DIVV (MOVVconst [c]) (MOVVconst [d])))
// cond: d != 0
// result: (MOVVconst [c/d])
for {
if v_0.Op != OpLOONG64DIVV {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_0_0.AuxInt)
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpLOONG64MOVVconst {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpLOONG64MOVVconst)
v.AuxInt = int64ToAuxInt(c / d)
return true
}
// match: (Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d])))
// cond: d != 0
// result: (MOVVconst [int64(uint64(c)/uint64(d))])
for {
if v_0.Op != OpLOONG64DIVVU {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64MOVVconst {
break
}
c := auxIntToInt64(v_0_0.AuxInt)
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpLOONG64MOVVconst {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpLOONG64MOVVconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d)))
return true
}
return false
}
func rewriteValueLOONG64_OpSlicemask(v *Value) bool {