1
0
mirror of https://github.com/golang/go synced 2024-11-26 15:06:52 -07:00

[dev.ssa] cmd/compile/internal/ssa/gen: generalize strength reduction.

Handle multiplication with -1, 0, 3, 5, 9 and all powers of two.

Change-Id: I8e87e7670dae389aebf6f446d7a56950cacb59e0
Reviewed-on: https://go-review.googlesource.com/12350
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Alexandru Moșoi 2015-07-17 12:26:35 +02:00 committed by Keith Randall
parent 954d5ada29
commit 3e7e519c36
3 changed files with 129 additions and 18 deletions

View File

@ -131,9 +131,13 @@
(CMPQ (MOVQconst [c]) x) -> (InvertFlags (CMPQconst <TypeFlags> x [c]))
// strength reduction
// TODO: do this a lot more generically
(MULQconst [8] x) -> (SHLQconst [3] x)
(MULQconst [64] x) -> (SHLQconst [6] x)
(MULQconst [-1] x) -> (NEGQ x)
(MULQconst [0] _) -> (MOVQconst [0])
(MULQconst [1] x) -> (Copy x)
(MULQconst [3] x) -> (LEAQ2 x x)
(MULQconst [5] x) -> (LEAQ4 x x)
(MULQconst [9] x) -> (LEAQ8 x x)
(MULQconst [c] x) && isPowerOfTwo(c) -> (SHLQconst [log2(c)] x)
// fold add/shift into leaq
(ADDQ x (SHLQconst [3] y)) -> (LEAQ8 x y)

View File

@ -119,3 +119,18 @@ func mergeSym(x, y interface{}) interface{} {
func inBounds(idx, len int64) bool {
return idx >= 0 && idx < len
}
// log2 returns logarithm in base of n.
// expects n to be a power of 2.
func log2(n int64) (l int64) {
for n > 1 {
l++
n >>= 1
}
return l
}
// isPowerOfTwo returns true if n is a power of 2.
func isPowerOfTwo(n int64) bool {
return n > 0 && n&(n-1) == 0
}

View File

@ -1200,43 +1200,135 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
endc6e18d6968175d6e58eafa6dcf40c1b8:
;
case OpAMD64MULQconst:
// match: (MULQconst [8] x)
// match: (MULQconst [-1] x)
// cond:
// result: (SHLQconst [3] x)
// result: (NEGQ x)
{
if v.AuxInt != 8 {
goto ende8d313a52a134fb2e1c0beb54ea599fd
if v.AuxInt != -1 {
goto end82501cca6b5fb121a7f8b197e55f2fec
}
x := v.Args[0]
v.Op = OpAMD64SHLQconst
v.Op = OpAMD64NEGQ
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
v.AuxInt = 3
v.AddArg(x)
return true
}
goto ende8d313a52a134fb2e1c0beb54ea599fd
ende8d313a52a134fb2e1c0beb54ea599fd:
goto end82501cca6b5fb121a7f8b197e55f2fec
end82501cca6b5fb121a7f8b197e55f2fec:
;
// match: (MULQconst [64] x)
// match: (MULQconst [0] _)
// cond:
// result: (SHLQconst [6] x)
// result: (MOVQconst [0])
{
if v.AuxInt != 64 {
goto end3e36a587d1e7c193048d489a0429692c
if v.AuxInt != 0 {
goto endcb9faa068e3558ff44daaf1d47d091b5
}
v.Op = OpAMD64MOVQconst
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
v.AuxInt = 0
return true
}
goto endcb9faa068e3558ff44daaf1d47d091b5
endcb9faa068e3558ff44daaf1d47d091b5:
;
// match: (MULQconst [1] x)
// cond:
// result: (Copy x)
{
if v.AuxInt != 1 {
goto endd7217a7c6311fc7a3e0736a1b0b5be73
}
x := v.Args[0]
v.Op = OpCopy
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
v.AddArg(x)
return true
}
goto endd7217a7c6311fc7a3e0736a1b0b5be73
endd7217a7c6311fc7a3e0736a1b0b5be73:
;
// match: (MULQconst [3] x)
// cond:
// result: (LEAQ2 x x)
{
if v.AuxInt != 3 {
goto end34a86f261671b5852bec6c57155fe0da
}
x := v.Args[0]
v.Op = OpAMD64LEAQ2
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
v.AddArg(x)
v.AddArg(x)
return true
}
goto end34a86f261671b5852bec6c57155fe0da
end34a86f261671b5852bec6c57155fe0da:
;
// match: (MULQconst [5] x)
// cond:
// result: (LEAQ4 x x)
{
if v.AuxInt != 5 {
goto end534601906c45a9171a9fec3e4b82b189
}
x := v.Args[0]
v.Op = OpAMD64LEAQ4
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
v.AddArg(x)
v.AddArg(x)
return true
}
goto end534601906c45a9171a9fec3e4b82b189
end534601906c45a9171a9fec3e4b82b189:
;
// match: (MULQconst [9] x)
// cond:
// result: (LEAQ8 x x)
{
if v.AuxInt != 9 {
goto end48a2280b6459821289c56073b8354997
}
x := v.Args[0]
v.Op = OpAMD64LEAQ8
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
v.AddArg(x)
v.AddArg(x)
return true
}
goto end48a2280b6459821289c56073b8354997
end48a2280b6459821289c56073b8354997:
;
// match: (MULQconst [c] x)
// cond: isPowerOfTwo(c)
// result: (SHLQconst [log2(c)] x)
{
c := v.AuxInt
x := v.Args[0]
if !(isPowerOfTwo(c)) {
goto end75076953dbfe022526a153eda99b39b2
}
v.Op = OpAMD64SHLQconst
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
v.AuxInt = 6
v.AuxInt = log2(c)
v.AddArg(x)
return true
}
goto end3e36a587d1e7c193048d489a0429692c
end3e36a587d1e7c193048d489a0429692c:
goto end75076953dbfe022526a153eda99b39b2
end75076953dbfe022526a153eda99b39b2:
;
case OpMove:
// match: (Move [size] dst src mem)