1
0
mirror of https://github.com/golang/go synced 2024-11-12 06:30:21 -07:00

cmd/compile: constant fold more of IsInBounds and IsSliceInBounds

Fixes #14721

Change-Id: Id1d5a819e5c242b91a37c4e464ed3f00c691aff5
Reviewed-on: https://go-review.googlesource.com/20482
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Alexandru Moșoi <alexandru@mosoi.ro>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Alexandru Moșoi 2016-03-09 11:00:58 +01:00 committed by Alexandru Moșoi
parent b594b8b039
commit bbd3ffbd83
2 changed files with 135 additions and 3 deletions

View File

@ -77,8 +77,12 @@
(Rsh8x64 (Const8 [0]) _) -> (Const8 [0]) (Rsh8x64 (Const8 [0]) _) -> (Const8 [0])
(Rsh8Ux64 (Const8 [0]) _) -> (Const8 [0]) (Rsh8Ux64 (Const8 [0]) _) -> (Const8 [0])
(IsInBounds (And32 (Const32 [c]) _) (Const32 [d])) && inBounds32(c, d) -> (ConstBool [1])
(IsInBounds (And64 (Const64 [c]) _) (Const64 [d])) && inBounds64(c, d) -> (ConstBool [1])
(IsInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(inBounds32(c,d))]) (IsInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(inBounds32(c,d))])
(IsInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(inBounds64(c,d))]) (IsInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(inBounds64(c,d))])
(IsSliceInBounds (And32 (Const32 [c]) _) (Const32 [d])) && sliceInBounds32(c, d) -> (ConstBool [1])
(IsSliceInBounds (And64 (Const64 [c]) _) (Const64 [d])) && sliceInBounds64(c, d) -> (ConstBool [1])
(IsSliceInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(sliceInBounds32(c,d))]) (IsSliceInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(sliceInBounds32(c,d))])
(IsSliceInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(sliceInBounds64(c,d))]) (IsSliceInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(sliceInBounds64(c,d))])
@ -664,9 +668,9 @@
//(Mod64 n (Const64 [1])) -> (Const64 [0]) //(Mod64 n (Const64 [1])) -> (Const64 [0])
//(Mod64u n (Const64 [1])) -> (Const64 [0]) //(Mod64u n (Const64 [1])) -> (Const64 [0])
// Unsigned divide by power of 2. Currently handled by frontend. // Unsigned divide by power of 2.
//(Div64u <t> n (Const64 [c])) && isPowerOfTwo(c) -> (Rsh64Ux64 n (Const64 <t> [log2(c)])) (Div64u <t> n (Const64 [c])) && isPowerOfTwo(c) -> (Rsh64Ux64 n (Const64 <t> [log2(c)]))
//(Mod64u <t> n (Const64 [c])) && isPowerOfTwo(c) -> (And64 n (Const64 <t> [c-1])) (Mod64u <t> n (Const64 [c])) && isPowerOfTwo(c) -> (And64 n (Const64 <t> [c-1]))
// Signed divide by power of 2. Currently handled by frontend. // Signed divide by power of 2. Currently handled by frontend.
// n / c = n >> log(c) if n >= 0 // n / c = n >> log(c) if n >= 0

View File

