cmd/compile: simplify specific addition operations using the ADDV16 instruction

On loong64, the addi.d instruction can only directly handle 12-bit
immediate numbers. If a larger immediate number needs to be processed,
it must first be placed in a register, and then the add.d instruction
is used to complete the processing of the larger immediate number.
If a larger immediate number c satisfies is32Bit(c) && c&0xffff == 0,
then the ADDV16 instruction can be used to complete the addition operation.

Removes 164 instructions from the go binary on loong64.

Change-Id: I404de93cc4eaaa12fe424f5a0d61b03231215d1a
Reviewed-on: https://go-review.googlesource.com/c/go/+/700536
Reviewed-by: Meidan Li <limeidan@loongson.cn>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
Reviewed-by: abner chenc <chenguoqi@loongson.cn>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
Xiaolin Zhao 2025-09-03 15:43:21 +08:00 committed by Gopher Robot
parent 459b85ccaa
commit 3492e4262b
6 changed files with 41 additions and 4 deletions

View file

@ -276,6 +276,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpLOONG64ADDVconst,
ssa.OpLOONG64ADDV16const,
ssa.OpLOONG64SUBVconst,
ssa.OpLOONG64ANDconst,
ssa.OpLOONG64ORconst,

View file

@ -794,6 +794,7 @@
(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)
(ADDVconst [c] x) && is32Bit(c) && c&0xffff == 0 && c != 0 => (ADDV16const [c] 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)])

View file

@ -191,6 +191,7 @@ func init() {
// binary ops
{name: "ADDV", argLength: 2, reg: gp21, asm: "ADDVU", commutative: true}, // arg0 + arg1
{name: "ADDVconst", argLength: 1, reg: gp11sp, asm: "ADDVU", aux: "Int64"}, // arg0 + auxInt. auxInt is 32-bit, also in other *const ops.
{name: "ADDV16const", argLength: 1, reg: gp11sp, asm: "ADDV16", aux: "Int64"}, // arg0 + auxInt. auxInt is signed 32-bit and is a multiple of 65536, also in other *const ops.
{name: "SUBV", argLength: 2, reg: gp21, asm: "SUBVU"}, // arg0 - arg1
{name: "SUBVconst", argLength: 1, reg: gp11, asm: "SUBVU", aux: "Int64"}, // arg0 - auxInt

View file

@ -1790,6 +1790,7 @@ const (
OpLOONG64VPCNT16
OpLOONG64ADDV
OpLOONG64ADDVconst
OpLOONG64ADDV16const
OpLOONG64SUBV
OpLOONG64SUBVconst
OpLOONG64MULV
@ -24067,6 +24068,20 @@ var opcodeTable = [...]opInfo{
},
},
},
{
name: "ADDV16const",
auxType: auxInt64,
argLen: 1,
asm: loong64.AADDV16,
reg: regInfo{
inputs: []inputInfo{
{0, 1073741820}, // SP 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: "SUBV",
argLen: 2,

View file

@ -2008,6 +2008,20 @@ func rewriteValueLOONG64_OpLOONG64ADDVconst(v *Value) bool {
v.AddArg(x)
return true
}
// match: (ADDVconst [c] x)
// cond: is32Bit(c) && c&0xffff == 0 && c != 0
// result: (ADDV16const [c] x)
for {
c := auxIntToInt64(v.AuxInt)
x := v_0
if !(is32Bit(c) && c&0xffff == 0 && c != 0) {
break
}
v.reset(OpLOONG64ADDV16const)
v.AuxInt = int64ToAuxInt(c)
v.AddArg(x)
return true
}
return false
}
func rewriteValueLOONG64_OpLOONG64AND(v *Value) bool {

View file

@ -51,6 +51,11 @@ func AddLargeConst(a uint64, out []uint64) {
out[9] = a - 32769
}
func AddLargeConst2(a int, out []int) {
// loong64: -"ADDVU","ADDV16"
out[0] = a + 0x10000
}
// ----------------- //
// Subtraction //
// ----------------- //