1
0
mirror of https://github.com/golang/go synced 2024-11-18 00:14:47 -07:00

cmd/compile: use right shifts to eliminate bounds checks

These rules trigger a few times during make.bash.
When we eliminate boundedness checks from walk.go
we'll rely on them more heavily.

Updates #19692

Change-Id: I268c36ae2f1401c68dd685b15f2d30f5d6971176
Reviewed-on: https://go-review.googlesource.com/43775
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2017-05-19 15:10:10 -07:00
parent 2fe53d8d55
commit 561b147e4b
2 changed files with 309 additions and 1 deletions

View File

@ -208,6 +208,17 @@
// (Mod64u x y) is always between 0 (inclusive) and y (exclusive). // (Mod64u x y) is always between 0 (inclusive) and y (exclusive).
(IsInBounds (Mod32u _ y) y) -> (ConstBool [1]) (IsInBounds (Mod32u _ y) y) -> (ConstBool [1])
(IsInBounds (Mod64u _ y) y) -> (ConstBool [1]) (IsInBounds (Mod64u _ y) y) -> (ConstBool [1])
// Right shifting a unsigned number limits its value.
(IsInBounds (ZeroExt8to64 (Rsh8Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 8 && 1<<uint( 8-c)-1 < d -> (ConstBool [1])
(IsInBounds (ZeroExt8to32 (Rsh8Ux64 _ (Const64 [c]))) (Const32 [d])) && 0 < c && c < 8 && 1<<uint( 8-c)-1 < d -> (ConstBool [1])
(IsInBounds (ZeroExt8to16 (Rsh8Ux64 _ (Const64 [c]))) (Const16 [d])) && 0 < c && c < 8 && 1<<uint( 8-c)-1 < d -> (ConstBool [1])
(IsInBounds (Rsh8Ux64 _ (Const64 [c])) (Const64 [d])) && 0 < c && c < 8 && 1<<uint( 8-c)-1 < d -> (ConstBool [1])
(IsInBounds (ZeroExt16to64 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 16 && 1<<uint(16-c)-1 < d -> (ConstBool [1])
(IsInBounds (ZeroExt16to32 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 16 && 1<<uint(16-c)-1 < d -> (ConstBool [1])
(IsInBounds (Rsh16Ux64 _ (Const64 [c])) (Const64 [d])) && 0 < c && c < 16 && 1<<uint(16-c)-1 < d -> (ConstBool [1])
(IsInBounds (ZeroExt32to64 (Rsh32Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 32 && 1<<uint(32-c)-1 < d -> (ConstBool [1])
(IsInBounds (Rsh32Ux64 _ (Const64 [c])) (Const64 [d])) && 0 < c && c < 32 && 1<<uint(32-c)-1 < d -> (ConstBool [1])
(IsInBounds (Rsh64Ux64 _ (Const64 [c])) (Const64 [d])) && 0 < c && c < 64 && 1<<uint(64-c)-1 < d -> (ConstBool [1])
(IsSliceInBounds x x) -> (ConstBool [1]) (IsSliceInBounds x x) -> (ConstBool [1])
(IsSliceInBounds (And32 (Const32 [c]) _) (Const32 [d])) && 0 <= c && c <= d -> (ConstBool [1]) (IsSliceInBounds (And32 (Const32 [c]) _) (Const32 [d])) && 0 <= c && c <= d -> (ConstBool [1])

View File

@ -134,7 +134,7 @@ func rewriteValuegeneric(v *Value) bool {
case OpInterCall: case OpInterCall:
return rewriteValuegeneric_OpInterCall_0(v) return rewriteValuegeneric_OpInterCall_0(v)
case OpIsInBounds: case OpIsInBounds:
return rewriteValuegeneric_OpIsInBounds_0(v) || rewriteValuegeneric_OpIsInBounds_10(v) || rewriteValuegeneric_OpIsInBounds_20(v) return rewriteValuegeneric_OpIsInBounds_0(v) || rewriteValuegeneric_OpIsInBounds_10(v) || rewriteValuegeneric_OpIsInBounds_20(v) || rewriteValuegeneric_OpIsInBounds_30(v)
case OpIsNonNil: case OpIsNonNil:
return rewriteValuegeneric_OpIsNonNil_0(v) return rewriteValuegeneric_OpIsNonNil_0(v)
case OpIsSliceInBounds: case OpIsSliceInBounds:
@ -9754,6 +9754,303 @@ func rewriteValuegeneric_OpIsInBounds_20(v *Value) bool {
v.AuxInt = 1 v.AuxInt = 1
return true return true
} }
// match: (IsInBounds (ZeroExt8to64 (Rsh8Ux64 _ (Const64 [c]))) (Const64 [d]))
// cond: 0 < c && c < 8 && 1<<uint( 8-c)-1 < d
// result: (ConstBool [1])
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpZeroExt8to64 {
break
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpRsh8Ux64 {
break
}
_ = v_0_0.Args[1]
v_0_0_1 := v_0_0.Args[1]
if v_0_0_1.Op != OpConst64 {
break
}
c := v_0_0_1.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
d := v_1.AuxInt
if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
return false
}
func rewriteValuegeneric_OpIsInBounds_30(v *Value) bool {
// match: (IsInBounds (ZeroExt8to32 (Rsh8Ux64 _ (Const64 [c]))) (Const32 [d]))
// cond: 0 < c && c < 8 && 1<<uint( 8-c)-1 < d
// result: (ConstBool [1])
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpZeroExt8to32 {
break
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpRsh8Ux64 {
break
}
_ = v_0_0.Args[1]
v_0_0_1 := v_0_0.Args[1]
if v_0_0_1.Op != OpConst64 {
break
}
c := v_0_0_1.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpConst32 {
break
}
d := v_1.AuxInt
if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsInBounds (ZeroExt8to16 (Rsh8Ux64 _ (Const64 [c]))) (Const16 [d]))
// cond: 0 < c && c < 8 && 1<<uint( 8-c)-1 < d
// result: (ConstBool [1])
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpZeroExt8to16 {
break
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpRsh8Ux64 {
break
}
_ = v_0_0.Args[1]
v_0_0_1 := v_0_0.Args[1]
if v_0_0_1.Op != OpConst64 {
break
}
c := v_0_0_1.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpConst16 {
break
}
d := v_1.AuxInt
if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsInBounds (Rsh8Ux64 _ (Const64 [c])) (Const64 [d]))
// cond: 0 < c && c < 8 && 1<<uint( 8-c)-1 < d
// result: (ConstBool [1])
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpRsh8Ux64 {
break
}
_ = v_0.Args[1]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpConst64 {
break
}
c := v_0_1.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
d := v_1.AuxInt
if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsInBounds (ZeroExt16to64 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d]))
// cond: 0 < c && c < 16 && 1<<uint(16-c)-1 < d
// result: (ConstBool [1])
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpZeroExt16to64 {
break
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpRsh16Ux64 {
break
}
_ = v_0_0.Args[1]
v_0_0_1 := v_0_0.Args[1]
if v_0_0_1.Op != OpConst64 {
break
}
c := v_0_0_1.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
d := v_1.AuxInt
if !(0 < c && c < 16 && 1<<uint(16-c)-1 < d) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsInBounds (ZeroExt16to32 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d]))
// cond: 0 < c && c < 16 && 1<<uint(16-c)-1 < d
// result: (ConstBool [1])
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpZeroExt16to32 {
break
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpRsh16Ux64 {
break
}
_ = v_0_0.Args[1]
v_0_0_1 := v_0_0.Args[1]
if v_0_0_1.Op != OpConst64 {
break
}
c := v_0_0_1.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
d := v_1.AuxInt
if !(0 < c && c < 16 && 1<<uint(16-c)-1 < d) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsInBounds (Rsh16Ux64 _ (Const64 [c])) (Const64 [d]))
// cond: 0 < c && c < 16 && 1<<uint(16-c)-1 < d
// result: (ConstBool [1])
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpRsh16Ux64 {
break
}
_ = v_0.Args[1]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpConst64 {
break
}
c := v_0_1.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
d := v_1.AuxInt
if !(0 < c && c < 16 && 1<<uint(16-c)-1 < d) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsInBounds (ZeroExt32to64 (Rsh32Ux64 _ (Const64 [c]))) (Const64 [d]))
// cond: 0 < c && c < 32 && 1<<uint(32-c)-1 < d
// result: (ConstBool [1])
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpZeroExt32to64 {
break
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpRsh32Ux64 {
break
}
_ = v_0_0.Args[1]
v_0_0_1 := v_0_0.Args[1]
if v_0_0_1.Op != OpConst64 {
break
}
c := v_0_0_1.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
d := v_1.AuxInt
if !(0 < c && c < 32 && 1<<uint(32-c)-1 < d) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsInBounds (Rsh32Ux64 _ (Const64 [c])) (Const64 [d]))
// cond: 0 < c && c < 32 && 1<<uint(32-c)-1 < d
// result: (ConstBool [1])
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpRsh32Ux64 {
break
}
_ = v_0.Args[1]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpConst64 {
break
}
c := v_0_1.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
d := v_1.AuxInt
if !(0 < c && c < 32 && 1<<uint(32-c)-1 < d) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
// match: (IsInBounds (Rsh64Ux64 _ (Const64 [c])) (Const64 [d]))
// cond: 0 < c && c < 64 && 1<<uint(64-c)-1 < d
// result: (ConstBool [1])
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpRsh64Ux64 {
break
}
_ = v_0.Args[1]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpConst64 {
break
}
c := v_0_1.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
d := v_1.AuxInt
if !(0 < c && c < 64 && 1<<uint(64-c)-1 < d) {
break
}
v.reset(OpConstBool)
v.AuxInt = 1
return true
}
return false return false
} }
func rewriteValuegeneric_OpIsNonNil_0(v *Value) bool { func rewriteValuegeneric_OpIsNonNil_0(v *Value) bool {