[dev.ssa] cmd/compiler: rewrite AND x const as a shift if possible
ANDs of constants whose only set bits are leading or trailing can be
rewritten as two shifts instead. This is slightly faster for 32 or
64 bit operands.
Change-Id: Id5c1ff27e5a4df22fac67b03b9bddb944871145d
Reviewed-on: https://go-review.googlesource.com/19485
Run-TryBot: Todd Neal <todd@tneal.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go
index 0d90523..72b3553 100644
--- a/src/cmd/compile/internal/ssa/rewritegeneric.go
+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go
@@ -676,6 +676,56 @@
v.AuxInt = 0
return true
}
+ // match: (And32 <t> (Const32 [y]) x)
+ // cond: nlz(int64(int32(y))) + nto(int64(int32(y))) == 64
+ // result: (Rsh32Ux32 (Lsh32x32 <t> x (Const32 <t> [nlz(int64(int32(y)))-32])) (Const32 <t> [nlz(int64(int32(y)))-32]))
+ for {
+ t := v.Type
+ if v.Args[0].Op != OpConst32 {
+ break
+ }
+ y := v.Args[0].AuxInt
+ x := v.Args[1]
+ if !(nlz(int64(int32(y)))+nto(int64(int32(y))) == 64) {
+ break
+ }
+ v.reset(OpRsh32Ux32)
+ v0 := b.NewValue0(v.Line, OpLsh32x32, t)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Line, OpConst32, t)
+ v1.AuxInt = nlz(int64(int32(y))) - 32
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ v2 := b.NewValue0(v.Line, OpConst32, t)
+ v2.AuxInt = nlz(int64(int32(y))) - 32
+ v.AddArg(v2)
+ return true
+ }
+ // match: (And32 <t> (Const32 [y]) x)
+ // cond: nlo(int64(int32(y))) + ntz(int64(int32(y))) == 64
+ // result: (Lsh32x32 (Rsh32Ux32 <t> x (Const32 <t> [ntz(int64(int32(y)))])) (Const32 <t> [ntz(int64(int32(y)))]))
+ for {
+ t := v.Type
+ if v.Args[0].Op != OpConst32 {
+ break
+ }
+ y := v.Args[0].AuxInt
+ x := v.Args[1]
+ if !(nlo(int64(int32(y)))+ntz(int64(int32(y))) == 64) {
+ break
+ }
+ v.reset(OpLsh32x32)
+ v0 := b.NewValue0(v.Line, OpRsh32Ux32, t)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Line, OpConst32, t)
+ v1.AuxInt = ntz(int64(int32(y)))
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ v2 := b.NewValue0(v.Line, OpConst32, t)
+ v2.AuxInt = ntz(int64(int32(y)))
+ v.AddArg(v2)
+ return true
+ }
return false
}
func rewriteValuegeneric_OpAnd64(v *Value, config *Config) bool {
@@ -744,6 +794,56 @@
v.AuxInt = 0
return true
}
+ // match: (And64 <t> (Const64 [y]) x)
+ // cond: nlz(y) + nto(y) == 64
+ // result: (Rsh64Ux64 (Lsh64x64 <t> x (Const64 <t> [nlz(y)])) (Const64 <t> [nlz(y)]))
+ for {
+ t := v.Type
+ if v.Args[0].Op != OpConst64 {
+ break
+ }
+ y := v.Args[0].AuxInt
+ x := v.Args[1]
+ if !(nlz(y)+nto(y) == 64) {
+ break
+ }
+ v.reset(OpRsh64Ux64)
+ v0 := b.NewValue0(v.Line, OpLsh64x64, t)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Line, OpConst64, t)
+ v1.AuxInt = nlz(y)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ v2 := b.NewValue0(v.Line, OpConst64, t)
+ v2.AuxInt = nlz(y)
+ v.AddArg(v2)
+ return true
+ }
+ // match: (And64 <t> (Const64 [y]) x)
+ // cond: nlo(y) + ntz(y) == 64
+ // result: (Lsh64x64 (Rsh64Ux64 <t> x (Const64 <t> [ntz(y)])) (Const64 <t> [ntz(y)]))
+ for {
+ t := v.Type
+ if v.Args[0].Op != OpConst64 {
+ break
+ }
+ y := v.Args[0].AuxInt
+ x := v.Args[1]
+ if !(nlo(y)+ntz(y) == 64) {
+ break
+ }
+ v.reset(OpLsh64x64)
+ v0 := b.NewValue0(v.Line, OpRsh64Ux64, t)
+ v0.AddArg(x)
+ v1 := b.NewValue0(v.Line, OpConst64, t)
+ v1.AuxInt = ntz(y)
+ v0.AddArg(v1)
+ v.AddArg(v0)
+ v2 := b.NewValue0(v.Line, OpConst64, t)
+ v2.AuxInt = ntz(y)
+ v.AddArg(v2)
+ return true
+ }
return false
}
func rewriteValuegeneric_OpAnd8(v *Value, config *Config) bool {