]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fold negation into multiplication
authorMeng Zhuo <mengzhuo@iscas.ac.cn>
Fri, 14 Nov 2025 04:47:35 +0000 (12:47 +0800)
committerGopher Robot <gobot@golang.org>
Fri, 14 Nov 2025 19:01:22 +0000 (11:01 -0800)
goos: linux
goarch: riscv64
pkg: cmd/compile/internal/test
cpu: Spacemit(R) X60
        │ /root/mul.base.log │          /root/mul.new.log          │
        │       sec/op       │   sec/op     vs base                │
MulNeg           6.426µ ± 0%   4.501µ ± 0%  -29.96% (p=0.000 n=10)
Mul2Neg          9.000µ ± 0%   6.431µ ± 0%  -28.54% (p=0.000 n=10)
Mul2             1.263µ ± 0%   1.263µ ± 0%        ~ (p=1.000 n=10)
MulNeg2          1.577µ ± 0%   1.577µ ± 0%        ~ (p=0.211 n=10)
geomean          3.276µ        2.756µ       -15.89%

goos: linux
goarch: amd64
pkg: cmd/compile/internal/test
cpu: AMD EPYC 7532 32-Core Processor
        │ /root/base  │              /root/new              │
        │   sec/op    │   sec/op     vs base                │
MulNeg    691.9n ± 1%   319.4n ± 0%  -53.83% (p=0.000 n=10)
Mul2Neg   630.0n ± 0%   629.6n ± 0%   -0.07% (p=0.000 n=10)
Mul2      438.1n ± 0%   438.1n ± 0%        ~ (p=0.728 n=10)
MulNeg2   439.3n ± 0%   439.4n ± 0%        ~ (p=0.656 n=10)
geomean   538.2n        443.6n       -17.58%

Change-Id: Ice8e6c8d1e8e3009ba8a0b1b689205174e199019
Reviewed-on: https://go-review.googlesource.com/c/go/+/720180
Reviewed-by: abner chenc <chenguoqi@loongson.cn>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Reviewed-by: Joel Sing <joel@sing.id.au>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>

src/cmd/compile/internal/ssa/_gen/LOONG64.rules
src/cmd/compile/internal/ssa/_gen/generic.rules
src/cmd/compile/internal/ssa/rewriteLOONG64.go
src/cmd/compile/internal/ssa/rewritegeneric.go
test/codegen/arithmetic.go

index 9691296043a3ae6962489944bce4208bd0068d63..2beba0b1c5caa246ef7420f84a0d0ec017a767e8 100644 (file)
 
 (MULV  x (MOVVconst [c])) && canMulStrengthReduce(config, c) => {mulStrengthReduce(v, x, c)}
 
-(MULV (NEGV x) (MOVVconst [c])) => (MULV x (MOVVconst [-c]))
-(MULV (NEGV x) (NEGV y)) => (MULV x y)
-
 (ADDV x0 x1:(SLLVconst [c] y)) && x1.Uses == 1 && c > 0 && c <= 4 => (ADDshiftLLV x0 y [c])
 
 // fold constant in ADDshift op
index 6efead03ade59c471e7cf46d1d72e39d0a42928e..e09cd31c31189b0630b9b3951246842e6de69922 100644 (file)
 // Convert x * -1 to -x.
 (Mul(8|16|32|64)  (Const(8|16|32|64)  [-1]) x) => (Neg(8|16|32|64)  x)
 
