mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: fold negation into multiplication
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>
This commit is contained in:
parent
b57962b7c7
commit
2cdcc4150b
5 changed files with 171 additions and 46 deletions
|
|
@ -743,9 +743,6 @@
|
||||||
|
|
||||||
(MULV x (MOVVconst [c])) && canMulStrengthReduce(config, c) => {mulStrengthReduce(v, x, c)}
|
(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])
|
(ADDV x0 x1:(SLLVconst [c] y)) && x1.Uses == 1 && c > 0 && c <= 4 => (ADDshiftLLV x0 y [c])
|
||||||
|
|
||||||
// fold constant in ADDshift op
|
// fold constant in ADDshift op
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,11 @@
|
||||||
// Convert x * -1 to -x.
|
// Convert x * -1 to -x.
|
||||||
(Mul(8|16|32|64) (Const(8|16|32|64) [-1]) x) => (Neg(8|16|32|64) 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
|
// 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))
|
(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))
|
(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))
|
||||||
|
|
|
||||||
|
|
@ -5866,7 +5866,6 @@ func rewriteValueLOONG64_OpLOONG64MULV(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
b := v.Block
|
b := v.Block
|
||||||
config := b.Func.Config
|
config := b.Func.Config
|
||||||
typ := &b.Func.Config.Types
|
|
||||||
// match: (MULV _ (MOVVconst [0]))
|
// match: (MULV _ (MOVVconst [0]))
|
||||||
// result: (MOVVconst [0])
|
// result: (MOVVconst [0])
|
||||||
for {
|
for {
|
||||||
|
|
@ -5911,44 +5910,6 @@ func rewriteValueLOONG64_OpLOONG64MULV(v *Value) bool {
|
||||||
}
|
}
|
||||||
break
|
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]))
|
// match: (MULV (MOVVconst [c]) (MOVVconst [d]))
|
||||||
// result: (MOVVconst [c*d])
|
// result: (MOVVconst [c*d])
|
||||||
for {
|
for {
|
||||||
|
|
|
||||||
|
|
@ -16786,6 +16786,45 @@ func rewriteValuegeneric_OpMul16(v *Value) bool {
|
||||||
}
|
}
|
||||||
break
|
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))
|
// match: (Mul16 (Const16 <t> [c]) (Add16 <t> (Const16 <t> [d]) x))
|
||||||
// cond: !isPowerOfTwo(c)
|
// cond: !isPowerOfTwo(c)
|
||||||
// result: (Add16 (Const16 <t> [c*d]) (Mul16 <t> (Const16 <t> [c]) x))
|
// result: (Add16 (Const16 <t> [c*d]) (Mul16 <t> (Const16 <t> [c]) x))
|
||||||
|
|
@ -16997,6 +17036,45 @@ func rewriteValuegeneric_OpMul32(v *Value) bool {
|
||||||
}
|
}
|
||||||
break
|
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))
|
// match: (Mul32 (Const32 <t> [c]) (Add32 <t> (Const32 <t> [d]) x))
|
||||||
// cond: !isPowerOfTwo(c)
|
// cond: !isPowerOfTwo(c)
|
||||||
// result: (Add32 (Const32 <t> [c*d]) (Mul32 <t> (Const32 <t> [c]) x))
|
// result: (Add32 (Const32 <t> [c*d]) (Mul32 <t> (Const32 <t> [c]) x))
|
||||||
|
|
@ -17369,6 +17447,45 @@ func rewriteValuegeneric_OpMul64(v *Value) bool {
|
||||||
}
|
}
|
||||||
break
|
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))
|
// match: (Mul64 (Const64 <t> [c]) (Add64 <t> (Const64 <t> [d]) x))
|
||||||
// cond: !isPowerOfTwo(c)
|
// cond: !isPowerOfTwo(c)
|
||||||
// result: (Add64 (Const64 <t> [c*d]) (Mul64 <t> (Const64 <t> [c]) x))
|
// result: (Add64 (Const64 <t> [c*d]) (Mul64 <t> (Const64 <t> [c]) x))
|
||||||
|
|
@ -17741,6 +17858,45 @@ func rewriteValuegeneric_OpMul8(v *Value) bool {
|
||||||
}
|
}
|
||||||
break
|
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))
|
// match: (Mul8 (Const8 <t> [c]) (Add8 <t> (Const8 <t> [d]) x))
|
||||||
// cond: !isPowerOfTwo(c)
|
// cond: !isPowerOfTwo(c)
|
||||||
// result: (Add8 (Const8 <t> [c*d]) (Mul8 <t> (Const8 <t> [c]) x))
|
// result: (Add8 (Const8 <t> [c*d]) (Mul8 <t> (Const8 <t> [c]) x))
|
||||||
|
|
|
||||||
|
|
@ -318,13 +318,19 @@ func MergeMuls5(a, n int) int {
|
||||||
// Multiplications folded negation
|
// Multiplications folded negation
|
||||||
|
|
||||||
func FoldNegMul(a int) int {
|
func FoldNegMul(a int) int {
|
||||||
// loong64:"SUBVU" "ALSLV [$]2" "ALSLV [$]1"
|
// amd64:"IMUL3Q [$]-11" -"NEGQ"
|
||||||
return (-a) * 11
|
// 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 {
|
func Fold2NegMul(a, b int) int {
|
||||||
|
// amd64:"IMULQ" -"NEGQ"
|
||||||
|
// arm64:"MUL" -"NEG"
|
||||||
// loong64:"MULV" -"SUBVU R[0-9], R0,"
|
// loong64:"MULV" -"SUBVU R[0-9], R0,"
|
||||||
return (-a) * (-b)
|
// riscv64:"MUL" -"NEG"
|
||||||
|
return -a * -b
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------- //
|
// -------------- //
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue