From a7f05b38f7e7beefd5ee54089aae59b21507bb3c Mon Sep 17 00:00:00 2001 From: Xiaolin Zhao Date: Wed, 6 Aug 2025 15:50:24 +0800 Subject: [PATCH] cmd/compile: convert branch with zero to more optimal branch zero on loong64 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Cherry Mui Reviewed-by: abner chenc LUCI-TryBot-Result: Go LUCI --- .../compile/internal/ssa/_gen/LOONG64.rules | 12 ++ .../compile/internal/ssa/rewriteLOONG64.go | 116 ++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules index 02339cc1e4..4c19507628 100644 --- a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules +++ b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules @@ -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)) diff --git a/src/cmd/compile/internal/ssa/rewriteLOONG64.go b/src/cmd/compile/internal/ssa/rewriteLOONG64.go index 87dae2194b..3065e2c315 100644 --- a/src/cmd/compile/internal/ssa/rewriteLOONG64.go +++ b/src/cmd/compile/internal/ssa/rewriteLOONG64.go @@ -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) -- 2.51.0