@ -1577,6 +1577,26 @@ func rewriteValuegeneric_OpDiv64(v *Value, config *Config) bool {
func rewriteValuegeneric_OpDiv64u(v *Value, config *Config) bool { func rewriteValuegeneric_OpDiv64u(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (Div64u <t> n (Const64 [c]))
// cond: isPowerOfTwo(c)
// result: (Rsh64Ux64 n (Const64 <t> [log2(c)]))
for {
t := v.Type
n := v.Args[0]
if v.Args[1].Op != OpConst64 {
break
}
c := v.Args[1].AuxInt
if !(isPowerOfTwo(c)) {
break
}
v.reset(OpRsh64Ux64)
v.AddArg(n)
v0 := b.NewValue0(v.Line, OpConst64, t)
v0.AuxInt = log2(c)
v.AddArg(v0)
return true
}
// match: (Div64u <t> x (Const64 [c])) // match: (Div64u <t> x (Const64 [c]))
// cond: umagic64ok(c) && !umagic64a(c) // cond: umagic64ok(c) && !umagic64a(c)
// result: (Rsh64Ux64 (Hmul64u <t> (Const64 <t> [umagic64m(c)]) x) (Const64 <t> [umagic64s(c)])) // result: (Rsh64Ux64 (Hmul64u <t> (Const64 <t> [umagic64m(c)]) x) (Const64 <t> [umagic64s(c)]))
@ -2467,6 +2487,50 @@ func rewriteValuegeneric_OpITab(v *Value, config *Config) bool {
func rewriteValuegeneric_OpIsInBounds(v *Value, config *Config) bool { func rewriteValuegeneric_OpIsInBounds(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (IsInBounds (And32 (Const32 [c]) _) (Const32 [d]))
// cond: inBounds32(c, d)
// result: (ConstBool [1])
for {
if v.Args[0].Op != OpAnd32 {
break
}
if v.Args[0].Args[0].Op != OpConst32 {
break
}
c := v.Args[0].Args[0].AuxInt
if v.Args[1].Op != OpConst32 {
break
}
d := v.Args[1].AuxInt
if !(inBounds32(c, d)) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsInBounds (And64 (Const64 [c]) _) (Const64 [d]))
// cond: inBounds64(c, d)
// result: (ConstBool [1])
for {
if v.Args[0].Op != OpAnd64 {
break
}
if v.Args[0].Args[0].Op != OpConst64 {
break
}
c := v.Args[0].Args[0].AuxInt
if v.Args[1].Op != OpConst64 {
break
}
d := v.Args[1].AuxInt
if !(inBounds64(c, d)) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsInBounds (Const32 [c]) (Const32 [d])) // match: (IsInBounds (Const32 [c]) (Const32 [d]))
// cond: // cond:
// result: (ConstBool [b2i(inBounds32(c,d))]) // result: (ConstBool [b2i(inBounds32(c,d))])
@ -2504,6 +2568,50 @@ func rewriteValuegeneric_OpIsInBounds(v *Value, config *Config) bool {
func rewriteValuegeneric_OpIsSliceInBounds(v *Value, config *Config) bool { func rewriteValuegeneric_OpIsSliceInBounds(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (IsSliceInBounds (And32 (Const32 [c]) _) (Const32 [d]))
// cond: sliceInBounds32(c, d)
// result: (ConstBool [1])
for {
if v.Args[0].Op != OpAnd32 {
break
}
if v.Args[0].Args[0].Op != OpConst32 {
break
}
c := v.Args[0].Args[0].AuxInt
if v.Args[1].Op != OpConst32 {
break
}
d := v.Args[1].AuxInt
if !(sliceInBounds32(c, d)) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsSliceInBounds (And64 (Const64 [c]) _) (Const64 [d]))
// cond: sliceInBounds64(c, d)
// result: (ConstBool [1])
for {
if v.Args[0].Op != OpAnd64 {
break
}
if v.Args[0].Args[0].Op != OpConst64 {
break
}
c := v.Args[0].Args[0].AuxInt
if v.Args[1].Op != OpConst64 {
break
}
d := v.Args[1].AuxInt
if !(sliceInBounds64(c, d)) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsSliceInBounds (Const32 [c]) (Const32 [d])) // match: (IsSliceInBounds (Const32 [c]) (Const32 [d]))
// cond: // cond:
// result: (ConstBool [b2i(sliceInBounds32(c,d))]) // result: (ConstBool [b2i(sliceInBounds32(c,d))])
@ -3875,6 +3983,26 @@ func rewriteValuegeneric_OpMod64(v *Value, config *Config) bool {
func rewriteValuegeneric_OpMod64u(v *Value, config *Config) bool { func rewriteValuegeneric_OpMod64u(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (Mod64u <t> n (Const64 [c]))
// cond: isPowerOfTwo(c)
// result: (And64 n (Const64 <t> [c-1]))
for {
t := v.Type
n := v.Args[0]
if v.Args[1].Op != OpConst64 {
break
}
c := v.Args[1].AuxInt
if !(isPowerOfTwo(c)) {
break
}
v.reset(OpAnd64)
v.AddArg(n)
v0 := b.NewValue0(v.Line, OpConst64, t)
v0.AuxInt = c - 1
v.AddArg(v0)
return true
}
// match: (Mod64u <t> x (Const64 [c])) // match: (Mod64u <t> x (Const64 [c]))
// cond: umagic64ok(c) // cond: umagic64ok(c)
// result: (Sub64 x (Mul64 <t> (Div64u <t> x (Const64 <t> [c])) (Const64 <t> [c]))) // result: (Sub64 x (Mul64 <t> (Div64u <t> x (Const64 <t> [c])) (Const64 <t> [c])))