From 0321cabdfacc5472d2bc650de3e36ca10131b60a Mon Sep 17 00:00:00 2001 From: David Chase Date: Tue, 8 Mar 2016 15:08:25 -0500 Subject: [PATCH] cmd/compile: guard the &-to-<<>> opt against small constants Converting an and-K into a pair of shifts for K that will fit in a one-byte argument is probably not an optimization, and it also interferes with other patterns that we want to see fire, like (<< (AND K)) [for small K] and bounds check elimination for masked indices. Turns out that on Intel, even 32-bit signed immediates beat the shift pair; the size reduction of tool binaries is 0.09% vs 0.07% for only the 8-bit immediates. RLH found this one working on the new/next GC. Change-Id: I2414a8de1dd58d680d18587577fbadb7ff4f67d9 Reviewed-on: https://go-review.googlesource.com/20410 Reviewed-by: Keith Randall Run-TryBot: David Chase --- .../compile/internal/ssa/gen/generic.rules | 8 +-- .../compile/internal/ssa/rewritegeneric.go | 58 ++----------------- 2 files changed, 7 insertions(+), 59 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 57ab70339a..8cb79a0da8 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -366,13 +366,11 @@ (Trunc32to16 (And32 (Const32 [y]) x)) && y&0xFFFF == 0xFFFF -> (Trunc32to16 x) (Trunc16to8 (And16 (Const16 [y]) x)) && y&0xFF == 0xFF -> (Trunc16to8 x) -// Rewrite AND of consts as shifts if possible, slightly faster for 32/64 bit operands +// Rewrite AND of consts as shifts if possible, slightly faster for 64 bit operands // leading zeros can be shifted left, then right -(And64 (Const64 [y]) x) && nlz(y) + nto(y) == 64 -> (Rsh64Ux64 (Lsh64x64 x (Const64 [nlz(y)])) (Const64 [nlz(y)])) -(And32 (Const32 [y]) x) && nlz(int64(int32(y))) + nto(int64(int32(y))) == 64 -> (Rsh32Ux32 (Lsh32x32 x (Const32 [nlz(int64(int32(y)))-32])) (Const32 [nlz(int64(int32(y)))-32])) +(And64 (Const64 [y]) x) && nlz(y) + nto(y) == 64 && nto(y) >= 32 -> (Rsh64Ux64 (Lsh64x64 x (Const64 [nlz(y)])) (Const64 [nlz(y)])) // trailing zeros can be shifted right, then left -(And64 (Const64 [y]) x) && nlo(y) + ntz(y) == 64 -> (Lsh64x64 (Rsh64Ux64 x (Const64 [ntz(y)])) (Const64 [ntz(y)])) -(And32 (Const32 [y]) x) && nlo(int64(int32(y))) + ntz(int64(int32(y))) == 64 -> (Lsh32x32 (Rsh32Ux32 x (Const32 [ntz(int64(int32(y)))])) (Const32 [ntz(int64(int32(y)))])) +(And64 (Const64 [y]) x) && nlo(y) + ntz(y) == 64 && ntz(y) >= 32 -> (Lsh64x64 (Rsh64Ux64 x (Const64 [ntz(y)])) (Const64 [ntz(y)])) // simplifications often used for lengths. e.g. len(s[i:i+5])==5 (Sub64 (Add64 x y) x) -> y diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index cde60c1bcd..122c661114 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -693,56 +693,6 @@ func rewriteValuegeneric_OpAnd32(v *Value, config *Config) bool { v.AuxInt = 0 return true } - // match: (And32 (Const32 [y]) x) - // cond: nlz(int64(int32(y))) + nto(int64(int32(y))) == 64 - // result: (Rsh32Ux32 (Lsh32x32 x (Const32 [nlz(int64(int32(y)))-32])) (Const32 [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 (Const32 [y]) x) - // cond: nlo(int64(int32(y))) + ntz(int64(int32(y))) == 64 - // result: (Lsh32x32 (Rsh32Ux32 x (Const32 [ntz(int64(int32(y)))])) (Const32 [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 { @@ -812,7 +762,7 @@ func rewriteValuegeneric_OpAnd64(v *Value, config *Config) bool { return true } // match: (And64 (Const64 [y]) x) - // cond: nlz(y) + nto(y) == 64 + // cond: nlz(y) + nto(y) == 64 && nto(y) >= 32 // result: (Rsh64Ux64 (Lsh64x64 x (Const64 [nlz(y)])) (Const64 [nlz(y)])) for { t := v.Type @@ -821,7 +771,7 @@ func rewriteValuegeneric_OpAnd64(v *Value, config *Config) bool { } y := v.Args[0].AuxInt x := v.Args[1] - if !(nlz(y)+nto(y) == 64) { + if !(nlz(y)+nto(y) == 64 && nto(y) >= 32) { break } v.reset(OpRsh64Ux64) @@ -837,7 +787,7 @@ func rewriteValuegeneric_OpAnd64(v *Value, config *Config) bool { return true } // match: (And64 (Const64 [y]) x) - // cond: nlo(y) + ntz(y) == 64 + // cond: nlo(y) + ntz(y) == 64 && ntz(y) >= 32 // result: (Lsh64x64 (Rsh64Ux64 x (Const64 [ntz(y)])) (Const64 [ntz(y)])) for { t := v.Type @@ -846,7 +796,7 @@ func rewriteValuegeneric_OpAnd64(v *Value, config *Config) bool { } y := v.Args[0].AuxInt x := v.Args[1] - if !(nlo(y)+ntz(y) == 64) { + if !(nlo(y)+ntz(y) == 64 && ntz(y) >= 32) { break } v.reset(OpLsh64x64) -- 2.48.1