+// Convert -x * c to x * -c
+(Mul(8|16|32|64) (Const(8|16|32|64) <t> [c]) (Neg(8|16|32|64) x)) => (Mul(8|16|32|64) x (Const(8|16|32|64) <t> [-c]))
+
+(Mul(8|16|32|64) (Neg(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))
 (Neq(64|32|16) (SignExt8to(64|32|16) (CvtBoolToUint8 x)) (Const(64|32|16) [0])) => x
 (Neq(64|32|16) (SignExt8to(64|32|16) (CvtBoolToUint8 x)) (Const(64|32|16) [1])) => (Not x)
 (Eq(64|32|16)  (SignExt8to(64|32|16) (CvtBoolToUint8 x)) (Const(64|32|16) [1])) => x
-(Eq(64|32|16)  (SignExt8to(64|32|16) (CvtBoolToUint8 x)) (Const(64|32|16) [0])) => (Not x)
\ No newline at end of file
+(Eq(64|32|16)  (SignExt8to(64|32|16) (CvtBoolToUint8 x)) (Const(64|32|16) [0])) => (Not x)
index 4262d4e0fb7b2d4a1f4bd01bc128c4df2de4007a..bf2dd114a93a33d8bc5702b4648d7bcc2276fec0 100644 (file)
@@ -5866,7 +5866,6 @@ func rewriteValueLOONG64_OpLOONG64MULV(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
        config := b.Func.Config
-       typ := &b.Func.Config.Types
        // match: (MULV _ (MOVVconst [0]))
        // result: (MOVVconst [0])
        for {
@@ -5911,44 +5910,6 @@ func rewriteValueLOONG64_OpLOONG64MULV(v *Value) bool {
                }
                break
        }
-       // match: (MULV (NEGV x) (MOVVconst [c]))
-       // result: (MULV x (MOVVconst [-c]))
-       for {
-               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
-                       if v_0.Op != OpLOONG64NEGV {
-                               continue
-                       }
-                       x := v_0.Args[0]
-                       if v_1.Op != OpLOONG64MOVVconst {
-                               continue
-                       }
-                       c := auxIntToInt64(v_1.AuxInt)
-                       v.reset(OpLOONG64MULV)
-                       v0 := b.NewValue0(v.Pos, OpLOONG64MOVVconst, typ.UInt64)
-                       v0.AuxInt = int64ToAuxInt(-c)
-                       v.AddArg2(x, v0)
-                       return true
-               }
-               break
-       }
-       // match: (MULV (NEGV x) (NEGV y))
-       // result: (MULV x y)
-       for {
-               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
-                       if v_0.Op != OpLOONG64NEGV {
-                               continue
-                       }
-                       x := v_0.Args[0]
-                       if v_1.Op != OpLOONG64NEGV {
-                               continue
-                       }
-                       y := v_1.Args[0]
-                       v.reset(OpLOONG64MULV)
-                       v.AddArg2(x, y)
-                       return true
-               }
-               break
-       }
        // match: (MULV (MOVVconst [c]) (MOVVconst [d]))
        // result: (MOVVconst [c*d])
        for {
index 2428f17947238ad4a6deb49bc297326733540330..1621153b439d569db95bf92d8945d8ff5fc18c77 100644 (file)
@@ -16786,6 +16786,45 @@ func rewriteValuegeneric_OpMul16(v *Value) bool {
                }
                break
        }
+       // match: (Mul16 (Const16 <t> [c]) (Neg16 x))
+       // result: (Mul16 x (Const16 <t> [-c]))
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       if v_0.Op != OpConst16 {
+                               continue
+                       }
+                       t := v_0.Type
+                       c := auxIntToInt16(v_0.AuxInt)
+                       if v_1.Op != OpNeg16 {
+                               continue
+                       }
+                       x := v_1.Args[0]
+                       v.reset(OpMul16)
+                       v0 := b.NewValue0(v.Pos, OpConst16, t)
+                       v0.AuxInt = int16ToAuxInt(-c)
+                       v.AddArg2(x, v0)
+                       return true
+               }
+               break
+       }
+       // match: (Mul16 (Neg16 x) (Neg16 y))
+       // result: (Mul16 x y)
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       if v_0.Op != OpNeg16 {
+                               continue
+                       }
+                       x := v_0.Args[0]
+                       if v_1.Op != OpNeg16 {
+                               continue
+                       }
+                       y := v_1.Args[0]
+                       v.reset(OpMul16)
+                       v.AddArg2(x, y)
+                       return true
+               }
+               break
+       }
        // match: (Mul16 (Const16 <t> [c]) (Add16 <t> (Const16 <t> [d]) x))
        // cond: !isPowerOfTwo(c)
        // result: (Add16 (Const16 <t> [c*d]) (Mul16 <t> (Const16 <t> [c]) x))
@@ -16997,6 +17036,45 @@ func rewriteValuegeneric_OpMul32(v *Value) bool {
                }
                break
        }
+       // match: (Mul32 (Const32 <t> [c]) (Neg32 x))
+       // result: (Mul32 x (Const32 <t> [-c]))
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       if v_0.Op != OpConst32 {
+                               continue
+                       }
+                       t := v_0.Type
+                       c := auxIntToInt32(v_0.AuxInt)
+                       if v_1.Op != OpNeg32 {
+                               continue
+                       }
+                       x := v_1.Args[0]
+                       v.reset(OpMul32)
+                       v0 := b.NewValue0(v.Pos, OpConst32, t)
+                       v0.AuxInt = int32ToAuxInt(-c)
+                       v.AddArg2(x, v0)
+                       return true
+               }
+               break
+       }
+       // match: (Mul32 (Neg32 x) (Neg32 y))
+       // result: (Mul32 x y)
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       if v_0.Op != OpNeg32 {
+                               continue
+                       }
+                       x := v_0.Args[0]
+                       if v_1.Op != OpNeg32 {
+                               continue
+                       }
+                       y := v_1.Args[0]
+                       v.reset(OpMul32)
+                       v.AddArg2(x, y)
+                       return true
+               }
+               break
+       }
        // match: (Mul32 (Const32 <t> [c]) (Add32 <t> (Const32 <t> [d]) x))
        // cond: !isPowerOfTwo(c)
        // result: (Add32 (Const32 <t> [c*d]) (Mul32 <t> (Const32 <t> [c]) x))
