Commit 6a74fe2f authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile: strength reduce more x86 constant multiplication

The additions were machine-generated.

The change for x * 7 avoids a reg-reg move,
reducing the number of instructions from 3 to 2.

Change-Id: Ib002e39f29ca5e46cfdb8daaf87ddc7ba50a17e5
Reviewed-on: https://go-review.googlesource.com/102395
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 7bf631e1
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -28,16 +28,23 @@ type szD struct {
sn string
u []uint64
i []int64
oponly string
}
var szs = []szD{
{name: "uint64", sn: "64", u: []uint64{0, 1, 4294967296, 0x8000000000000000, 0xffffFFFFffffFFFF}},
{name: "uint64", sn: "64", u: []uint64{3, 5, 7, 9, 10, 11, 13, 19, 21, 25, 27, 37, 41, 45, 73, 81}, oponly: "mul"},
{name: "int64", sn: "64", i: []int64{-0x8000000000000000, -0x7FFFFFFFFFFFFFFF,
-4294967296, -1, 0, 1, 4294967296, 0x7FFFFFFFFFFFFFFE, 0x7FFFFFFFFFFFFFFF}},
{name: "int64", sn: "64", i: []int64{-9, -5, -3, 3, 5, 7, 9, 10, 11, 13, 19, 21, 25, 27, 37, 41, 45, 73, 81}, oponly: "mul"},
{name: "uint32", sn: "32", u: []uint64{0, 1, 4294967295}},
{name: "uint32", sn: "32", u: []uint64{3, 5, 7, 9, 10, 11, 13, 19, 21, 25, 27, 37, 41, 45, 73, 81}, oponly: "mul"},
{name: "int32", sn: "32", i: []int64{-0x80000000, -0x7FFFFFFF, -1, 0,
1, 0x7FFFFFFF}},
{name: "int32", sn: "32", i: []int64{-9, -5, -3, 3, 5, 7, 9, 10, 11, 13, 19, 21, 25, 27, 37, 41, 45, 73, 81}, oponly: "mul"},
{name: "uint16", sn: "16", u: []uint64{0, 1, 65535}},
{name: "int16", sn: "16", i: []int64{-32768, -32767, -1, 0, 1, 32766, 32767}},
......@@ -162,6 +169,9 @@ func {{.Name}}_{{.FNumber}}_{{.Type_}}(a {{.Type_}}) {{.Type_}} { return {{.Numb
for _, s := range szs {
for _, o := range ops {
if s.oponly != "" && s.oponly != o.name {
continue
}
fd := fncData{o.name, s.name, o.symbol, "", ""}
// unsigned test cases
......@@ -218,17 +228,20 @@ func {{.Name}}_{{.FNumber}}_{{.Type_}}(a {{.Type_}}) {{.Type_}} { return {{.Numb
}
for _, s := range szs {
fmt.Fprintf(w, `
type test_%[1]s struct {
type test_%[1]s%[2]s struct {
fn func (%[1]s) %[1]s
fnname string
in %[1]s
want %[1]s
}
`, s.name)
fmt.Fprintf(w, "var tests_%[1]s =[]test_%[1]s {\n\n", s.name)
`, s.name, s.oponly)
fmt.Fprintf(w, "var tests_%[1]s%[2]s =[]test_%[1]s {\n\n", s.name, s.oponly)
if len(s.u) > 0 {
for _, o := range ops {
if s.oponly != "" && s.oponly != o.name {
continue
}
fd := cfncData{s.name, o.name, s.name, o.symbol, "", "", "", ""}
for _, i := range s.u {
fd.Number = fmt.Sprintf("%d", i)
......@@ -262,6 +275,9 @@ type test_%[1]s struct {
// signed
if len(s.i) > 0 {
for _, o := range ops {
if s.oponly != "" && s.oponly != o.name {
continue
}
// don't generate tests for shifts by signed integers
if o.name == "lsh" || o.name == "rsh" {
continue
......@@ -303,7 +319,7 @@ func main() {
`)
for _, s := range szs {
fmt.Fprintf(w, `for _, test := range tests_%s {`, s.name)
fmt.Fprintf(w, `for _, test := range tests_%s%s {`, s.name, s.oponly)
// Use WriteString here to avoid a vet warning about formatting directives.
w.WriteString(`if got := test.fn(test.in); got != test.want {
fmt.Printf("%s(%d) = %d, want %d\n", test.fnname, test.in, got, test.want)
......
......@@ -495,24 +495,34 @@
// strength reduction
// Assumes that the following costs from https://gmplib.org/~tege/x86-timing.pdf:
// 1 - addq, shlq, leaq, negq
// 3 - imulq
// 1 - addl, shll, leal, negl, subl
// 3 - imull
// This limits the rewrites to two instructions.
// TODO: 27, 81
// Note that negl always operates in-place,
// which can require a register-register move
// to preserve the original value,
// so it must be used with care.
(MULLconst [-9] x) -> (NEGL (LEAL8 <v.Type> x x))
(MULLconst [-5] x) -> (NEGL (LEAL4 <v.Type> x x))
(MULLconst [-3] x) -> (NEGL (LEAL2 <v.Type> x x))
(MULLconst [-1] x) -> (NEGL x)
(MULLconst [0] _) -> (MOVLconst [0])
(MULLconst [1] x) -> x
(MULLconst [3] x) -> (LEAL2 x x)
(MULLconst [5] x) -> (LEAL4 x x)
(MULLconst [7] x) -> (LEAL8 (NEGL <v.Type> x) x)
(MULLconst [7] x) -> (LEAL2 x (LEAL2 <v.Type> x x))
(MULLconst [9] x) -> (LEAL8 x x)
(MULLconst [11] x) -> (LEAL2 x (LEAL4 <v.Type> x x))
(MULLconst [13] x) -> (LEAL4 x (LEAL2 <v.Type> x x))
(MULLconst [19] x) -> (LEAL2 x (LEAL8 <v.Type> x x))
(MULLconst [21] x) -> (LEAL4 x (LEAL4 <v.Type> x x))
(MULLconst [25] x) -> (LEAL8 x (LEAL2 <v.Type> x x))
(MULLconst [27] x) -> (LEAL8 (LEAL2 <v.Type> x x) (LEAL2 <v.Type> x x))
(MULLconst [37] x) -> (LEAL4 x (LEAL8 <v.Type> x x))
(MULLconst [41] x) -> (LEAL8 x (LEAL4 <v.Type> x x))
(MULLconst [45] x) -> (LEAL8 (LEAL4 <v.Type> x x) (LEAL4 <v.Type> x x))
(MULLconst [73] x) -> (LEAL8 x (LEAL8 <v.Type> x x))
(MULLconst [81] x) -> (LEAL8 (LEAL8 <v.Type> x x) (LEAL8 <v.Type> x x))
(MULLconst [c] x) && isPowerOfTwo(c+1) && c >= 15 -> (SUBL (SHLLconst <v.Type> [log2(c+1)] x) x)
(MULLconst [c] x) && isPowerOfTwo(c-1) && c >= 17 -> (LEAL1 (SHLLconst <v.Type> [log2(c-1)] x) x)
......
......@@ -954,24 +954,34 @@
// strength reduction
// Assumes that the following costs from https://gmplib.org/~tege/x86-timing.pdf:
// 1 - addq, shlq, leaq, negq
// 1 - addq, shlq, leaq, negq, subq
// 3 - imulq
// This limits the rewrites to two instructions.
// TODO: 27, 81
// Note that negq always operates in-place,
// which can require a register-register move
// to preserve the original value,
// so it must be used with care.
(MULQconst [-9] x) -> (NEGQ (LEAQ8 <v.Type> x x))
(MULQconst [-5] x) -> (NEGQ (LEAQ4 <v.Type> x x))
(MULQconst [-3] x) -> (NEGQ (LEAQ2 <v.Type> x x))
(MULQconst [-1] x) -> (NEGQ x)
(MULQconst [0] _) -> (MOVQconst [0])
(MULQconst [1] x) -> x
(MULQconst [3] x) -> (LEAQ2 x x)
(MULQconst [5] x) -> (LEAQ4 x x)
(MULQconst [7] x) -> (LEAQ8 (NEGQ <v.Type> x) x)
(MULQconst [7] x) -> (LEAQ2 x (LEAQ2 <v.Type> x x))
(MULQconst [9] x) -> (LEAQ8 x x)
(MULQconst [11] x) -> (LEAQ2 x (LEAQ4 <v.Type> x x))
(MULQconst [13] x) -> (LEAQ4 x (LEAQ2 <v.Type> x x))
(MULQconst [19] x) -> (LEAQ2 x (LEAQ8 <v.Type> x x))
(MULQconst [21] x) -> (LEAQ4 x (LEAQ4 <v.Type> x x))
(MULQconst [25] x) -> (LEAQ8 x (LEAQ2 <v.Type> x x))
(MULQconst [27] x) -> (LEAQ8 (LEAQ2 <v.Type> x x) (LEAQ2 <v.Type> x x))
(MULQconst [37] x) -> (LEAQ4 x (LEAQ8 <v.Type> x x))
(MULQconst [41] x) -> (LEAQ8 x (LEAQ4 <v.Type> x x))
(MULQconst [45] x) -> (LEAQ8 (LEAQ4 <v.Type> x x) (LEAQ4 <v.Type> x x))
(MULQconst [73] x) -> (LEAQ8 x (LEAQ8 <v.Type> x x))
(MULQconst [81] x) -> (LEAQ8 (LEAQ8 <v.Type> x x) (LEAQ8 <v.Type> x x))
(MULQconst [c] x) && isPowerOfTwo(c+1) && c >= 15 -> (SUBQ (SHLQconst <v.Type> [log2(c+1)] x) x)
(MULQconst [c] x) && isPowerOfTwo(c-1) && c >= 17 -> (LEAQ1 (SHLQconst <v.Type> [log2(c-1)] x) x)
......
......@@ -140,7 +140,7 @@ func rewriteValue386(v *Value) bool {
case Op386MULL:
return rewriteValue386_Op386MULL_0(v)
case Op386MULLconst:
return rewriteValue386_Op386MULLconst_0(v) || rewriteValue386_Op386MULLconst_10(v) || rewriteValue386_Op386MULLconst_20(v)
return rewriteValue386_Op386MULLconst_0(v) || rewriteValue386_Op386MULLconst_10(v) || rewriteValue386_Op386MULLconst_20(v) || rewriteValue386_Op386MULLconst_30(v)
case Op386NEGL:
return rewriteValue386_Op386NEGL_0(v)
case Op386NOTL:
......@@ -8339,6 +8339,51 @@ func rewriteValue386_Op386MULLconst_0(v *Value) bool {
v.AddArg(x)
return true
}
// match: (MULLconst [-9] x)
// cond:
// result: (NEGL (LEAL8 <v.Type> x x))
for {
if v.AuxInt != -9 {
break
}
x := v.Args[0]
v.reset(Op386NEGL)
v0 := b.NewValue0(v.Pos, Op386LEAL8, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (MULLconst [-5] x)
// cond:
// result: (NEGL (LEAL4 <v.Type> x x))
for {
if v.AuxInt != -5 {
break
}
x := v.Args[0]
v.reset(Op386NEGL)
v0 := b.NewValue0(v.Pos, Op386LEAL4, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (MULLconst [-3] x)
// cond:
// result: (NEGL (LEAL2 <v.Type> x x))
for {
if v.AuxInt != -3 {
break
}
x := v.Args[0]
v.reset(Op386NEGL)
v0 := b.NewValue0(v.Pos, Op386LEAL2, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (MULLconst [-1] x)
// cond:
// result: (NEGL x)
......@@ -8403,19 +8448,25 @@ func rewriteValue386_Op386MULLconst_0(v *Value) bool {
}
// match: (MULLconst [7] x)
// cond:
// result: (LEAL8 (NEGL <v.Type> x) x)
// result: (LEAL2 x (LEAL2 <v.Type> x x))
for {
if v.AuxInt != 7 {
break
}
x := v.Args[0]
v.reset(Op386LEAL8)
v0 := b.NewValue0(v.Pos, Op386NEGL, v.Type)
v.reset(Op386LEAL2)
v.AddArg(x)
v0 := b.NewValue0(v.Pos, Op386LEAL2, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
v.AddArg(x)
return true
}
return false
}
func rewriteValue386_Op386MULLconst_10(v *Value) bool {
b := v.Block
_ = b
// match: (MULLconst [9] x)
// cond:
// result: (LEAL8 x x)
......@@ -8461,11 +8512,22 @@ func rewriteValue386_Op386MULLconst_0(v *Value) bool {
v.AddArg(v0)
return true
}
return false
}
func rewriteValue386_Op386MULLconst_10(v *Value) bool {
b := v.Block
_ = b
// match: (MULLconst [19] x)
// cond:
// result: (LEAL2 x (LEAL8 <v.Type> x x))
for {
if v.AuxInt != 19 {
break
}
x := v.Args[0]
v.reset(Op386LEAL2)
v.AddArg(x)
v0 := b.NewValue0(v.Pos, Op386LEAL8, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (MULLconst [21] x)
// cond:
// result: (LEAL4 x (LEAL4 <v.Type> x x))
......@@ -8498,6 +8560,25 @@ func rewriteValue386_Op386MULLconst_10(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (MULLconst [27] x)
// cond:
// result: (LEAL8 (LEAL2 <v.Type> x x) (LEAL2 <v.Type> x x))
for {
if v.AuxInt != 27 {
break
}
x := v.Args[0]
v.reset(Op386LEAL8)
v0 := b.NewValue0(v.Pos, Op386LEAL2, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
v1 := b.NewValue0(v.Pos, Op386LEAL2, v.Type)
v1.AddArg(x)
v1.AddArg(x)
v.AddArg(v1)
return true
}
// match: (MULLconst [37] x)
// cond:
// result: (LEAL4 x (LEAL8 <v.Type> x x))
......@@ -8530,6 +8611,30 @@ func rewriteValue386_Op386MULLconst_10(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (MULLconst [45] x)
// cond:
// result: (LEAL8 (LEAL4 <v.Type> x x) (LEAL4 <v.Type> x x))
for {
if v.AuxInt != 45 {
break
}
x := v.Args[0]
v.reset(Op386LEAL8)
v0 := b.NewValue0(v.Pos, Op386LEAL4, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
v1 := b.NewValue0(v.Pos, Op386LEAL4, v.Type)
v1.AddArg(x)
v1.AddArg(x)
v.AddArg(v1)
return true
}
return false
}
func rewriteValue386_Op386MULLconst_20(v *Value) bool {
b := v.Block
_ = b
// match: (MULLconst [73] x)
// cond:
// result: (LEAL8 x (LEAL8 <v.Type> x x))
......@@ -8546,6 +8651,25 @@ func rewriteValue386_Op386MULLconst_10(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (MULLconst [81] x)
// cond:
// result: (LEAL8 (LEAL8 <v.Type> x x) (LEAL8 <v.Type> x x))
for {
if v.AuxInt != 81 {
break
}
x := v.Args[0]
v.reset(Op386LEAL8)
v0 := b.NewValue0(v.Pos, Op386LEAL8, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
v1 := b.NewValue0(v.Pos, Op386LEAL8, v.Type)
v1.AddArg(x)
v1.AddArg(x)
v.AddArg(v1)
return true
}
// match: (MULLconst [c] x)
// cond: isPowerOfTwo(c+1) && c >= 15
// result: (SUBL (SHLLconst <v.Type> [log2(c+1)] x) x)
......@@ -8631,11 +8755,6 @@ func rewriteValue386_Op386MULLconst_10(v *Value) bool {
v.AddArg(x)
return true
}
return false
}
func rewriteValue386_Op386MULLconst_20(v *Value) bool {
b := v.Block
_ = b
// match: (MULLconst [c] x)
// cond: c%3 == 0 && isPowerOfTwo(c/3)
// result: (SHLLconst [log2(c/3)] (LEAL2 <v.Type> x x))
......@@ -8687,6 +8806,9 @@ func rewriteValue386_Op386MULLconst_20(v *Value) bool {
v.AddArg(v0)
return true
}
return false
}
func rewriteValue386_Op386MULLconst_30(v *Value) bool {
// match: (MULLconst [c] (MOVLconst [d]))
// cond:
// result: (MOVLconst [int64(int32(c*d))])
......
......@@ -300,7 +300,7 @@ func rewriteValueAMD64(v *Value) bool {
case OpAMD64MULQ:
return rewriteValueAMD64_OpAMD64MULQ_0(v)
case OpAMD64MULQconst:
return rewriteValueAMD64_OpAMD64MULQconst_0(v) || rewriteValueAMD64_OpAMD64MULQconst_10(v) || rewriteValueAMD64_OpAMD64MULQconst_20(v)
return rewriteValueAMD64_OpAMD64MULQconst_0(v) || rewriteValueAMD64_OpAMD64MULQconst_10(v) || rewriteValueAMD64_OpAMD64MULQconst_20(v) || rewriteValueAMD64_OpAMD64MULQconst_30(v)
case OpAMD64MULSD:
return rewriteValueAMD64_OpAMD64MULSD_0(v)
case OpAMD64MULSDmem:
......@@ -19190,6 +19190,51 @@ func rewriteValueAMD64_OpAMD64MULQconst_0(v *Value) bool {
v.AddArg(x)
return true
}
// match: (MULQconst [-9] x)
// cond:
// result: (NEGQ (LEAQ8 <v.Type> x x))
for {
if v.AuxInt != -9 {
break
}
x := v.Args[0]
v.reset(OpAMD64NEGQ)
v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (MULQconst [-5] x)
// cond:
// result: (NEGQ (LEAQ4 <v.Type> x x))
for {
if v.AuxInt != -5 {
break
}
x := v.Args[0]
v.reset(OpAMD64NEGQ)
v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (MULQconst [-3] x)
// cond:
// result: (NEGQ (LEAQ2 <v.Type> x x))
for {
if v.AuxInt != -3 {
break
}
x := v.Args[0]
v.reset(OpAMD64NEGQ)
v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (MULQconst [-1] x)
// cond:
// result: (NEGQ x)
......@@ -19254,19 +19299,25 @@ func rewriteValueAMD64_OpAMD64MULQconst_0(v *Value) bool {
}
// match: (MULQconst [7] x)
// cond:
// result: (LEAQ8 (NEGQ <v.Type> x) x)
// result: (LEAQ2 x (LEAQ2 <v.Type> x x))
for {
if v.AuxInt != 7 {
break
}
x := v.Args[0]
v.reset(OpAMD64LEAQ8)
v0 := b.NewValue0(v.Pos, OpAMD64NEGQ, v.Type)
v.reset(OpAMD64LEAQ2)
v.AddArg(x)
v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
v.AddArg(x)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64MULQconst_10(v *Value) bool {
b := v.Block
_ = b
// match: (MULQconst [9] x)
// cond:
// result: (LEAQ8 x x)
......@@ -19312,11 +19363,22 @@ func rewriteValueAMD64_OpAMD64MULQconst_0(v *Value) bool {
v.AddArg(v0)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64MULQconst_10(v *Value) bool {
b := v.Block
_ = b
// match: (MULQconst [19] x)
// cond:
// result: (LEAQ2 x (LEAQ8 <v.Type> x x))
for {
if v.AuxInt != 19 {
break
}
x := v.Args[0]
v.reset(OpAMD64LEAQ2)
v.AddArg(x)
v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (MULQconst [21] x)
// cond:
// result: (LEAQ4 x (LEAQ4 <v.Type> x x))
......@@ -19349,6 +19411,25 @@ func rewriteValueAMD64_OpAMD64MULQconst_10(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (MULQconst [27] x)
// cond:
// result: (LEAQ8 (LEAQ2 <v.Type> x x) (LEAQ2 <v.Type> x x))
for {
if v.AuxInt != 27 {
break
}
x := v.Args[0]
v.reset(OpAMD64LEAQ8)
v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
v1 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type)
v1.AddArg(x)
v1.AddArg(x)
v.AddArg(v1)
return true
}
// match: (MULQconst [37] x)
// cond:
// result: (LEAQ4 x (LEAQ8 <v.Type> x x))
......@@ -19381,6 +19462,30 @@ func rewriteValueAMD64_OpAMD64MULQconst_10(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (MULQconst [45] x)
// cond:
// result: (LEAQ8 (LEAQ4 <v.Type> x x) (LEAQ4 <v.Type> x x))
for {
if v.AuxInt != 45 {
break
}
x := v.Args[0]
v.reset(OpAMD64LEAQ8)
v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
v1 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type)
v1.AddArg(x)
v1.AddArg(x)
v.AddArg(v1)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64MULQconst_20(v *Value) bool {
b := v.Block
_ = b
// match: (MULQconst [73] x)
// cond:
// result: (LEAQ8 x (LEAQ8 <v.Type> x x))
......@@ -19397,6 +19502,25 @@ func rewriteValueAMD64_OpAMD64MULQconst_10(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (MULQconst [81] x)
// cond:
// result: (LEAQ8 (LEAQ8 <v.Type> x x) (LEAQ8 <v.Type> x x))
for {
if v.AuxInt != 81 {
break
}
x := v.Args[0]
v.reset(OpAMD64LEAQ8)
v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type)
v0.AddArg(x)
v0.AddArg(x)
v.AddArg(v0)
v1 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type)
v1.AddArg(x)
v1.AddArg(x)
v.AddArg(v1)
return true
}
// match: (MULQconst [c] x)
// cond: isPowerOfTwo(c+1) && c >= 15
// result: (SUBQ (SHLQconst <v.Type> [log2(c+1)] x) x)
......@@ -19482,11 +19606,6 @@ func rewriteValueAMD64_OpAMD64MULQconst_10(v *Value) bool {
v.AddArg(x)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64MULQconst_20(v *Value) bool {
b := v.Block
_ = b
// match: (MULQconst [c] x)
// cond: c%3 == 0 && isPowerOfTwo(c/3)
// result: (SHLQconst [log2(c/3)] (LEAQ2 <v.Type> x x))
......@@ -19538,6 +19657,9 @@ func rewriteValueAMD64_OpAMD64MULQconst_20(v *Value) bool {
v.AddArg(v0)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64MULQconst_30(v *Value) bool {
// match: (MULQconst [c] (MOVQconst [d]))
// cond:
// result: (MOVQconst [c*d])
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment