cmd/compile: convert branch with zero to more optimal branch zero on loong64

This reduces 7500+ instructions from the go toolchain binary on loong64.

	file         before      after      Δ       %
	asm          555066      554406   -660    -0.1189%
	cgo          481480      480764   -716    -0.1487%
	compile      2475836     2474776  -1060   -0.0428%
	cover        516536      515788   -748    -0.1448%
	link         702220      701216   -1004   -0.1430%
	preprofile   238626      238122   -504    -0.2112%
	vet          792798      791894   -904    -0.1140%
	go           1573108     1571676  -1432   -0.0910%
	gofmt        320578      320042   -536    -0.1672%
	total        7656248     7648684  -7564   -0.0988%

Change-Id: I51b70a1543bc258b7664caa8647e75eecbaf5eed
Reviewed-on: https://go-review.googlesource.com/c/go/+/693495
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: abner chenc <chenguoqi@loongson.cn>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Xiaolin Zhao 2025-08-06 15:50:24 +08:00 committed by abner chenc
parent 1718828c81
commit a7f05b38f7
2 changed files with 128 additions and 0 deletions

View file

@ -951,6 +951,18 @@
(GEZ (MOVVconst [c]) yes no) && c >= 0 => (First yes no)
(GEZ (MOVVconst [c]) yes no) && c < 0 => (First no yes)
// Convert branch with zero to more optimal branch zero.
(BEQ (MOVVconst [0]) cond yes no) => (EQZ cond yes no)
(BEQ cond (MOVVconst [0]) yes no) => (EQZ cond yes no)
(BNE (MOVVconst [0]) cond yes no) => (NEZ cond yes no)
(BNE cond (MOVVconst [0]) yes no) => (NEZ cond yes no)
(BLT (MOVVconst [0]) cond yes no) => (GTZ cond yes no)
(BLT cond (MOVVconst [0]) yes no) => (LTZ cond yes no)
(BLTU (MOVVconst [0]) cond yes no) => (NEZ cond yes no)
(BGE (MOVVconst [0]) cond yes no) => (LEZ cond yes no)
(BGE cond (MOVVconst [0]) yes no) => (GEZ cond yes no)
(BGEU (MOVVconst [0]) cond yes no) => (EQZ cond yes no)
// Arch-specific inlining for small or disjoint runtime.memmove
// Match post-lowering calls, register version.
(SelectN [0] call:(CALLstatic {sym} dst src (MOVVconst [sz]) mem))

View file

@ -11479,6 +11479,122 @@ func rewriteValueLOONG64_OpZero(v *Value) bool {
func rewriteBlockLOONG64(b *Block) bool {
typ := &b.Func.Config.Types
switch b.Kind {
case BlockLOONG64BEQ:
// match: (BEQ (MOVVconst [0]) cond yes no)
// result: (EQZ cond yes no)
for b.Controls[0].Op == OpLOONG64MOVVconst {
v_0 := b.Controls[0]
if auxIntToInt64(v_0.AuxInt) != 0 {
break
}
cond := b.Controls[1]
b.resetWithControl(BlockLOONG64EQZ, cond)
return true
}
// match: (BEQ cond (MOVVconst [0]) yes no)
// result: (EQZ cond yes no)
for b.Controls[1].Op == OpLOONG64MOVVconst {
cond := b.Controls[0]
v_1 := b.Controls[1]
if auxIntToInt64(v_1.AuxInt) != 0 {
break
}
b.resetWithControl(BlockLOONG64EQZ, cond)
return true
}
case BlockLOONG64BGE:
// match: (BGE (MOVVconst [0]) cond yes no)
// result: (LEZ cond yes no)
for b.Controls[0].Op == OpLOONG64MOVVconst {
v_0 := b.Controls[0]
if auxIntToInt64(v_0.AuxInt) != 0 {
break
}
cond := b.Controls[1]
b.resetWithControl(BlockLOONG64LEZ, cond)
return true
}
// match: (BGE cond (MOVVconst [0]) yes no)
// result: (GEZ cond yes no)
for b.Controls[1].Op == OpLOONG64MOVVconst {
cond := b.Controls[0]
v_1 := b.Controls[1]
if auxIntToInt64(v_1.AuxInt) != 0 {
break
}
b.resetWithControl(BlockLOONG64GEZ, cond)
return true
}
case BlockLOONG64BGEU:
// match: (BGEU (MOVVconst [0]) cond yes no)
// result: (EQZ cond yes no)
for b.Controls[0].Op == OpLOONG64MOVVconst {
v_0 := b.Controls[0]
if auxIntToInt64(v_0.AuxInt) != 0 {
break
}
cond := b.Controls[1]
b.resetWithControl(BlockLOONG64EQZ, cond)
return true
}
case BlockLOONG64BLT:
// match: (BLT (MOVVconst [0]) cond yes no)
// result: (GTZ cond yes no)
for b.Controls[0].Op == OpLOONG64MOVVconst {
v_0 := b.Controls[0]
if auxIntToInt64(v_0.AuxInt) != 0 {
break
}
cond := b.Controls[1]
b.resetWithControl(BlockLOONG64GTZ, cond)
return true
}
// match: (BLT cond (MOVVconst [0]) yes no)
// result: (LTZ cond yes no)
for b.Controls[1].Op == OpLOONG64MOVVconst {
cond := b.Controls[0]
v_1 := b.Controls[1]
if auxIntToInt64(v_1.AuxInt) != 0 {
break
}
b.resetWithControl(BlockLOONG64LTZ, cond)
return true
}
case BlockLOONG64BLTU:
// match: (BLTU (MOVVconst [0]) cond yes no)
// result: (NEZ cond yes no)
for b.Controls[0].Op == OpLOONG64MOVVconst {
v_0 := b.Controls[0]
if auxIntToInt64(v_0.AuxInt) != 0 {
break
}
cond := b.Controls[1]
b.resetWithControl(BlockLOONG64NEZ, cond)
return true
}
case BlockLOONG64BNE:
// match: (BNE (MOVVconst [0]) cond yes no)
// result: (NEZ cond yes no)
for b.Controls[0].Op == OpLOONG64MOVVconst {
v_0 := b.Controls[0]
if auxIntToInt64(v_0.AuxInt) != 0 {
break
}
cond := b.Controls[1]
b.resetWithControl(BlockLOONG64NEZ, cond)
return true
}
// match: (BNE cond (MOVVconst [0]) yes no)
// result: (NEZ cond yes no)
for b.Controls[1].Op == OpLOONG64MOVVconst {
cond := b.Controls[0]
v_1 := b.Controls[1]
if auxIntToInt64(v_1.AuxInt) != 0 {
break
}
b.resetWithControl(BlockLOONG64NEZ, cond)
return true
}
case BlockLOONG64EQZ:
// match: (EQZ (FPFlagTrue cmp) yes no)
// result: (FPF cmp yes no)