cmd/compile: simplify negative on multiplication

goos: linux
goarch: amd64
pkg: cmd/compile/internal/test
cpu: AMD EPYC 7532 32-Core Processor
               │       simplify_base │               simplify_new          │
               │       sec/op        │   sec/op     vs base                │
SimplifyNegMul           623.0n ± 0%   319.3n ± 1%  -48.75% (p=0.000 n=10)

goos: linux
goarch: riscv64
pkg: cmd/compile/internal/test
cpu: Spacemit(R) X60
               │       simplify.base │               simplify.new          │
               │       sec/op        │   sec/op     vs base                │
SimplifyNegMul          10.928µ ± 0%   6.432µ ± 0%  -41.14% (p=0.000 n=10)

Change-Id: I1d9393cd19a0b948a5d3a512d627cdc0cf0b38be
Reviewed-on: https://go-review.googlesource.com/c/go/+/721520
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Meng Zhuo 2025-11-18 09:53:21 +08:00 committed by Gopher Robot
parent 35d2712b32
commit e7d47ac33d
4 changed files with 228 additions and 0 deletions

View file

@ -200,6 +200,10 @@
(Mul(8|16|32|64) (Neg(8|16|32|64) x) (Neg(8|16|32|64) y)) => (Mul(8|16|32|64) x y)
// simplify negative on mul if possible
(Neg(8|16|32|64) (Mul(8|16|32|64) x (Const(8|16|32|64) <t> [c]))) => (Mul(8|16|32|64) x (Const(8|16|32|64) <t> [-c]))
(Neg(8|16|32|64) (Mul(8|16|32|64) x (Neg(8|16|32|64) y))) => (Mul(8|16|32|64) x y)
// DeMorgan's Laws
(And(8|16|32|64) <t> (Com(8|16|32|64) x) (Com(8|16|32|64) y)) => (Com(8|16|32|64) (Or(8|16|32|64) <t> x y))
(Or(8|16|32|64) <t> (Com(8|16|32|64) x) (Com(8|16|32|64) y)) => (Com(8|16|32|64) (And(8|16|32|64) <t> x y))

View file

