Skip to content

Commit d2e0587

Browse files
wdvxdr1123mvdan
authored andcommitted
cmd/compile: derive relation between x+delta and x in prove
If x+delta cannot overflow/underflow, we can derive: x+delta < x if delta<0 (this CL included) x+delta > x if delta>0 (this CL not included due to a recursive stack overflow) Remove 95 bounds checks during ./make.bat Fixes #51622 Change-Id: I60d9bd84c5d7e81bbf808508afd09be596644f09 Reviewed-on: https://go-review.googlesource.com/c/go/+/406175 Reviewed-by: David Chase <[email protected]> Reviewed-by: Keith Randall <[email protected]> Run-TryBot: Wayne Zuo <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]>
1 parent 6b113c0 commit d2e0587

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

src/cmd/compile/internal/ssa/prove.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -463,15 +463,23 @@ func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) {
463463
if parent.Func.pass.debug > 1 {
464464
parent.Func.Warnl(parent.Pos, "x+d %s w; x:%v %v delta:%v w:%v d:%v", r, x, parent.String(), delta, w.AuxInt, d)
465465
}
466+
underflow := true
467+
if l, has := ft.limits[x.ID]; has && delta < 0 {
468+
if (x.Type.Size() == 8 && l.min >= math.MinInt64-delta) ||
469+
(x.Type.Size() == 4 && l.min >= math.MinInt32-delta) {
470+
underflow = false
471+
}
472+
}
473+
if delta < 0 && !underflow {
474+
// If delta < 0 and x+delta cannot underflow then x > x+delta (that is, x > v)
475+
ft.update(parent, x, v, signed, gt)
476+
}
466477
if !w.isGenericIntConst() {
467478
// If we know that x+delta > w but w is not constant, we can derive:
468-
// if delta < 0 and x > MinInt - delta, then x > w (because x+delta cannot underflow)
479+
// if delta < 0 and x+delta cannot underflow, then x > w
469480
// This is useful for loops with bounds "len(slice)-K" (delta = -K)
470-
if l, has := ft.limits[x.ID]; has && delta < 0 {
471-
if (x.Type.Size() == 8 && l.min >= math.MinInt64-delta) ||
472-
(x.Type.Size() == 4 && l.min >= math.MinInt32-delta) {
473-
ft.update(parent, x, w, signed, r)
474-
}
481+
if delta < 0 && !underflow {
482+
ft.update(parent, x, w, signed, r)
475483
}
476484
} else {
477485
// With w,delta constants, we want to derive: x+delta > w ⇒ x > w-delta

test/prove.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
// +build amd64
21
// errorcheck -0 -d=ssa/prove/debug=1
32

3+
//go:build amd64
4+
// +build amd64
5+
46
// Copyright 2016 The Go Authors. All rights reserved.
57
// Use of this source code is governed by a BSD-style
68
// license that can be found in the LICENSE file.
@@ -793,7 +795,7 @@ func unrollUpExcl(a []int) int {
793795
func unrollUpIncl(a []int) int {
794796
var i, x int
795797
for i = 0; i <= len(a)-2; i += 2 { // ERROR "Induction variable: limits \[0,\?\], increment 2$"
796-
x += a[i]
798+
x += a[i] // ERROR "Proved IsInBounds$"
797799
x += a[i+1]
798800
}
799801
if i == len(a)-1 {
@@ -833,7 +835,7 @@ func unrollDownInclStep(a []int) int {
833835
var i, x int
834836
for i = len(a); i >= 2; i -= 2 { // ERROR "Induction variable: limits \[2,\?\], increment 2$"
835837
x += a[i-1] // ERROR "Proved IsInBounds$"
836-
x += a[i-2]
838+
x += a[i-2] // ERROR "Proved IsInBounds$"
837839
}
838840
if i == 1 {
839841
x += a[i-1]
@@ -1044,6 +1046,13 @@ func and(p []byte) ([]byte, []byte) { // issue #52563
10441046
return blk, rem
10451047
}
10461048

1049+
func issue51622(b []byte) int {
1050+
if len(b) >= 3 && b[len(b)-3] == '#' { // ERROR "Proved IsInBounds$"
1051+
return len(b)
1052+
}
1053+
return 0
1054+
}
1055+
10471056
//go:noinline
10481057
func useInt(a int) {
10491058
}

0 commit comments

Comments
 (0)