1
0
mirror of https://github.com/golang/go synced 2024-11-26 12:27:57 -07:00

cmd/compile: handle non-negatives in prove

Handle this case:
if 0 <= i && i < len(a) {
        use a[i]
}

Shaves about 5k from pkg/tools/linux_amd64/*.

Change-Id: I6675ff49aa306b0d241b074c5738e448204cd981
Reviewed-on: https://go-review.googlesource.com/21431
Run-TryBot: Alexandru Moșoi <alexandru@mosoi.ro>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Alexandru Moșoi 2016-04-02 10:29:11 +02:00 committed by Alexandru Moșoi
parent 72c1180852
commit 27ebc84716
2 changed files with 32 additions and 5 deletions

View File

@ -296,6 +296,15 @@ func (ft *factsTable) update(v, w *Value, d domain, r relation) {
} }
} }
// isNonNegative returns true if v is known to be non-negative.
func (ft *factsTable) isNonNegative(v *Value) bool {
if isNonNegative(v) {
return true
}
l, has := ft.limits[v.ID]
return has && (l.min >= 0 || l.umax <= math.MaxInt64)
}
// checkpoint saves the current state of known relations. // checkpoint saves the current state of known relations.
// Called when descending on a branch. // Called when descending on a branch.
func (ft *factsTable) checkpoint() { func (ft *factsTable) checkpoint() {
@ -608,8 +617,7 @@ func simplifyBlock(ft *factsTable, b *Block) branch {
// to the upper bound than this is proven. Most useful in cases such as: // to the upper bound than this is proven. Most useful in cases such as:
// if len(a) <= 1 { return } // if len(a) <= 1 { return }
// do something with a[1] // do something with a[1]
// TODO: use constant bounds to do isNonNegative. if (c.Op == OpIsInBounds || c.Op == OpIsSliceInBounds) && ft.isNonNegative(c.Args[0]) {
if (c.Op == OpIsInBounds || c.Op == OpIsSliceInBounds) && isNonNegative(c.Args[0]) {
m := ft.get(a0, a1, signed) m := ft.get(a0, a1, signed)
if m != 0 && tr.r&m == m { if m != 0 && tr.r&m == m {
if b.Func.pass.debug > 0 { if b.Func.pass.debug > 0 {

View File

@ -29,11 +29,30 @@ func f1(a []int) int {
} }
func f1b(a []int, i int, j uint) int { func f1b(a []int, i int, j uint) int {
if i >= 0 && i < len(a) { // TODO: handle this case if i >= 0 && i < len(a) {
return a[i] return a[i] // ERROR "Proved non-negative bounds IsInBounds$"
}
if i >= 10 && i < len(a) {
return a[i] // ERROR "Proved non-negative bounds IsInBounds$"
}
if i >= 10 && i < len(a) {
return a[i] // ERROR "Proved non-negative bounds IsInBounds$"
}
if i >= 10 && i < len(a) { // todo: handle this case
return a[i-10]
} }
if j < uint(len(a)) { if j < uint(len(a)) {
return a[j] // ERROR "Proved IsInBounds" return a[j] // ERROR "Proved IsInBounds$"
}
return 0
}
func f1c(a []int, i int64) int {
c := uint64(math.MaxInt64 + 10) // overflows int
d := int64(c)
if i >= d && i < int64(len(a)) {
// d overflows, should not be handled.
return a[i]
} }
return 0 return 0
} }