@ -18069,6 +18069,51 @@ func rewriteValuegeneric_OpNeg16(v *Value) bool {
v.AuxInt = int16ToAuxInt(-c)
return true
}
// match: (Neg16 (Mul16 x (Const16 <t> [c])))
// result: (Mul16 x (Const16 <t> [-c]))
for {
if v_0.Op != OpMul16 {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
x := v_0_0
if v_0_1.Op != OpConst16 {
continue
}
t := v_0_1.Type
c := auxIntToInt16(v_0_1.AuxInt)
v.reset(OpMul16)
v0 := b.NewValue0(v.Pos, OpConst16, t)
v0.AuxInt = int16ToAuxInt(-c)
v.AddArg2(x, v0)
return true
}
break
}
// match: (Neg16 (Mul16 x (Neg16 y)))
// result: (Mul16 x y)
for {
if v_0.Op != OpMul16 {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
x := v_0_0
if v_0_1.Op != OpNeg16 {
continue
}
y := v_0_1.Args[0]
v.reset(OpMul16)
v.AddArg2(x, y)
return true
}
break
}
// match: (Neg16 (Sub16 x y))
// result: (Sub16 y x)
for {
@ -18121,6 +18166,51 @@ func rewriteValuegeneric_OpNeg32(v *Value) bool {
v.AuxInt = int32ToAuxInt(-c)
return true
}
// match: (Neg32 (Mul32 x (Const32 <t> [c])))
// result: (Mul32 x (Const32 <t> [-c]))
for {
if v_0.Op != OpMul32 {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
x := v_0_0
if v_0_1.Op != OpConst32 {
continue
}
t := v_0_1.Type
c := auxIntToInt32(v_0_1.AuxInt)
v.reset(OpMul32)
v0 := b.NewValue0(v.Pos, OpConst32, t)
v0.AuxInt = int32ToAuxInt(-c)
v.AddArg2(x, v0)
return true
}
break
}
// match: (Neg32 (Mul32 x (Neg32 y)))
// result: (Mul32 x y)
for {
if v_0.Op != OpMul32 {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
x := v_0_0
if v_0_1.Op != OpNeg32 {
continue
}
y := v_0_1.Args[0]
v.reset(OpMul32)
v.AddArg2(x, y)
return true
}
break
}
// match: (Neg32 (Sub32 x y))
// result: (Sub32 y x)
for {
@ -18192,6 +18282,51 @@ func rewriteValuegeneric_OpNeg64(v *Value) bool {
v.AuxInt = int64ToAuxInt(-c)
return true
}
// match: (Neg64 (Mul64 x (Const64 <t> [c])))
// result: (Mul64 x (Const64 <t> [-c]))
for {
if v_0.Op != OpMul64 {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
x := v_0_0
if v_0_1.Op != OpConst64 {
continue
}
t := v_0_1.Type
c := auxIntToInt64(v_0_1.AuxInt)
v.reset(OpMul64)
v0 := b.NewValue0(v.Pos, OpConst64, t)
v0.AuxInt = int64ToAuxInt(-c)
v.AddArg2(x, v0)
return true
}
break
}
// match: (Neg64 (Mul64 x (Neg64 y)))
// result: (Mul64 x y)
for {
if v_0.Op != OpMul64 {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
x := v_0_0
if v_0_1.Op != OpNeg64 {
continue
}
y := v_0_1.Args[0]
v.reset(OpMul64)
v.AddArg2(x, y)
return true
}
break
}
// match: (Neg64 (Sub64 x y))
// result: (Sub64 y x)
for {
@ -18263,6 +18398,51 @@ func rewriteValuegeneric_OpNeg8(v *Value) bool {
v.AuxInt = int8ToAuxInt(-c)
return true
}
// match: (Neg8 (Mul8 x (Const8 <t> [c])))
// result: (Mul8 x (Const8 <t> [-c]))
for {
if v_0.Op != OpMul8 {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
x := v_0_0
if v_0_1.Op != OpConst8 {
continue
}
t := v_0_1.Type
c := auxIntToInt8(v_0_1.AuxInt)
v.reset(OpMul8)
v0 := b.NewValue0(v.Pos, OpConst8, t)
v0.AuxInt = int8ToAuxInt(-c)
v.AddArg2(x, v0)
return true
}
break
}
// match: (Neg8 (Mul8 x (Neg8 y)))
// result: (Mul8 x y)
for {
if v_0.Op != OpMul8 {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
x := v_0_0
if v_0_1.Op != OpNeg8 {
continue
}
y := v_0_1.Args[0]
v.reset(OpMul8)
v.AddArg2(x, y)
return true
}
break
}
// match: (Neg8 (Sub8 x y))
// result: (Sub8 y x)
for {

View file

@ -145,3 +145,32 @@ func BenchmarkMul2Neg(b *testing.B) {
globl = s
}
}
func BenchmarkSimplifyNegMul(b *testing.B) {
x := make([]int64, 1024)
y := make([]int64, 1024)
b.ResetTimer()
for i := 0; i < b.N; i++ {
var s int64
for i := range x {
s = -(-x[i] * y[i])
}
globl = s
}
}
func BenchmarkSimplifyNegDiv(b *testing.B) {
x := make([]int64, 1024)
y := make([]int64, 1024)
for i := range y {
y[i] = 42
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
var s int64
for i := range x {
s = -(-x[i] / y[i])
}
globl = s
}
}

View file

@ -337,11 +337,26 @@ 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)
}
func SimplifyNegMulConst(a int) int {
// amd64:-"NEGQ"
// arm64:"MOVD [$]11" "MUL" -"NEG"
// riscv64:"MOV [$]11" "MUL" -"NEG"
return -(a * -11)
}
func SimplifyNegMul(a, b int) int {
// amd64:-"NEGQ"
// arm64:"MUL" -"NEG"
// riscv64:"MUL" -"NEG"
return -(-a * b)
}
// -------------- //
// Division //
// -------------- //