]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: simplify negative on multiplication
authorMeng Zhuo <mengzhuo@iscas.ac.cn>
Tue, 18 Nov 2025 01:53:21 +0000 (09:53 +0800)
committerGopher Robot <gobot@golang.org>
Fri, 21 Nov 2025 20:40:29 +0000 (12:40 -0800)
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>
src/cmd/compile/internal/ssa/_gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go
src/cmd/compile/internal/test/bench_test.go
test/codegen/arithmetic.go

index 372e89863d51a972e6bacf1f52f817969ad898d4..e440a5d1eede2d3a00032725c115218b4db2f5ae 100644 (file)
 
 (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))
index f0560671ace3dae8dbb7555ed81171c6619dc3c7..35dee611fc362187cd6605b17a4ee67e9c1213da 100644 (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 {
index 7303f672fee2a2f45e91de5a64360e5fb2079fce..694673a8f6abe437fb3afd3ca51505ba333364b7 100644 (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
+       }
+}
index 9443d812dc8dd67efc801cccf294cb70e233bd41..29764bf817b3f1b63b0fa0e511a2360f29a2b734 100644 (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    //
 // -------------- //