From e1a12c781f55da85a30fd63471f8adcba908acd2 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 17 Nov 2025 12:47:04 -0800 Subject: [PATCH] cmd/compile: use 32x32->64 multiplies on arm64 Gets rid of some sign extensions. Change-Id: Ie67ef36b4ca1cd1a2cd9fa5d84578db553578a22 Reviewed-on: https://go-review.googlesource.com/c/go/+/721241 LUCI-TryBot-Result: Go LUCI Reviewed-by: Junyang Shao Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/_gen/ARM64.rules | 4 ++ src/cmd/compile/internal/ssa/rewriteARM64.go | 48 +++++++++++++++++++ test/codegen/arithmetic.go | 9 ++++ 3 files changed, 61 insertions(+) diff --git a/src/cmd/compile/internal/ssa/_gen/ARM64.rules b/src/cmd/compile/internal/ssa/_gen/ARM64.rules index f54a692725..04f43f3137 100644 --- a/src/cmd/compile/internal/ssa/_gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/_gen/ARM64.rules @@ -1814,3 +1814,7 @@ (Select0 (Mul64uover x y)) => (MUL x y) (Select1 (Mul64uover x y)) => (NotEqual (CMPconst (UMULH x y) [0])) + +// 32 mul 32 -> 64 +(MUL r:(MOVWUreg x) s:(MOVWUreg y)) && r.Uses == 1 && s.Uses == 1 => (UMULL x y) +(MUL r:(MOVWreg x) s:(MOVWreg y)) && r.Uses == 1 && s.Uses == 1 => (MULL x y) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 6af1558833..6137ec13a0 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -12556,6 +12556,54 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { } break } + // match: (MUL r:(MOVWUreg x) s:(MOVWUreg y)) + // cond: r.Uses == 1 && s.Uses == 1 + // result: (UMULL x y) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + r := v_0 + if r.Op != OpARM64MOVWUreg { + continue + } + x := r.Args[0] + s := v_1 + if s.Op != OpARM64MOVWUreg { + continue + } + y := s.Args[0] + if !(r.Uses == 1 && s.Uses == 1) { + continue + } + v.reset(OpARM64UMULL) + v.AddArg2(x, y) + return true + } + break + } + // match: (MUL r:(MOVWreg x) s:(MOVWreg y)) + // cond: r.Uses == 1 && s.Uses == 1 + // result: (MULL x y) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + r := v_0 + if r.Op != OpARM64MOVWreg { + continue + } + x := r.Args[0] + s := v_1 + if s.Op != OpARM64MOVWreg { + continue + } + y := s.Args[0] + if !(r.Uses == 1 && s.Uses == 1) { + continue + } + v.reset(OpARM64MULL) + v.AddArg2(x, y) + return true + } + break + } return false } func rewriteValueARM64_OpARM64MULW(v *Value) bool { diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index 6b2c5529e1..9443d812dc 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -333,6 +333,15 @@ func Fold2NegMul(a, b int) int { return -a * -b } +func Mul32(a, b int32) int64 { + // arm64:"SMULL" -"MOVW" + return int64(a) * int64(b) +} +func Mul32U(a, b uint32) uint64 { + // arm64:"UMULL" -"MOVWU" + return uint64(a) * uint64(b) +} + // -------------- // // Division // // -------------- // -- 2.52.0