@@ -17369,6 +17447,45 @@ func rewriteValuegeneric_OpMul64(v *Value) bool {
                }
                break
        }
+       // match: (Mul64 (Const64 <t> [c]) (Neg64 x))
+       // result: (Mul64 x (Const64 <t> [-c]))
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       if v_0.Op != OpConst64 {
+                               continue
+                       }
+                       t := v_0.Type
+                       c := auxIntToInt64(v_0.AuxInt)
+                       if v_1.Op != OpNeg64 {
+                               continue
+                       }
+                       x := v_1.Args[0]
+                       v.reset(OpMul64)
+                       v0 := b.NewValue0(v.Pos, OpConst64, t)
+                       v0.AuxInt = int64ToAuxInt(-c)
+                       v.AddArg2(x, v0)
+                       return true
+               }
+               break
+       }
+       // match: (Mul64 (Neg64 x) (Neg64 y))
+       // result: (Mul64 x y)
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       if v_0.Op != OpNeg64 {
+                               continue
+                       }
+                       x := v_0.Args[0]
+                       if v_1.Op != OpNeg64 {
+                               continue
+                       }
+                       y := v_1.Args[0]
+                       v.reset(OpMul64)
+                       v.AddArg2(x, y)
+                       return true
+               }
+               break
+       }
        // match: (Mul64 (Const64 <t> [c]) (Add64 <t> (Const64 <t> [d]) x))
        // cond: !isPowerOfTwo(c)
        // result: (Add64 (Const64 <t> [c*d]) (Mul64 <t> (Const64 <t> [c]) x))
@@ -17741,6 +17858,45 @@ func rewriteValuegeneric_OpMul8(v *Value) bool {
                }
                break
        }
+       // match: (Mul8 (Const8 <t> [c]) (Neg8 x))
+       // result: (Mul8 x (Const8 <t> [-c]))
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       if v_0.Op != OpConst8 {
+                               continue
+                       }
+                       t := v_0.Type
+                       c := auxIntToInt8(v_0.AuxInt)
+                       if v_1.Op != OpNeg8 {
+                               continue
+                       }
+                       x := v_1.Args[0]
+                       v.reset(OpMul8)
+                       v0 := b.NewValue0(v.Pos, OpConst8, t)
+                       v0.AuxInt = int8ToAuxInt(-c)
+                       v.AddArg2(x, v0)
+                       return true
+               }
+               break
+       }
+       // match: (Mul8 (Neg8 x) (Neg8 y))
+       // result: (Mul8 x y)
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       if v_0.Op != OpNeg8 {
+                               continue
+                       }
+                       x := v_0.Args[0]
+                       if v_1.Op != OpNeg8 {
+                               continue
+                       }
+                       y := v_1.Args[0]
+                       v.reset(OpMul8)
+                       v.AddArg2(x, y)
+                       return true
+               }
+               break
+       }
        // match: (Mul8 (Const8 <t> [c]) (Add8 <t> (Const8 <t> [d]) x))
        // cond: !isPowerOfTwo(c)
        // result: (Add8 (Const8 <t> [c*d]) (Mul8 <t> (Const8 <t> [c]) x))
index 42d5d2ef65848b64fd7092138dc1e399a0fc8f86..6b2c5529e1601e10c4268e93fa51c25f52e210c9 100644 (file)
@@ -318,13 +318,19 @@ func MergeMuls5(a, n int) int {
 // Multiplications folded negation
 
 func FoldNegMul(a int) int {
-       // loong64:"SUBVU" "ALSLV [$]2" "ALSLV [$]1"
-       return (-a) * 11
+       // amd64:"IMUL3Q [$]-11" -"NEGQ"
+       // arm64:"MOVD [$]-11" "MUL" -"NEG"
+       // loong64:"ALSLV [$]2" "SUBVU" "ALSLV [$]4"
+       // riscv64:"MOV [$]-11" "MUL" -"NEG"
+       return -a * 11
 }
 
 func Fold2NegMul(a, b int) int {
+       // amd64:"IMULQ" -"NEGQ"
+       // arm64:"MUL" -"NEG"
        // loong64:"MULV" -"SUBVU R[0-9], R0,"
-       return (-a) * (-b)
+       // riscv64:"MUL" -"NEG"
+       return -a * -b
 }
 
 // -------------- //